Eindeutigen Wert sicherstellen

Fornax

New Member
Hallo zusammen,

wie kann ich folgendes Problem am besten lösen:
Eine ID-Nummer soll in einer Tabelle eindeutig vorhanden sein.
Die ID wird per VBScript in einer Applikation erzeugt; diese kann aber auch manuell überschrieben werden bzw. wenn zwei User gleichzeitig die Nummer erzeugen kann sie doppelt erstellt werden.
Dieses Problem möchte ich jetzt über die Datenbank abfangen (SQL Server 2000), dass es eine Fehlermeldung gibt.
Weiterhin gibts in der Tabelle aber eine Spalte "deleted"; wenn da 1 steht, soll die entsprechende ID nicht zur Prüfung herangezogen werden.

Aus alten Zeiten gibts aber bereits einige IDs die schon mehrfach vorhanden sind, bzw. mit einem Defaultwert belegt sind. Diese sollen nicht geändert werden.

Ich hätte jetzt an einen Trigger gedacht; nachdem ich aber einigermaßen neu in der Materie bin, komme ich da nicht so richtig weiter...

Könnte ir da jemand helfen?

Danke schon mal.
 
Warum machst du die ID nicht zum Primärschlusses? Dann stellt die Datenbank auch sicher dass es diese ID nur einmal gibt.
 
Primärschlüssel funktioniert aber nicht, wenn bereits doppelte Einträge vorhanden sind.

An deiner Stelle würde ich eher die jetzigen, doppelten Schlüssel in eine extra Spalte schreiben und einen neuen Index anlegen.
Diesen dann als Primärschlüssel setzen. Oder aber, du lässt den Schlüssel von der Datenbank erstellen. Oder aber du prüfst entsprechend bevor du einen INSERT machst.

SELECT COUNT (*) FROM ... WHERE ... = VBSchlüssel.
IF ... > 0
neuen Schlüssel erstellen.
FI


Oder so ähnlich.
 
Ich empfehle ebenfalls das Aufräumen der Spalte so dass keine Dubletten enthalten sind und das Setzen des Primary Key oder eines Unique Index.
Der Wert sollte ab dann automatisch von der Datenbank gesetzt werden oder vor dem Einfügen aus einer Sequenz beschafft werden.

Auf jeden Fall sollte die Eindeutigkeit von der Datenbank-Engine durchgesetzt werden. Alles andere ruft förmlich nach Inkonsistenz.
 
So einfach ist das mit dem Aufräumen leider nicht.
Erstens steckt da eine Applikation dahinter, zweitens wird diese ID nicht immer befüllt. Es gibt auch einen "Default-Wert", der mehrfach vorkommen darf und NULL. Deshalb ist ein Index leider keine Lösung.
Ich hätte da an einen (Insert?)-Trigger gedacht, der auslöst, wenn ich einen bereits vorhandenen Wert eintragen will und sich dieser vom Default bzw. NULL unterscheidet. Nur komm ich mit dem Code dafür nicht ganz klar :)

Folgendes habe ich probiert:

Code:
CREATE TRIGGER eindeutige_nummer 
   ON  tabelle_xy 
   for insert, update
AS 
BEGIN
	if inserted.feld1 in 
		(select feld1 
		from tabelle_xy 
		where deleted = 0
		and (feld1 <> '-' or feld1 is not null))     -- '-' ist der Defaultwert, den es auch 199mal geben darf
BEGIN
   RAISERROR ('Doppelte Nummer!', 16, 1)
   ROLLBACK TRANSACTION
END
END
GO

Ich bekomme folgende Fehlermeldung:
Code:
Msg 4104, Level 16, State 1, Procedure eindeutige_nummer, Line 14
The multi-part identifier "inserted.feld1" could not be bound.
 
Last edited by a moderator:
Eindeutiger Wert

Servus,

dazu habe ich auch gleich noch eine Frage. Die Sache mit Primärschlüssel ist klar, funktioniert ja auch wunderbar. Ich habe nur das Problem, dass ich den erzeugten Wert sofort wieder benötige.

Datensatz wird angelegt -> ID wird erstellt z.B. 4711 -> Wissen das es 4711 ist tu ich ja zu diesem Zeitpunkt nicht. Im Access weiß ich das schon, wie kann ich das mit dem SQL Server umsetzen?

Merci
lg
WW
 
Die Lösung dafür ist, das Einfügen in einer Transaktion zu machen.
Da die ID streng monoton steigend ist, hat der zuletzt eingefügte Datensatz die höchste ID. Die Transaktion eleminiert eine mögliche Race-Condition mit anderen Einfügeoperationen.
Ggf. kann man den zuletzt vergebenen Wert auch an der Sequenz für die ID-Spalte ablesen.
 
Back
Top