it-swarm.com.de

Die beste Möglichkeit, eine Oracle-Sequenz auf den nächsten Wert in einer vorhandenen Spalte zurückzusetzen?

Aus irgendeinem Grund haben Personen in der Vergangenheit Daten ohne Verwendung von sequence.NEXTVAL eingefügt. Wenn ich sequence.NEXTVAL verwende, um eine Tabelle zu füllen, erhalte ich eine PK-Verletzung, da diese Nummer bereits in der Tabelle verwendet wird.

Wie kann ich den nächsten Wert aktualisieren, damit er verwendet werden kann? Im Moment füge ich nur immer wieder ein, bis es erfolgreich ist (INSERT INTO tbl (pk) VALUES (sequence.NEXTVAL)), und das synchronisiert den nächsten Wert.

41
Cade Roux

Mit diesen beiden Verfahren kann ich die Sequenz zurücksetzen und die Sequenz basierend auf Daten in einer Tabelle zurücksetzen (entschuldigen Sie die von diesem Client verwendeten Codierungskonventionen):

CREATE OR REPLACE PROCEDURE SET_SEQ_TO(p_name IN VARCHAR2, p_val IN NUMBER)
AS
   l_num   NUMBER;
BEGIN
   EXECUTE IMMEDIATE 'select ' || p_name || '.nextval from dual' INTO l_num;

   -- Added check for 0 to avoid "ORA-04002: INCREMENT must be a non-zero integer"
   IF (p_val - l_num - 1) != 0
   THEN
      EXECUTE IMMEDIATE 'alter sequence ' || p_name || ' increment by ' || (p_val - l_num - 1) || ' minvalue 0';
   END IF;

   EXECUTE IMMEDIATE 'select ' || p_name || '.nextval from dual' INTO l_num;

   EXECUTE IMMEDIATE 'alter sequence ' || p_name || ' increment by 1 ';

   DBMS_OUTPUT.put_line('Sequence ' || p_name || ' is now at ' || p_val);
END;

CREATE OR REPLACE PROCEDURE SET_SEQ_TO_DATA(seq_name IN VARCHAR2, table_name IN VARCHAR2, col_name IN VARCHAR2)
AS
   nextnum   NUMBER;
BEGIN
   EXECUTE IMMEDIATE 'SELECT MAX(' || col_name || ') + 1 AS n FROM ' || table_name INTO nextnum;

   SET_SEQ_TO(seq_name, nextnum);
END;
16
Cade Roux

Sie können die Cachegröße vorübergehend erhöhen und einen Dummy auswählen und dann die Cachegröße auf 1 zurücksetzen. Zum Beispiel

ALTER SEQUENCE mysequence INCREMENT BY 100;

select mysequence.nextval from dual;

ALTER SEQUENCE mysequence INCREMENT BY 1;
78
Basanth Roy

Wenn Sie davon ausgehen können, dass sich die Tabelle in einem stabilen Zustand befindet, in dem keine neuen Einfügungen vorgenommen werden, sollten Sie dies tun (ungetestet):

DECLARE
  last_used  NUMBER;
  curr_seq   NUMBER;
BEGIN
  SELECT MAX(pk_val) INTO last_used FROM your_table;

  LOOP
    SELECT your_seq.NEXTVAL INTO curr_seq FROM dual;
    IF curr_seq >= last_used THEN EXIT;
    END IF;
  END LOOP;
END;

Auf diese Weise können Sie die Sequenz wieder mit der Tabelle synchronisieren, ohne die Sequenz löschen/neu erstellen/erneut erteilen zu müssen. Es wird auch keine DDL verwendet, sodass keine impliziten Commits ausgeführt werden. Natürlich müssen Sie die Leute jagen und schlagen, die darauf bestehen, die Sequenz nicht zum Auffüllen der Spalte zu verwenden ...

12
DCookie

In meinem Fall habe ich eine Sequenz mit dem Namen PS_LOG_SEQ, Die einen LAST_NUMBER = 3920 Hatte.

Ich habe dann einige Daten von PROD auf meinen lokalen Rechner importiert und in die Tabelle PS_LOG Eingefügt. Produktionsdaten hatten mehr als 20000 Zeilen mit der neuesten LOG_ID (Primärschlüssel) von 20070. Nach dem Import habe ich versucht, neue Zeilen in diese Tabelle einzufügen, aber beim Speichern habe ich eine Ausnahme wie diese erhalten:

ORA-00001: unique constraint (LOG.PS_LOG_PK) violated

Dies hat sicherlich mit der Sequenz PS_LOG_SEQ Zu tun, die der Tabelle PS_LOG Zugeordnet ist. Der LAST_NUMBER Kollidierte mit Daten, die ich importiert hatte und die bereits den nächsten ID-Wert aus dem PS_LOG_SEQ Verwendet hatten.

Um das zu lösen, habe ich diesen Befehl verwendet, um die Sequenz auf die neueste\max(LOG_ID) + 1 zu aktualisieren:

alter sequence PS_LOG_SEQ restart start with 20071;

Dieser Befehl setzte den Wert LAST_NUMBER Zurück und ich konnte dann neue Zeilen in die Tabelle einfügen. Keine Kollision mehr. :)

Hinweis: Dieser alter sequence Befehl ist neu in Oracle 12c.

10

Mit Oracle 10.2g:

select  level, sequence.NEXTVAL
from  dual 
connect by level <= (select max(pk) from tbl);

setzt den aktuellen Sequenzwert auf das Maximum (pk) Ihrer Tabelle (d. h. der nächste Aufruf von NEXTVAL liefert das richtige Ergebnis). Wenn Sie Toad verwenden, drücken Sie F5, um die Anweisung und nicht F9 auszuführen, mit der die Ausgabe ausgegeben wird (wodurch das Inkrement in der Regel nach 500 Zeilen gestoppt wird). Gute Seite: Diese Lösung ist nur DML, nicht DDL. Nur SQL und kein PL-SQL. Schlechte Seite: Diese Lösung druckt maximal (pk) Zeilen der Ausgabe, d. H. Ist normalerweise langsamer als die ALTER SEQUENCE-Lösung.

9
tech