5

In meiner derzeitigen Rails-Anwendung behebe ich Terminierungskonflikte, indem ich die Modelle nach dem Feld "created_at" sortiere. Ich habe jedoch festgestellt, dass beim Einfügen mehrerer Modelle aus einem Formular, die dies ermöglicht, alle created_at Zeiten genau gleich sind!Kann man sich auf den automatisch inkrementierenden Primärschlüssel in Ihrer Datenbank verlassen?

Dies ist mehr eine Frage der besten Programmierpraktiken: Kann Ihre Anwendung darauf vertrauen, dass Ihre ID-Spalte in Ihrer Datenbank größer und größer wird mit jedem INSERT, um die Reihenfolge der Erstellung zu erhalten? Um es anders auszudrücken, kann ich eine Gruppe von Zeilen, die ich aus meiner Datenbank herausziehe, nach ihrer ID-Spalte sortieren und sicher sein, dass dies eine genaue Sortierung ist, basierend auf der Erstellungsreihenfolge? Und ist das eine gute Übung in meiner Anwendung?

Antwort

1

Das hängt von Ihrem Datenbankanbieter ab.

MySQL Ich glaube, absolut Auto-Inkrementschlüssel bestellt. SQL Server Ich weiß nicht sicher, ob es das tut oder nicht, aber ich glaube, dass es so ist.

Wo Probleme auftreten, ist mit Datenbanken, die diese Funktionalität nicht unterstützen, vor allem Oracle, die Sequenzen verwendet, die grob, aber nicht absolut geordnet sind.

Eine Alternative könnte sein, für erstellte Zeit und dann ID zu gehen.

+0

Ich mag die Idee der Redundanz, Sortieren nach eins und dann ID für eine sekundäre Sortierung. . . Vielen Dank! – BushyMark

+0

Oracle-Sequenzen sind für Nicht-RAC-Installationen bestellt, die die große Mehrheit von ihnen sind. –

2

Die generierten Identifikationsnummern sind eindeutig. Unabhängig davon, ob Sie Sequenzen wie in PostgreSQL und Oracle verwenden oder ob Sie einen anderen Mechanismus wie Auto-Increment von MySQL verwenden.

Sequenzen werden jedoch am häufigsten in Mengen von beispielsweise 20 Nummern erfasst. Also mit PostgreSQL können Sie nicht bestimmen, welches Feld zuerst eingefügt wurde. Es kann sogar Lücken in der ID der eingefügten Datensätze geben.

Daher sollten Sie ein generiertes ID-Feld nicht für eine solche Aufgabe verwenden, um sich nicht auf Datenbankimplementierungsdetails zu verlassen.

Generieren eines erstellt oder aktualisiert Feld während der Befehlsausführung ist viel besser für durch Erstellungs- Sortierung oder update-Zeit später. Zum Beispiel:

INSERT INTO A (data, created) VALUES (smething, DATE()) 
UPDATE A SET data=something, updated=DATE() 
0

Ich glaube, die Antwort auf Ihre Frage ist ja ... wenn ich zwischen den Zeilen zu lesen, ich glaube, Sie sind besorgt, dass das System-Zahlen wiederverwenden ID kann, die ‚fehlenden‘ sind in die Reihenfolge, und deshalb, wenn Sie 1,2,3,5,6,7 als ID-Nummern verwendet haben, in allen Implementierungen, die ich kenne, wird die nächste ID-Nummer immer 8 (oder möglicherweise höher) sein, aber ich nicht ' Ich kenne keine DB, die versuchen würde herauszufinden, dass die Datensatz-ID Nr. 4 fehlt. Versuchen Sie also, diese ID-Nummer erneut zu verwenden.

Obwohl ich mit SQL Server am besten vertraut bin, weiß ich nicht, warum ein Anbieter versucht, die Lücken in einer Sequenz zu füllen - denken Sie an den Overhead, diese Liste von ungenutzten IDs zu behalten, anstatt immer nur den Überblick zu behalten der letzten I-Nummer verwendet, und Hinzufügen von 1.

Ich würde sagen, Sie könnten sicher verlassen auf die nächste ID zugewiesen Nummer immer höher als die letzte - nicht nur einzigartig.

0

Ja, die ID wird eindeutig sein und nein, Sie können und sollten sich nicht darauf verlassen, um sortiert zu werden - es ist da, um nur die Zeileneindeutigkeit zu garantieren. Der beste Ansatz ist, wie emktas angegeben hat, ein separates "aktualisiertes" oder "erzeugtes" Feld für genau diese Information zu verwenden.

Für die Erstellungszeit einstellen, können Sie nur einen Standardwert wie diese verwenden

CREATE TABLE foo (
    id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL; 
    created TIMESTAMP NOT NULL DEFAULT NOW(); 
    updated TIMESTAMP; 
    PRIMARY KEY(id); 
) engine=InnoDB; ## whatever :P 

Nun, die Bewahrung der Schöpfung Zeit in Anspruch nimmt. mit Update-Zeit würde ich ein AFTER UPDATE-Trigger wie diese vorschlägt (natürlich Sie es in einer separaten Abfrage tun können, aber der Auslöser, meiner Meinung nach, ist eine bessere Lösung - transparenter):

DELIMITER $$ 
CREATE TRIGGER foo_a_upd AFTER UPDATE ON foo 
FOR EACH ROW BEGIN 
    SET NEW.updated = NOW(); 
END; 
$$ 
DELIMITER ; 

Und das sollte es tun.

EDIT: Wehe mir. Dummerweise habe ich nicht angegeben, dass dies für mysql ist, es könnte einige Unterschiede in den Funktionsnamen (nämlich "NOW") und anderen subtilen Itty-Bitty geben.

+1

Sie ignorieren, was das OP gesagt hat: Er hat bereits ein Feld created_at und das ist dasselbe, wenn mehrere Elemente gleichzeitig eingefügt werden, daher seine Frage. – cletus

+0

Es würde in der Tat scheinen, dass mein Gedankengang, wild schlingernd wie es ist, zu einem Seitengleis gewandert ist. Es tut uns leid. Sie haben natürlich Recht. Die Sortierung nach created_at und dann nach id ist wahrscheinlich die einfachste Lösung (obwohl sie wahrscheinlich nicht die korrekte Reihenfolge garantiert, sondern nur garantiert, dass die Zeilen mit den gleichen created_at -Werten jeweils in der gleichen Reihenfolge zurückgegeben werden Zeit). – shylent

0

Eine Einschränkung zu EJB Antwort:

SQL geben keine Garantie für die Bestellung, wenn Sie nicht eine Bestellung durch Spalte angeben. Z.B. Wenn Sie einige frühe Zeilen löschen, dann fügen Sie sie ein, die neuen können am selben Ort in der Datenbank enden, die die alten hatten (wenn auch mit neuen IDs), und das ist es, was es als Standardsortierung verwenden kann.

FWIW, verwende ich normalerweise Bestellung nach ID als eine effektive Version der Bestellung von created_at. Es ist billiger, da es keinen Index zu einem Datetime-Feld hinzufügen muss (das größer und daher langsamer ist als ein einfacher Integer-Primärschlüsselindex), garantiert unterschiedlich ist, und es interessiert mich nicht wirklich, ob ein paar Zeilen das waren ungefähr zur gleichen Zeit hinzugefügt, sortiert in etwas anderer Reihenfolge.

0

Dies ist wahrscheinlich DB-Engine abhängig. Ich würde überprüfen, wie Ihre DB Sequenzen implementiert und wenn es keine dokumentierten Probleme gibt, würde ich mich entscheiden, ID zu verlassen.

z. Postgresql sequence ist OK, es sei denn, Sie spielen mit den Sequenz-Cache-Parametern.

Es besteht die Möglichkeit, dass andere Programmierer Datensätze aus verschiedenen DBs mit falscher ID-Spalte manuell erstellen oder kopieren. Allerdings würde ich das Problem vereinfachen. Vermeiden Sie Fälle mit geringer Wahrscheinlichkeit, bei denen jemand die Datenintegrität manuell zerstört. Du kannst dich nicht vor allem schützen.

Mein Rat ist, sich auf Sequenz generierte IDs zu verlassen und Ihr Projekt vorwärts zu bewegen.

0

In der Theorie ja die höchste ID-Nummer ist die letzte erstellt. Denken Sie daran, dass Datenbanken die Möglichkeit haben, die Einfügung des automatisch generierten Wertes vorübergehend zu deaktivieren, einige Datensätze manuell einzufügen und dann wieder einzuschalten. Diese Einsätze werden normalerweise nicht in einem Produktionssystem verwendet, können jedoch gelegentlich auftreten, wenn ein großer Teil der Daten von einem anderen System übertragen wird.