Der Versuch, eine Sequenz in Oracle zu erstellen, die mit dem Maximalwert aus einer bestimmten Tabelle beginnt. Warum funktioniert das nicht?
CREATE SEQUENCE transaction_sequence
MINVALUE 0
START WITH (SELECT MAX(trans_seq_no)
FROM TRANSACTION_LOG)
INCREMENT BY 1
CACHE 20;
sie möchten vielleicht mit max(trans_seq_no) + 1.
beginnen
sehen:
SQL> create table my_numbers(my_number number not null primary key);
Table created.
SQL> insert into my_numbers(select rownum from user_objects);
260 rows created.
SQL> select max(my_number) from my_numbers;
MAX(MY_NUMBER)
--------------
260
SQL> create sequence my_number_sn start with 260;
Sequence created.
SQL> insert into my_numbers(my_number) values (my_number_sn.NEXTVAL);
insert into my_numbers(my_number) values (my_number_sn.NEXTVAL)
*
ERROR at line 1:
ORA-00001: unique constraint (NEIL.SYS_C00102439) violated
Wenn Sie eine Sequenz mit einer Nummer erstellen, müssen Sie daran denken, dass Oracle bei der ersten Auswahl der Sequenz den von Ihnen zugewiesenen Anfangswert zurückgibt.
SQL> drop sequence my_number_sn;
Sequence dropped.
SQL> create sequence my_number_sn start with 261;
Sequence created.
SQL> insert into my_numbers(my_number) values (my_number_sn.NEXTVAL);
1 row created.
Wenn Sie versuchen, das "lückenlose" Ding zu tun, rate ich Ihnen dringend dazu
Wenn Sie PL/SQL verwenden können, versuchen Sie (EDIT: Enthält den Vorschlag von Neil zu xlnt, um mit dem nächst höheren Wert zu beginnen):
SELECT 'CREATE SEQUENCE transaction_sequence MINVALUE 0 START WITH '||MAX(trans_seq_no)+1||' INCREMENT BY 1 CACHE 20'
INTO v_sql
FROM transaction_log;
EXECUTE IMMEDIATE v_sql;
Ein weiterer zu berücksichtigender Punkt: Wenn Sie den Parameter CACHE auf 20 setzen, besteht das Risiko, dass Sie bis zu 19 Werte in Ihrer Sequenz verlieren, wenn die Datenbank ausfällt. CACHEd-Werte gehen bei Datenbankneustarts verloren. Wenn Sie die Sequenz nicht sehr oft treffen oder sich nicht so sehr auf Lücken konzentrieren, würde ich sie auf 1 setzen.
Ein letzter Schritt: Die Werte, die Sie für CACHE und INCREMENT BY angegeben haben, sind die Standardwerte. Sie können sie ausschalten und das gleiche Ergebnis erzielen.
Hier habe ich mein Beispiel, das gut funktioniert:
declare
ex number;
begin
select MAX(MAX_FK_ID) + 1 into ex from TABLE;
If ex > 0 then
begin
execute immediate 'DROP SEQUENCE SQ_NAME';
exception when others then
null;
end;
execute immediate 'CREATE SEQUENCE SQ_NAME INCREMENT BY 1 START WITH ' || ex || ' NOCYCLE CACHE 20 NOORDER';
end if;
end;
Sie können keine Unterauswahl in einer CREATE SEQUENCE
-Anweisung verwenden. Sie müssen den Wert vorher auswählen.
In der Mitte ist der MAX-Wert nur der Höchstwert der zugesagten Werte. Möglicherweise wird 1234 zurückgegeben, und Sie müssen möglicherweise berücksichtigen, dass jemand bereits 1235 eingefügt hat, jedoch noch nicht festgeschrieben hat.
Basierend auf Ivan Laharnar mit weniger Code und einfacher:
declare
lastSeq number;
begin
SELECT MAX(ID) + 1 INTO lastSeq FROM <TABLE_NAME>;
if lastSeq IS NULL then lastSeq := 1; end if;
execute immediate 'CREATE SEQUENCE <SEQUENCE_NAME> INCREMENT BY 1 START WITH ' || lastSeq || ' MAXVALUE 999999999 MINVALUE 1 NOCACHE';
end;
DECLARE
v_max NUMBER;
BEGIN
SELECT (NVL (MAX (<COLUMN_NAME>), 0) + 1) INTO v_max FROM <TABLE_NAME>;
EXECUTE IMMEDIATE 'CREATE SEQUENCE <SEQUENCE_NAME> INCREMENT BY 1 START WITH ' || v_max || ' NOCYCLE CACHE 20 NOORDER';
END;