Last
hawkmaster
- datenbank
Hallo zusammen,
In meiner PHP Webanwendung verbinde ich momentan mit PDO zu einem MySQL 5 Server. Ich versuche gerade die Anwendung bzw. die Datenbank zu MS SQL bzw. SQL Server 2008 Express zu portieren.
Einige Hürden sind bereits geschafft.
Die Verbindung zum SQL Server findet mit PDO und ODBC statt.
Jetzt stellt sich die Frage was tun bezüglich "LastInsertID()".
In einigen Stellen meiner Scripte habe ich z.b. folgenden Code:
$sql = "INSERT INTO groups (SystemsID,ElementsID,TabsID) VALUES ('{systems_id}','88','19')";
$DBO->exec($sql);
$lastid = $DBO->lastInsertId();
$sqlcat = "INSERT INTO values (GroupID,Value,TextID,SystemsID) VALUES ('$lastid','not','1079','$systems_id')";
$DBO->exec($sqlcat);
Beim ersten Insert wird der Primary (auto_increment) Key "GroupID" erzeugt und diese ID wird in der zweiten Tabelle gespeichert.
Die Frage ist nun; was ist die beste Lösung für MSSQL? Hier gibt es ja keine LastInsertID() Funktion.
Wäre ein Select nach dem Insert wie folgt eine Lösung?
SELECT id FROM tbl_newsletter ORDER BY id DESC LIMIT 1
Oder ein Select mit max() ?
SELECT max(id) FROM table;
In vielen Forenbeiträgen habe ich gelesen man soll "@@IDENTITY" verwenden oder besser noch SCOPE_IDENTITY()
select @@IDENTITY as NewID from tbl_newsletter
SELECT scope_identity()
Hier habe ich gelesen das die unter Umständen nicht zuverlässig ist.
https://connect.microsoft.com/SQL/feedback/ViewFeedback.aspx?FeedbackID=328811&wa=wsignin1.0
Bin für jeden Ratschlag dankbar.
vielen Dank und viele Grüße
hawk
SCOPE_IDENTITY() ist die Funktion deiner Wahl.
mit @@IDENTITY hast du nämlich (u.a.) das Problem, dass ein von einem Trigger ausgelöstes INSERT @@IDENTITY mit der im Trigger generierten ID überschreibt ...
Hallo,
vielen Dank für eure Hilfe und Tipps.
Ich vermute es gibt keine "universelle" Lösung die für "alle" DB Systeme gilt?
Was würde denn gegen ein:
SELECT `jobID`
FROM `job`
ORDER BY `jobID` DESC
LIMIT 1
Wenn man dies gleich hinter dem Insert machen würde?
Ist eigentlich für so etwas eine StoredProcedure immer die beste Wahl?
Ich hatte bisher noch keinen Grund eine SP zu verwenden.
vielen Dank und viele Grüße
hawk
Hallo,
Ich vermute es gibt keine "universelle" Lösung die für "alle" DB Systeme gilt?
Was würde denn gegen ein:
SELECT
jobID
FROMjob
ORDER BYjobID
DESC
LIMIT 1
damit baust Du Dir eine Race-Condition.
Freundliche Grüße
Vinzenz
Hallo Vinzenz,
damit baust Du Dir eine Race-Condition.
hmm, was genau meinst du damit?
Meinst du die Gefahr, dass event. ein zweiter user zum selben Moment etwas speichert und dann mit dem Select die falsche "letzte" ID gelesen wird?
Wenn ja, könnte das nicht auch mit "SCOPE_IDENTITY()" passieren?
vielen Dank und viele Grüße
hawk
Nein, denn SCOPE_IDENTITY() ist genau dafür konzipiert.
Ansonsten könntest du auch (überaus umständlich) selbst durch Erzeugen einer Sperre (Transaktion mit Level auf Serializable) lange genug exklusiven Zugriff auf die Tabelle haben. Ohne Garantie.
Cheers, Frank
Hallo,
Ich versuche gerade die Anwendung bzw. die Datenbank zu MS SQL bzw. SQL Server 2008 Express zu portieren.
Jetzt stellt sich die Frage was tun bezüglich "LastInsertID()".
In einigen Stellen meiner Scripte habe ich z.b. folgenden Code:
$sql = "INSERT INTO groups (SystemsID,ElementsID,TabsID) VALUES ('{systems_id}','88','19')";
$DBO->exec($sql);
$lastid = $DBO->lastInsertId();
$sqlcat = "INSERT INTO values (GroupID,Value,TextID,SystemsID) VALUES ('$lastid','not','1079','$systems_id')";
$DBO->exec($sqlcat);
> Beim ersten Insert wird der Primary (auto\_increment) Key "GroupID" erzeugt und diese ID wird in der zweiten Tabelle gespeichert.
> Die Frage ist nun; was ist die beste Lösung für MSSQL? Hier gibt es ja keine LastInsertID() Funktion.
> Wäre ein Select nach dem Insert wie folgt eine Lösung?
> ~~~sql
SELECT id FROM tbl_newsletter ORDER BY id DESC LIMIT 1
>
Oder ein Select mit max() ?
SELECT max(id) FROM table;
Nein. Das ist *keine* Lösung.
In vielen Forenbeiträgen habe ich gelesen man soll "@@IDENTITY" verwenden oder besser noch SCOPE_IDENTITY()
select @@IDENTITY as NewID from tbl_newsletter
SELECT scope_identity()
Hier habe ich gelesen das die unter Umständen nicht zuverlässig ist.
https://connect.microsoft.com/SQL/feedback/ViewFeedback.aspx?FeedbackID=328811&wa=wsignin1.0
Du hast ein einzelnes INSERT. Ein Problem mit @@IDENTITY und SCOPE_IDENTITY() tritt laut verlinkter Ressource *nur* auf, wenn ein paralleler Ausführungsplan vorhanden ist, nicht bei einzelnen INSERTS, auch nicht, wenn in verschiedenen Sitzungen paralles einzelne INSERTS vorgenommen werden.
Du könntest IDENT_CURRENT('table_name') nutzen.
Du könntest die OUTPUT-Klausel des INSERT-INTO-Statement verwenden (falls PDO das kann). Du könntest einen der anderen Workarounds nutzen, die vorgeschlagen werden.
Freundliche Grüße
Vinzenz