Eu moro e trabalho perto de uma instalação da Microsoft. Como tal, muitos de nossos funcionários atuais são ex-funcionários da Microsoft com experiência em SQL Server. O SQL Server permite criar uma tabela com uma coluna IDENTITY. O Oracle 12c agora permite que você faça o mesmo. Isso deve ajudar aqueles que estão fazendo a transição do SQL Server para o Oracle. Ele também permite que uma empresa transfira mais facilmente um aplicativo do SQL Server, ou qualquer outro banco de dados que permita a coluna IDENTITY, para o Oracle.
Primeiro vou criar uma tabela com a coluna IDENTITY e preenchê-la com algumas linhas de dados.
SQL> cria tabela test_tab (2 id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY, 3 val VARCHAR2(20));Table created.SQL> insere valores test_tab (val) ('minha primeira linha');1 linha created.SQL> insira em test_tab (val) valores ('minha segunda linha');1 linha criada.SQL> commit;Commit completo.
Observe que não inseri nenhum valor na coluna ID. Agora vamos consultar a tabela.
SQL> selecione * from test_tab;ID VAL---------- --------------------1 minha primeira linha2 minha segunda linha
Como você pode ver, meus valores de ID foram adicionados como você poderia esperar. Na minha criação de tabela, defini esta coluna IDENTITY com: GENERATED BY DEFAULT ON NULL
A cláusula BY DEFAULT significa que o Oracle atribuirá automaticamente o próximo valor na sequência se você o omitir em sua instrução INSERT. Se você incluí-lo, o Oracle usará o valor especificado. Considere isto:
SQL> insira em valores test_tab (4,'ID especificado=4');1 linha criada.SQL> commit;Commit complete.SQL> selecione * from test_tab; ID VAL---------- -------------------- 1 minha primeira linha 2 minha segunda linha 4 ID especificado=4
Como você pode ver, porque eu declarei explicitamente ID=4 e o Oracle deixou esse valor passar. O que acontece quando tento inserir o próximo valor, que deve ser 3?
SQL> inserir valores test_tab (val) ('minha linha após ID=4');1 linha criada.SQL> commit;Commit complete.SQL> selecione * from test_tab; ID VAL---------- -------------------- 1 minha primeira linha 2 minha segunda linha 4 ID especificado=4 3 minha linha após o ID =4O acima funcionou como eu esperava. O próximo valor de ID disponível foi usado. Mas a próxima inserção usará '4' ou '5'?SQL> insira nos valores test_tab (val) ('minha quinta linha');1 linha criada.SQL> commit;Commit complete.SQL> selecione * de teste_tab; ID VAL---------- -------------------- 1 minha primeira linha 2 minha segunda linha 4 ID especificado=4 3 minha linha após o ID =4 4 minha quinta linhaUh-oh! O valor duplicado foi permitido. Eu teria esperado que uma restrição de Chave Primária fosse criada para impor o conceito de um valor de “identidade”, mas isso não acontece. Quais restrições existem?SQL> selecione constraint_name,constraint_type,table_name,search_condition de user_constraints;CONSTRAINT_NAME C TABLE_NAME-------------------------- --- - ------------------------------SEARCH_CONDITION--------------- -------------------------------------------------- ---------------SYS_C004978 C TEST_TAB"ID" NÃO É NULOPortanto, a única restrição é uma restrição de verificação NOT NULL. Agora vamos remover a última linha e adicionar uma restrição PK.SQL> delete from test_tab where val='my five row';1 row delete.SQL> commit;Commit complete.SQL> alter table test_tab add constraint test_tab_pk chave primária (id);Tabela alterada.Agora vou me certificar de que tenho alguns dados para testar.SQL> insira nos valores test_tab (val) ('after pk constraint'); 1 linha criada.SQL> insira nos valores test_tab (id,val) ( 6,'definir explicitamente id=6');1 linha criada.SQL> commit;Commit complete.SQL> select * from test_tab; ID VAL---------- -------------------- 1 minha primeira linha 2 minha segunda linha 4 ID especificado=4 3 minha linha após o ID =4 5 após a restrição de pk 6 id definido explicitamente=66 linhas selecionadas.Então eu adicionei explicitamente ID=6. Se for como quando eu adicionei explicitamente ID=4, minha próxima inserção tentará usar ID=6 e com a restrição PK em vigor, uma exceção será lançada.SQL> insert into test_tab (val) values (' after ID=6'); insira nos valores test_tab (val) ('after ID=6')*ERROR na linha 1:ORA-00001:restrição exclusiva (PEASLAND.TEST_TAB_PK) violadaPortanto, a moral da história é que, se você usar ON DEFAULT, esteja preparado para lidar com colisões de valores de identidade. O padrão é SEMPRE em vez de ON DEFAULT. Com ALWAYS, o Oracle sempre usará o gerador de número de sequência. Se você tentar especificar um valor de id, ocorrerá uma exceção.SQL> create table test_tab2(id number gerado sempre como identidade, val varchar2(20));Table created.SQL> insert into test_tab2(id,val) values (1,'first row');insert into test_tab2(id,val) values (1,'first row') *ERRO na linha 1:ORA-32795:não é possível inserir em uma coluna sempre de identidade geradaA visualização *_TAB_COLUMNS pode mostrar quais colunas em uma tabela são colunas IDENTITY.SQL> selecione column_name,identity_column de user_tab_columns onde table_name='TEST_TAB';COLUMN_NAME IDE-------------- - ---ID YESVAL NÃOSe você usar a coluna IDENTITY em suas tabelas, tenha o cuidado de testar para garantir que ela funcione corretamente para seu aplicativo. Fiquei surpreso que uma restrição PK ou UNIQUE não foi incluída automaticamente, o que me permitiu adicionar um valor duplicado.