![]() |
Datenbank: MSSQL SRV • Zugriff über: ADO
Mehr Benutzer Primary Key Insert in Tabelle
Hallo DP ler
Ich würde mich über eine Einschätzung von euch zu folgendem Problem und meinen Lösungsweg freuen. Problem: Ich entwickle zur Zeit ein Dokumentenmanagementsystem dass eng mit unserer ERP Lösung zusammenarbeitet. Die Haupttabelle für dieses Projekt ist eine Tabelle wo jedes Dokument einmalig gespeichert ist. Durch folgende Vorgänge können neue Sätze in diese Tabelle erstellt werden. 1. Aus dem ERP System beim Druck diverser Belegarten 2. Über einen Dokumentencsanner der von meinem Programm angesprochen wird. 3. Von bis zu 100 Usern im Netzwerk durch diverse Ablagemöglichkeiten im Programm. Ich halte es für nicht ausgeschlossen dass in dieser Konstellation es vorkommen kann dass zwei oder mehr Inserts zusammenstossen (Ich verwende einen Primary Key in dieser Tabelle für das ID Feld). folgenden Code habe ich mir für die Lösung dieses Problems überlegt
Delphi-Quellcode:
Ich habe diesen Programmteil von 2 Pc's absolut gleichzeitig gestartet und es funktioniert imho zielführend.
while i < 50 do //50 gleichzeitige Zugriffe simulieren
begin i:=i+1; MaxInsVersuche:=0; olev:=0; while (MaxInsVersuche < 5) and (olev = 0) do // Verhinderung Endlosschleife falls // Exception durch anderen Grund ausgelöst begin Inc(MaxInsVersuche,1); aNextDokId:=DataMain.NeueDokId; // Holt nächste höhere Nummer (DokID) aus Datenbank try sSql := Format('INSERT INTO dokumente (dkDokumentId, dkDokGruppe, dkErstelltAm, dkBezeichnung) VALUES (%s , %s, %s, %s)', [IntToStr(aNextDokId),'99',QuotedStr(DateToStr(now)),QuotedStr('Bezeichnung')]); DataMain.AdoConMain.ConnectionObject.Execute(sSql,olev,0); except Sleep(1000) //Annahme Exception ausgelöst durch Verletzung Primary Key // warten bis anderer User Insert abgeschlossen hat end; Memo1.Lines.Add(inttostr(aNextDokId)+'@'+IntToStr(MaxInsVersuche)); end; if olev<>1 then Application.MessageBox('Insert nicht erfolgreich','Fehler',16) end; ShowMessage('Instert Ok'); Anmerkung: Ich kann keinen Autowert oder GUID für den eindeutigen Schlüssel verwenden. |
Re: Mehr Benutzer Primary Key Insert in Tabelle
Keine schlechte Variante um "unnötige" OLE Exceptions abzufangen. Die 1000 ms zwischen den Versuchen finde ich jedoch etwas zu lang ... 500ms sollten IMHO locker reichen ...
Zitat:
SQL-Code:
INSERT INTO TABLE1 (GUID,Vorname,Name)
VALUES (GetGUID,'Hans','Wurst')
Delphi-Quellcode:
Bei Identity Werten (Autoinc) wirds komplizierter..
// benötigt Unit ACTIVEX
function GetGuid: variant; var ID: TGUID; begin Result := ''; if CoCreateGuid(ID) = S_OK then Result := GUIDToString(ID); end; Schöne Grüße, Jens |
Re: Mehr Benutzer Primary Key Insert in Tabelle
@ Jens
Danke für deine Meinung Der Grund für die Nichtverwendung eines Autowerts oder eine GUID ist das ich bei der Scannererfassung eine fortlaufende Zahl ohne Lücken brauche weil ich in den Barcodes eigene Prüfziffern integrieren muss die auf den Etiketten der Dokumente sind. :coder: |
Re: Mehr Benutzer Primary Key Insert in Tabelle
Zitat:
|
Re: Mehr Benutzer Primary Key Insert in Tabelle
Zitat:
Erzeuge eine Tabelle "Generators" mit:
SQL-Code:
Über folgende Stored Procedure bekommst du dann immer einen neuen Keywert:
CREATE TABLE [Generators] (
[IdGenerator] [varchar] (20) NOT NULL , [CurrentValue] [int] NOT NULL ) GO ALTER TABLE [Generators] CONSTRAINT [PK_Generators] PRIMARY KEY ( [IdGenerator] ) GO
SQL-Code:
Create procedure generator_id ( @IdGenerator varchar(20))
as begin declare @ID integer SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRANSACTION SP_GEN_ID select @ID = CurrentValue from Generators where IdGenerator =@IdGenerator IF @@ERROR <> 0 GOTO LBL_ERROR update Generators set CurrentValue =CurrentValue + 1 where IdGenerator=@IdGenerator IF @@ERROR <> 0 GOTO LBL_ERROR COMMIT TRANSACTION SP_GEN_ID return @ID LBL_ERROR: ROLLBACK TRANSACTION SP_GEN_ID return 0 end |
Re: Mehr Benutzer Primary Key Insert in Tabelle
ok Ich hätte vielleicht schreiben sollen ich will keine GUID oder Autowert verwenden
Die Lücken in den fortlaufenden Nummern sind nicht wirklich ein Problem ich will halt nur den Bereich in dem Sie gebildet werden beeinflussen und selbst kontrollieren können. Das mit dem Generator direkt auf dem MSSQL Server ist ein interessanter Vorschlag. Ich will aber so wenig logik wie möglich in die Datenbank packen da ich Datenbank unabhängig bleiben will. Primär gehts mir um eure Meinung bei dem Code innherhalb der beiden While schleifen eine weitere Idee die ich hatte war kurz vor dem Insert eine funktion aufzurufen die mir prüft ob die Nummer die ich einfügen will bereits in der Datenbank vorhanden ist aber das könnte ja dann wieder zu früh sein ??? |
Re: Mehr Benutzer Primary Key Insert in Tabelle
Hi,
kann man die Generator-Funktion aus Beitrag #5 auch so umbauen, dass man per SELECT Abfrage an den nächsten Wert kommt? Etwa: Select id from generator_id('meinetab'); Ich bin nicht so firm in den SQL Funktionssachen und muss deshalb fragen. |
Re: Mehr Benutzer Primary Key Insert in Tabelle
hat da nicht einer eine idee?
|
Re: Mehr Benutzer Primary Key Insert in Tabelle
Benutze doch den 'Generator'. Was ist dagegen einzuwenden?
Das ist doch nix anderes als ein Nachbau von 'Sequenzen', die es z.B. auf Oracle schon von Haus aus gibt. Postgres und Firebird kennen solche Sequenzen auch, für MySQL müsste man sowas dann wieder mit diesen Tabellen nachbauen. Ist aber kein großer Akt. |
Re: Mehr Benutzer Primary Key Insert in Tabelle
Mein Problem ist, dass ich die Kompontensuite mODBC für den Datenbankzugriff benutze und deren Komponente für stored procedures mStoredProcedures gibt keine Werte zurück.
Mit einer Select-Abfrage könnte ich direkt per mQuery an die Funktion herangehen. Gruß |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:03 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz