У меня есть последовательность Oracle, определенная так:
CREATE SEQUENCE "DALLAS"."X_SEQ"
MINVALUE 0
MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 0 NOCACHE NOORDER NOCYCLE ;
Он используется в хранимой процедуре для вставки записи:
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;
Иногда эта процедура возвращает ошибку при выполнении из кода приложения.
ORA-01400: cannot insert NULL into ("DALLAS"."X"."THE_ID")
ORA-06512: at "DALLAS.X_PKG", line 40
ORA-06512: at line 1
Подробности, которые могут иметь или не иметь отношение к делу:
- Oracle Database 11g Enterprise Edition, выпуск 11.2.0.1.0 - 64-разрядная версия
- Процедура выполняется через Microsoft.Practices.EnterpriseLibrary - Data.Oracle.OracleDatabase.ExecuteReader (команда DbCommand)
- Приложение не переносит вызов в явную транзакцию.
- Периодически происходит сбой вставки - менее 1%
При каких обстоятельствах может x_seq.nextval
быть нулевым?
v_id
упоминается только в последовательности выбора, вставке и последнем курсоре. Нашим следующим шагом было добавление кода отладки. Возможно, нам придется ждать результатов, так как это происходит только в производстве и очень редко. Существует триггер, который вставляется в таблицу аудита. Я прочесал это без курящего пистолета. Проблема также иногда возникает в других таблицах без триггеров. Спасибо, что посмотрели.Ответы:
Я почти уверен, что это станет артефактом вашего кода или используемого вами драйвера .net. Я подготовил для вас короткую демонстрацию, используя чистый SQL - PL / SQL, и никогда не получал значение потерянной последовательности. Между прочим, используемый вами ref-курсор, вероятно, не нужен и, вероятно, влияет на производительность и читаемость кода - моя демонстрация включает процедуру insert_record2, которая последовательно выполняется более чем на 10% быстрее - примерно на 26 с на моем ноутбуке против 36 для версии ref-курсора. Я по крайней мере также думаю, что это легче понять. Очевидно, что вы можете запустить модифицированную версию для своей тестовой базы данных вместе с триггером аудита.
источник
:new.the_id
нетронутым. Я понимаю, что мой вопрос - это длинный выстрел. Он устойчив к моему гугл-фу, и здесь несколько человек почесывают голову. Я просто подумал, что кто-то может распознать симптом (и лечение) при достаточном количестве глазных яблок. Спасибо, что посмотрели.Попробуйте сделать тестовый пример. Составьте фиктивную таблицу и вставьте 100 000 записей, используя вашу последовательность из базы данных. Держу пари, у тебя не будет проблем. Затем попробуйте вставить то же самое из вашего приложения.
Может ли это быть вызвано другими проблемами, такими как несоответствие клиента Oracle?
Другое решение, которое решило бы проблему, но не проблему, - добавить триггер на стол.
Перед вставкой в таблицу в Dallas.X ЕСЛИ: the_id имеет значение null, ТО ВЫБРАТЬ x_seq.nextval INTO: the_id FROM dual; END IF;
источник
У меня пока нет привилегий комментировать, поэтому пишу это как ответ: так как вы используете версию Oracle> = 11.1, которая позволяет использовать последовательности в выражениях PL / SQL вместо SQL, попробуйте следующее:
Вместо этого:
Или, хотя я слышал сомнения / подводные камни при использовании ".currval", возможно, пропустите отдельное назначение v_id и используйте только этот код ?:
Извините, у меня сейчас нет экземпляра 11g, чтобы попробовать это.
источник
select into...
в 11 столько же, сколько в 9i и 10g. Единственное преимущество 11+ - это возможность явно ссылаться на него, как вы указали.