Eu tenho uma sequência Oracle definida assim:
CREATE SEQUENCE "DALLAS"."X_SEQ"
MINVALUE 0
MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 0 NOCACHE NOORDER NOCYCLE ;
É usado em um procedimento armazenado para inserir um registro:
PROCEDURE Insert_Record
(p_name IN VARCHAR2,
p_userid IN INTEGER,
cur_out OUT TYPES_PKG.RefCursor)
IS
v_id NUMBER := 0;
BEGIN
-- Get id value from sequence
SELECT x_seq.nextval
INTO v_id
FROM dual;
-- Line below is X_PKG line 40
INSERT INTO X
(the_id,
name,
update_userid)
VALUES
(v_id,
p_name,
p_userid);
-- Return new id
OPEN cur_out FOR
SELECT v_id the_id
FROM dual;
END;
Ocasionalmente, esse procedimento retorna um erro quando executado a partir do código do aplicativo.
ORA-01400: cannot insert NULL into ("DALLAS"."X"."THE_ID")
ORA-06512: at "DALLAS.X_PKG", line 40
ORA-06512: at line 1
Detalhes que podem ou não ser relevantes:
- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Produção de 64 bits
- O procedimento é executado via Microsoft.Practices.EnterpriseLibrary - Data.Oracle.OracleDatabase.ExecuteReader (comando DbCommand)
- O aplicativo não quebra a chamada em uma transação explícita.
- A inserção falha intermitentemente - menos de 1%
Em que circunstâncias poderia x_seq.nextval
ser nulo?
v_id
é referenciado apenas na seleção de sequência, na inserção e no cursor final. Nosso próximo passo foi adicionar o código de depuração. Podemos ter que esperar pelos resultados, pois isso só acontece na produção e com pouca frequência. Há um gatilho que é inserido em uma tabela de auditoria. Eu penteei com ele sem arma de fumar. O problema também ocorre ocasionalmente em outras tabelas sem gatilhos. Obrigado por dar uma olhada.Respostas:
Tenho certeza de que isso acabará sendo um artefato do seu código ou o driver .net que você está usando. Fiz uma demonstração rápida para você usando SQL-PL / SQL puro e nunca obtive um valor de sequência perdido. Aliás, o cursor ref que você está usando provavelmente é desnecessário e provavelmente afeta o desempenho e a legibilidade do código - minha demonstração inclui um procedimento insert_record2 que executa consistentemente mais de 10% mais rápido - cerca de 26s no meu laptop vs 36 para a versão do cursor ref. Eu pelo menos também acho que é mais fácil de entender. Obviamente, você pode executar uma versão modificada no banco de dados de teste, completo com o acionador de auditoria.
fonte
:new.the_id
está intocado. Entendo que minha pergunta é um tiro no escuro. É resistente ao meu google-fu e tem várias pessoas coçando a cabeça aqui. Eu apenas imaginei que alguém pudesse reconhecer o sintoma (e o tratamento), com olhos suficientes. Obrigado por dar uma olhada.Tente fazer um caso de teste. Faça uma tabela fictícia e insira 100.000 registros usando sua sequência do banco de dados. Aposto que você não terá problemas. Em seguida, tente inserir a mesma coisa do seu aplicativo.
Isso pode ser causado por outros problemas, como uma incompatibilidade de cliente Oracle?
Outra solução que resolveria o problema, mas não o problema, seria adicionar um gatilho à tabela.
Antes de inserir na tabela no Dallas.X SE: o_id é nulo ENTÃO SELECIONE x_seq.nextval INTO: o_id FROM dual; FIM SE;
fonte
Ainda não tenho privilégios para fazer comentários, portanto, escreva isso como resposta: Como você está usando a versão Oracle> = 11.1, que permite sequências nas expressões PL / SQL em vez de no SQL, tente o seguinte:
Em vez disso:
Ou, apesar de ter ouvido dúvidas / armadilhas ao usar ".currval", talvez omita a atribuição separada de v_id e use apenas este código ?:
Desculpe, não tenho uma instância 11g à mão agora para tentar isso.
fonte
select into...
em 11 quanto em 9i e 10g. O único benefício do 11+ é poder referenciá-lo explicitamente, como você indicou.