Ich habe eine Oracle-Sequenz wie folgt definiert:
CREATE SEQUENCE "DALLAS"."X_SEQ"
MINVALUE 0
MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 0 NOCACHE NOORDER NOCYCLE ;
Es wird in einer gespeicherten Prozedur verwendet, um einen Datensatz einzufügen:
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;
Gelegentlich gibt diese Prozedur einen Fehler zurück, wenn sie aus dem Anwendungscode ausgeführt wird.
ORA-01400: cannot insert NULL into ("DALLAS"."X"."THE_ID")
ORA-06512: at "DALLAS.X_PKG", line 40
ORA-06512: at line 1
Details, die relevant sein können oder nicht:
- Oracle Database 11g Enterprise Edition Version 11.2.0.1.0 - 64-Bit-Produktion
- Die Prozedur wird über Microsoft.Practices.EnterpriseLibrary - Data.Oracle.OracleDatabase.ExecuteReader (Befehl DbCommand) ausgeführt.
- Die Anwendung schließt den Aufruf nicht in eine explizite Transaktion ein.
- Der Einsatz fällt zeitweise aus - weniger als 1%
Unter welchen Umständen könnte x_seq.nextval
null sein?
v_id
wird nur in der Sequenzauswahl, dem Einfügen und dem letzten Cursor referenziert. Unser nächster Schritt war das Hinzufügen des Debugging-Codes. Wir müssen möglicherweise auf Ergebnisse warten, da dies nur in der Produktion und sehr selten vorkommt. Es gibt einen Trigger, der in eine Prüftabelle eingefügt wird. Ich habe es ohne rauchende Waffe durchgekämmt. Das Problem tritt gelegentlich auch in anderen Tabellen ohne Trigger auf. Vielen Dank für Ihren Blick.Antworten:
Ich bin mir ziemlich sicher, dass dies ein Artefakt Ihres Codes oder des von Ihnen verwendeten .net-Treibers sein wird. Ich habe eine schnelle Demo für Sie mit reinem SQL - PL / SQL erstellt und erhalte nie einen verlorenen Sequenzwert. Übrigens ist der von Ihnen verwendete Ref-Cursor wahrscheinlich unnötig und beeinträchtigt wahrscheinlich die Leistung und Lesbarkeit des Codes. Meine Demo enthält eine insert_record2-Prozedur, die auf meinem Laptop durchweg über 10% schneller ausgeführt wird - in etwa 26 Sekunden gegenüber 36 für die Ref-Cursor-Version. Ich denke zumindest auch, dass es leichter zu verstehen ist. Sie könnten natürlich eine geänderte Version für Ihre Testdatenbank mit Audit-Trigger ausführen.
quelle
:new.the_id
ist unberührt. Ich verstehe, dass meine Frage ein langer Schuss ist. Es ist resistent gegen mein Google-Fu und hat mehrere Leute, die sich hier am Kopf kratzen. Ich dachte nur, jemand könnte das Symptom (und die Behandlung) erkennen, wenn genügend Augäpfel vorhanden sind. Vielen Dank für Ihren Blick.Versuchen Sie einen Testfall. Erstellen Sie eine Dummy-Tabelle und fügen Sie 100.000 Datensätze mit Ihrer Sequenz aus der Datenbank ein. Ich wette, Sie werden keine Probleme haben. Versuchen Sie als Nächstes, dasselbe aus Ihrer Anwendung einzufügen.
Könnte dies durch andere Probleme verursacht werden, z. B. durch eine Nichtübereinstimmung des Oracle-Clients?
Eine andere Lösung, die das Problem beheben würde, aber kein Problem, besteht darin, der Tabelle einen Auslöser hinzuzufügen.
Vor dem Einfügen in eine Tabelle in Dallas.X IF: the_id ist null THEN SELECT x_seq.nextval INTO: the_id FROM dual; END IF;
quelle
Ich habe noch keine Berechtigung, Kommentare abzugeben. Schreiben Sie dies als Antwort: Da Sie die Oracle-Version> = 11.1 verwenden, die Sequenzen in PL / SQL-Ausdrücken anstelle von SQL zulässt , versuchen Sie Folgendes:
An Stelle von:
Oder, obwohl ich bei der Verwendung von ".currval" Zweifel / Fallstricke gehört habe, die separate Zuweisung von v_id weglassen und nur diesen Code verwenden?:
Entschuldigung, ich habe jetzt keine 11g-Instanz zur Hand, um dies auszuprobieren.
quelle
select into...
in 11 so viel wie in 9i und 10g. Der einzige Vorteil von 11+ besteht darin, dass Sie explizit darauf verweisen können, wie Sie bereits betont haben.