Ich habe eine Datenbank, die nicht in Produktion ist. Die Haupttabelle ist CustodyDetails. Diese Tabelle enthält eine ID int IDENTITY(1,1) PRIMARY KEY
Spalte. Ich suche nach einer Möglichkeit, eine weitere eindeutige Kennung hinzuzufügen, auf die in keiner anderen Tabelle verwiesen wird Konto Der Inhalt der Spalte wäre nicht genau ein Identitätsschlüssel.
Diese neue Identitätsspalte enthält jedoch einige spezifische Details, und hier beginnt mein Problem. Das Format lautet wie folgt: XX/YY
Dabei ist XX ein automatisch inkrementierbarer Wert, der jedes neue Jahr zurückgesetzt / neu gestartet wird, und YY die letzten beiden Ziffern des aktuellen Jahres SELECT RIGHT(YEAR(GETDATE()), 2)
.
So zum Beispiel kann pretend einen Datensatz pro Tag beginnend hinzugefügt werden vom 28/12/2015 enden 2016.03.01 , die Spalte aussehen würde:
ID ID2 DATE_ADDED
1 1/15 2015-12-28
2 2/15 2015-12-29
3 3/15 2015-12-30
4 4/15 2015-12-31
5 1/16 2016-01-01
6 2/16 2016-01-02
7 3/16 2016-01-03
Ich dachte daran, das Frontend zu verwenden, um die zusammengesetzte ID zu analysieren (ID2 im Beispiel), die letzten 2 Ziffern abzurufen und mit den letzten 2 Ziffern des aktuellen Jahres zu vergleichen und dann zu entscheiden, ob ein neues Korrelativ gestartet werden soll oder nicht. Natürlich wäre es großartig, alles auf der Datenbankseite erledigen zu können.
EDIT 1: Übrigens habe ich auch Leute gesehen, die separate Tabellen nur zum Speichern paralleler Identitätsschlüssel verwenden. Ein Tabellenidentitätsschlüssel wird also zu einem zweiten Tabellensekundärschlüssel. Das klingt etwas zwielichtig, aber vielleicht ist dies der Fall, wenn eine solche Implementierung erfolgt?
BEARBEITEN 2: Diese zusätzliche ID ist eine Legacy-Dokumentreferenz, die jede Datei / jeden Datensatz kennzeichnet. Ich denke, man könnte es sich als speziellen Alias für die Haupt-ID vorstellen.
Die Anzahl der Datensätze, die diese Datenbank jährlich verarbeitet, war in den letzten 20 Jahren nicht von den 100 und ist höchst (wirklich, extrem hoch) unwahrscheinlich, dass dies natürlich der Fall sein würde, wenn sie über 99 hinausgeht Fahren Sie mit der zusätzlichen Ziffer fort und das Frontend / die Prozedur kann über 99 gehen, so dass es nicht so ist, als würde es Dinge ändern.
Natürlich haben einige dieser Details, die ich am Anfang nicht erwähnt habe, nur die Lösungsmöglichkeiten eingegrenzt, um meinen spezifischen Anforderungen gerecht zu werden, und versucht, den Problembereich breiter zu halten.
ID
= 5, 6 und 7 sollte DATE_ADDED sein2016-01-01
und so weiter?Antworten:
Sie können eine Schlüsseltabelle verwenden, um den inkrementierenden Teil Ihrer zweiten ID-Spalte zu speichern. Diese Lösung basiert nicht auf clientseitigem Code und ist automatisch mehrjährig verfügbar. Wenn der
@DateAdded
Parameter in einem zuvor nicht verwendeten Jahr übergeben wird, wird automatisch ein neuer Wertesatz für dieID2
Spalte verwendet, der auf diesem Jahr basiert. Wenn der Prozess folglich zum Einfügen von Zeilen aus früheren Jahren verwendet wird, werden diese Zeilen mit "korrekten" Werten für das Inkrement eingefügt. DerGetNextID()
Prozess ist darauf ausgerichtet, mögliche Deadlocks ordnungsgemäß zu behandeln, und gibt nur dann einen Fehler an den Aufrufer weiter, wenn beim Versuch, dietblIDs
Tabelle zu aktualisieren, 5 aufeinanderfolgende Deadlocks auftreten .Erstellen Sie eine Tabelle zum Speichern einer Zeile pro Jahr mit dem aktuell verwendeten ID-Wert sowie eine gespeicherte Prozedur, um den neuen zu verwendenden Wert zurückzugeben:
Ihre Tabelle zusammen mit einem Proc zum Einfügen von Zeilen:
Fügen Sie einige Beispieldaten ein:
Beide Tabellen anzeigen:
Ergebnisse:
Die Schlüsseltabelle und der gespeicherte Prozess stammen aus dieser Frage.
quelle
(IDName, LastID)
würden, dieselbe Zeile einzufügen , würde dies zu einem Deadlock oder zu einer der Transaktionen führen, die die PK verletzen? In letzterem Fall wäre es möglicherweise sinnvoll, dieser Transaktion eine weitere Chance zu geben (damit sie schließlich die ID 2 erhält).@NewID
am Anfang der Schleife explizit auf null setzen : Wenn die Transaktion, die versucht, eine Zeile einzufügen, ein Deadlock-Opfer wird, wird sie nicht versuchen, eine Zeile bei der nächsten Iteration einzufügen, da dies@NewID
bereits der Fall ist wurde auf 1 gesetzt (was nicht NULL ist, und daher wird der INSERT-Zweig weggelassen).tblIDs
Tabelle einfügen könnten, da diese Tabelle durch eine einzelne atomare Operation aktualisiert wird. das "skurrile" Update.@NewID = NULL
am Anfang der Schleife.