it-swarm.com.de

MySQL-Äquivalent zu SEQUENCE.NEXTVAL von Oracle

Ich muss in der Lage sein, eine Abfrage zu generieren, die den nächsten ID-Wert in der folgenden Tabelle zurückgibt:

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
)

In Oracle können Sie NEXTVAL in einer Sequenz aufrufen, und Sie erhalten die nächste Sequenz (Hinweis: ohne Einfügen in die Tabelle). 

Nach dem googeln fand ich heraus, dass Sie den aktuellen Wert von auto_increment finden können, indem Sie die folgende Abfrage verwenden:

SELECT Auto_increment 
FROM information_schema.tables 
WHERE table_name='animals';

Das Problem ist, ich möchte, dass der Wert jedes Mal erhöht wird, wenn der Wert abgefragt wird. Wenn Sie in Oracle nextval aufrufen, wird der Wert der Sequenz erhöht, auch wenn Sie keine Zeile in eine Tabelle einfügen. 

Gibt es eine Möglichkeit, die obige Abfrage so zu ändern, dass der zurückgegebene Wert immer vom letzten Aufruf der Abfrage abweicht? Das heißt, Auto_increment wird jedes Mal erhöht, wenn es geprüft wird, und wenn es bei einer Abfrage verwendet wird, würde es einen neuen Wert verwenden. 

Ich verwende Spring JDBCTemplate. Wenn es also in einer Abfrage ausgeführt werden kann, ist dies besser. 

12
ziggy

Dieses Beispiel mit InnoDB zeigt eine Möglichkeit, Ihren eigenen Zähler mithilfe von ineinandergreifenden Abfragen zu implementieren:

http://dev.mysql.com/doc/refman/5.0/de/innodb-locking-reads.html

Wofür brauchen Sie eine Lücke? IDs reservieren? Ich würde den Entwurf um jeden Preis "reparieren" und die anderen Module aktualisieren, anstatt eine Sequenz zu berühren.

Anstatt die Sequenz nur explizit zu inkrementieren, würde ich sie implizieren, indem Sie für jede ID eine Standardzeile (als ungültig markiert) einfügen, um die ID zuzuweisen und zurückzugeben. Dieser Ansatz ist konsistent und portabel . Statt Einfügungen mit einem expliziten Sequenzwert zu erzwingen, können Sie diese Standardzeilen später mit ihren übereinstimmenden Sequenzwerten aktualisieren. Dies erfordert mehr Speicher, aber keine Sperren. Abfallsammlung in abgelaufenen Zeilen kann hier helfen. Anweisungen zum Einfügen oder Aktualisieren können reihenweise gesammelte Zeilen wiederherstellen, dies würde ich jedoch nicht tun.

5
Sam

http://docs.Oracle.com/cd/E17952_01/refman-5.5-de/example-auto-increment.html

3.6.9. AUTO_INCREMENT verwenden

Mit dem Attribut AUTO_INCREMENT kann eine eindeutige Identität für neue Zeilen generiert werden:

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
);

INSERT INTO animals (name) VALUES
    ('dog'),('cat'),('penguin'),
    ('lax'),('whale'),('ostrich');

SELECT * FROM animals;
Which returns:

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+

Für die Spalte AUTO_INCREMENT wurde kein Wert angegeben, daher hat MySQL automatisch Sequenznummern zugewiesen. Sie können der Spalte auch explizit NULL oder 0 zuweisen, um Sequenznummern zu generieren.

Sie können den neuesten AUTO_INCREMENT-Wert mit der SQL-Funktion LAST_INSERT_ID () oder der C-API-Funktion mysql_insert_id () abrufen. Diese Funktionen sind verbindungsspezifisch, sodass ihre Rückgabewerte nicht von einer anderen Verbindung beeinflusst werden, die auch Einfügungen ausführt.

Verwenden Sie den kleinsten ganzzahligen Datentyp für die AUTO_INCREMENT-Spalte, der groß genug ist, um den maximalen Sequenzwert aufzunehmen, den Sie benötigen. Wenn die Spalte die Obergrenze des Datentyps erreicht, schlägt der nächste Versuch, eine Sequenznummer zu generieren, fehl. Verwenden Sie nach Möglichkeit das UNSIGNED-Attribut, um einen größeren Bereich zuzulassen. Wenn Sie beispielsweise TINYINT verwenden, ist die maximal zulässige Sequenznummer 127. Für TINYINT UNSIGNED beträgt das Maximum 255. Siehe Abschnitt 11.2.1, „Ganzzahltypen (genauer Wert) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT ”Für die Bereiche aller Integer-Typen.

Hinweis Für eine Einfügung mit mehreren Zeilen geben LAST_INSERT_ID () und mysql_insert_id () tatsächlich den Schlüssel AUTO_INCREMENT aus der ersten der eingefügten Zeilen zurück. Auf diese Weise können Einfügungen mit mehreren Zeilen in einem Replikationssetup auf anderen Servern korrekt reproduziert werden.

Wenn die AUTO_INCREMENT-Spalte Teil mehrerer Indizes ist, generiert MySQL Sequenzwerte mit dem Index, der mit der AUTO_INCREMENT-Spalte beginnt (sofern vorhanden). Wenn die Animals-Tabelle beispielsweise die Indizes PRIMARY KEY (GRP, ID) und INDEX (ID) enthält, ignoriert MySQL den PRIMARY KEY zum Generieren von Sequenzwerten. Folglich würde die Tabelle eine einzelne Sequenz enthalten, nicht eine Sequenz pro GRP-Wert.

Um mit einem anderen AUTO_INCREMENT-Wert als 1 zu beginnen, legen Sie diesen Wert mit CREATE TABLE oder ALTER TABLE wie folgt fest:

mysql> ALTER TABLE tbl AUTO_INCREMENT = 100; InnoDB-Hinweise

Seien Sie bei InnoDB-Tabellen vorsichtig, wenn Sie die Spalte ändern, die den Auto-Increment-Wert in der Mitte einer Sequenz von INSERT-Anweisungen enthält. Wenn Sie beispielsweise eine UPDATE-Anweisung verwenden, um einen neuen, größeren Wert in die Spalte für das automatische Inkrementieren zu setzen, kann bei einem nachfolgenden INSERT der Fehler "Eintrag duplizieren" auftreten. Der Test, ob bereits ein Auto-Inkrement-Wert vorhanden ist, wird ausgeführt, wenn Sie ein DELETE gefolgt von weiteren INSERT-Anweisungen ausführen oder wenn Sie die Transaktion COMMIT ausführen, jedoch nicht nach einer UPDATE-Anweisung.

MyISAM-Hinweise

Für MyISAM-Tabellen können Sie AUTO_INCREMENT für eine sekundäre Spalte in einem Index mit mehreren Spalten angeben. In diesem Fall wird der generierte Wert für die Spalte AUTO_INCREMENT als MAX (auto_increment_column) + 1 WHERE-Präfix = vorgegebenes Präfix berechnet. Dies ist nützlich, wenn Sie Daten in geordnete Gruppen einordnen möchten.

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;
Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

In diesem Fall (wenn die AUTO_INCREMENT-Spalte Teil eines mehrspaltigen Index ist), werden die AUTO_INCREMENT-Werte wiederverwendet, wenn Sie die Zeile mit dem größten AUTO_INCREMENT-Wert in einer Gruppe löschen. Dies gilt auch für MyISAM-Tabellen, für die normalerweise AUTO_INCREMENT-Werte nicht wiederverwendet werden.

Lesen Sie weiter

Weitere Informationen zu AUTO_INCREMENT finden Sie hier:

So weisen Sie das AUTO_INCREMENT-Attribut einer Spalte zu: Abschnitt 13.1.17, „CREATE TABLE-Syntax“ und Abschnitt 13.1.7, „ALTER TABLE-Syntax“.

Wie sich AUTO_INCREMENT in Abhängigkeit vom SQL-Modus NO_AUTO_VALUE_ON_ZERO verhält: Abschnitt 5.1.7, „Server-SQL-Modi“.

So suchen Sie mit der Funktion LAST_INSERT_ID () nach der Zeile, die den neuesten Wert von AUTO_INCREMENT enthält: Abschnitt 12.14, „Informationsfunktionen“.

Festlegen des zu verwendenden AUTO_INCREMENT-Werts: Abschnitt 5.1.4, „Serversystemvariablen“.

AUTO_INCREMENT und Replikation: Abschnitt 16.4.1.1, „Replikation und AUTO_INCREMENT“.

Serversystemvariablen, die sich auf AUTO_INCREMENT beziehen (auto_increment_increment und auto_increment_offset), die für die Replikation verwendet werden können: Abschnitt 5.1.4, „Serversystemvariablen“.

http://search.Oracle.com/search/search?q=auto_increment&group=Documentation&x=0&y=0

11
Ivan M.

Sie können Ihre eigene MySQL-Funktion hinzufügen - wie unter http://www.microshell.com/database/mysql/emulating-nextval-function-to-get-sequence-in-mysql/ - beschrieben etwas wie das:

SELECT nextval('sq_my_sequence') as next_sequence;
4
ziesemer

MySQL verwendet AUTO_INCREMENT, der den Zwecken dient. Es gibt jedoch folgende Unterschiede:

MySQL AUTO_INCREMENT zu Oracle SEQUENCE Unterschiede

  • AUTO_INCREMENT ist auf eine Spalte pro Tabelle begrenzt
  • AUTO_INCREMENT muss einer bestimmten table.column zugeordnet sein (die Verwendung mehrerer Tabellen ist nicht zulässig)
  • AUTO_INCREMENT wird als nicht angegebene Spalte oder als Wert NULL INSERT

wenn Sie eine SEQUENCE-Implementierung mit MySQL sehen möchten, können Sie dies mit SP tun.

Unter dem Link finden Sie alles, was Sie möchten.

http://ronaldbradford.com/blog/sequences-in-mysql-2006-01-26/

2
user319198

Sie möchten den nächsten Wert für diese Tabelle, damit Sie Zeilen erstellen können, die noch nicht eingefügt wurden, ohne andere Prozesse zu stören, die das Auto-Inkrement verwenden.

Einige Optionen:

Fahren Sie fort und fügen Sie einfach die Zeilen ein, um "die Sequenz zu verbrauchen", markieren Sie sie als ausstehend und aktualisieren Sie sie später.

Fügen Sie in eine Transaktion ein und brechen Sie die Transaktion ab. Die automatische Nummernfolge sollte normalerweise aufgebraucht sein und normalerweise eine "Lücke" in der Tabelle bilden. Diese Nummer steht Ihnen jetzt zur Verfügung.

Bei Oracle ist die Sequenz vollständig tabellenunabhängig, sodass Prozesse die Sequenz verwenden können oder nicht (und sie können auch dieselbe Sequenz für unterschiedliche Tabellen verwenden). In dieser Hinsicht könnten Sie eine Sequenzsequenztabelle implementieren, auf die Sie über eine Funktion zugreifen, und für die anderen Prozesse, die auf das Auto-Inkrement angewiesen sind, entfernen Sie das Auto-Inkrement und verwenden einen Trigger, der die Zuweisungen von diesen Elementen zulässt Sequenzfunktion, wenn keine ID angegeben ist.

1
Cade Roux
1.) create table query
2.) Insert query
3.) Update query
4.) Select query for that table e.g. SELECT next_val FROM hib_sequence;
5.) Before each select update first, like this you can achieve similar

-- CREATE TABLE hib_sequence (next_val INT NOT NULL);
-- UPDATE hib_sequence SET next_val=LAST_INSERT_ID(next_val+1);
-- select last_insert_id();
-- INSERT INTO hib_sequence VALUES (0);

-- select next_val from hib_sequence;
0
Sumit

Schauen Sie sich die MariaDBs SEQUENCE Engine an. Damit können Sie so einfach Sequenzen erzeugen

SELECT seq FROM seq_1_to_5;
+-----+
| seq |
+-----+
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
+-----+

Details hier: https://mariadb.com/kb/de/mariadb/sequence/

Damit soll man sowas machen können

SELECT min(seq) as nextVal FROM seq_1_to_500 
WHERE seq NOT IN (SELECT ID FROM customers)
0
Benvorth