Como posso descartar uma restrição "não nula" no Oracle quando não sei o nome da restrição?

85

Eu tenho um banco de dados que tem uma restrição NOT NULL em um campo e desejo remover essa restrição. O fator complicador é que essa restrição tem um nome definido pelo sistema e o nome dessa restrição difere entre o servidor de produção, o servidor de integração e os vários bancos de dados do desenvolvedor. Nosso processo atual é fazer o check-in dos scripts de alteração e uma tarefa automatizada executa as consultas apropriadas por meio do sqlplus no banco de dados de destino, então eu preferiria uma solução que pudesse ser enviada diretamente para o sqlplus.

Em meu próprio banco de dados, o SQL para eliminar isso seria:

alter table MYTABLE drop constraint SYS_C0044566

Posso ver a restrição ao consultar a all_constraintsvisualização:

select * from all_constraints where table_name = 'MYTABLE'

mas não tenho certeza de como trabalhar com o SEARCH_CONDITION's LONGtipo de dados ou a melhor forma de eliminar de forma dinâmica a restrição olhou-up, mesmo depois de eu sei o seu nome.

Portanto, como posso criar um script de mudança que possa eliminar essa restrição com base no que ela é, em vez de em seu nome?


EDIT: @A resposta de Allan é boa, mas estou preocupado (em minha falta de experiência em Oracle) que pode não ser universalmente verdadeiro que qualquer restrição que possa ter um nome gerado pelo sistema terá associado a ele uma maneira de remover o restrição sem precisar saber seu nome. É verdade que sempre haverá uma maneira de evitar ter que saber o nome de uma restrição nomeada pelo sistema ao eliminar logicamente essa restrição?

Chris Farmer
fonte
3
Apenas para satisfazer sua curiosidade: a restrição NOT NULL é o único tipo de restrição no Oracle que você pode remover sem precisar saber o nome da restrição. Todos os outros tipos de restrição, você precisa saber o nome da restrição.
Jeffrey Kemp

Respostas:

170
alter table MYTABLE modify (MYCOLUMN null);

No Oracle, as restrições não nulas são criadas automaticamente quando não nulo é especificado para uma coluna. Da mesma forma, eles são eliminados automaticamente quando a coluna é alterada para permitir nulos.

Esclarecendo a questão revisada : Esta solução se aplica apenas a restrições criadas para colunas "não nulas". Se você especificar "Chave primária" ou uma restrição de verificação na definição da coluna sem nomeá-la, você terminará com um nome gerado pelo sistema para a restrição (e o índice, para a chave primária). Nesses casos, você precisa saber o nome para descartá-lo. O melhor conselho é evitar o cenário, certificando-se de especificar um nome para todas as restrições, exceto "não nulo". Se você se encontrar na situação em que precisa descartar uma dessas restrições genericamente, provavelmente precisará recorrer à PL / SQL e às tabelas de definição de dados.

Allan
fonte
Isso parece bom demais para ser verdade, mas definitivamente trata do meu caso atual e é muito simples! Há algum caso no oracle onde o nome da restrição pode ser gerado pelo sistema, mas o sql não pode ser escrito para evitar o nome da restrição como esse?
Chris Farmer
1
Obrigado ... acontece que as not nullrestrições são as únicas com nome de sistema em meu esquema que provavelmente me afetarão dessa forma.
Chris Farmer
16

Experimentar:

alter table <your table> modify <column name> null;
vasanth
fonte
1

Apenas lembre-se, se o campo que você deseja tornar nulo fizer parte de uma chave primária, você não pode. As chaves primárias não podem ter campos nulos.

Mary C
fonte
1

Para descobrir quaisquer restrições usadas, use o código abaixo:

-- Set the long data type for display purposes to 500000.

SET LONG 500000

-- Define a session scope variable.

VARIABLE output CLOB

-- Query the table definition through the <code>DBMS_METADATA</code> package.

SELECT dbms_metadata.get_ddl('TABLE','[Table Described]') INTO :output FROM dual;

Isso mostra essencialmente uma instrução de criação de como a tabela referenciada é feita. Ao saber como a tabela é criada, você pode ver todas as restrições da tabela.

Resposta retirada do blog de Michael McLaughlin: http://michaelmclaughlin.info/db1/lesson-5-querying-data/lab-5-querying-data/ De sua classe Database Design I.

FrostyDog
fonte
0

Eu estava enfrentando o mesmo problema ao tentar contornar uma restrição de verificação personalizada que precisava atualizar para permitir valores diferentes. O problema é que ALL_CONSTRAINTS não tem uma maneira de dizer a qual coluna as restrições são aplicadas. A forma como consegui fazer isso é consultando ALL_CONS_COLUMNS, em seguida, descartando cada uma das restrições por seu nome e recriá-lo.

selecione constraint_name de all_cons_columns onde table_name = [TABLE_NAME] e column_name = [COLUMN_NAME];

CaduMaciel
fonte
0

Algo assim aconteceu comigo quando fiz cópias de estruturas para tabelas temporárias, então removi o não nulo.

DECLARE
   CURSOR cur_temp_not_null IS
        SELECT table_name, constraint_name  FROM all_constraints WHERE table_name LIKE 'TEMP_%' AND  owner='myUSUARIO';

   V_sql VARCHAR2(200); 

BEGIN
  FOR c_not_null IN cur_temp_not_null
   LOOP
     v_sql :='ALTER TABLE ' || c_not_null.table_name || ' DROP CONSTRAINT '|| c_not_null.constraint_name;
     EXECUTE IMMEDIATE  v_sql;     
  END LOOP;
END;
Francisco
fonte
Stack Overflow é um site apenas em inglês. No entanto, há Stack Overflow en español . Veja minha edição.
help-info.de
0

Se a restrição na coluna STATUS foi criada sem um nome durante a criação de uma tabela, o Oracle atribuirá um nome aleatório para ela. Infelizmente, não podemos modificar a restrição diretamente.

Etapas envolvidas para eliminar a restrição sem nome vinculada à coluna STATUS

  1. Duplique o campo STATUS em um novo campo STATUS2
  2. Defina as restrições CHECK em STATUS2
  3. Migrar dados de STATUS para STATUS2
  4. Colocar coluna STATUS
  5. Renomear STATUS2 para STATUS

    ALTER TABLE MY_TABLE ADD STATUS2 NVARCHAR2(10) DEFAULT 'OPEN'; ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_CHECK_STATUS CHECK (STATUS2 IN ('OPEN', 'CLOSED')); UPDATE MY_TABLE SET STATUS2 = STATUS; ALTER TABLE MY_TABLE DROP COLUMN STATUS; ALTER TABLE MY_TABLE RENAME COLUMN STATUS2 TO STATUS;

Lukasz Ciesluk
fonte