verwendetes Datenbanksystem: MySql / Connector/NET
Hallo,
mein PK in der Tabelle ist ein „auto_increment“ Integer.
Wir frage ich nun nach einem Insert, am besten die automatisch erzeuge ID ab?
Nach dem Insert ein „SELECT @@IDENTITY“? Ist das sicher (Multithreading)? Performant?
@@IDENTITY kann unter umständen zu problemen führen da es eine globale variable ist, die bei jeder anweisung, die der server bekommt, beeinflusst wird. wird also z.b. direkt nach deinem insert, noch ein anderer command eines anderen programmes z.b. verarbeitet, dann bekommst du einen von dir nicht gewünsten wert.
eine möglichkeit es sicher zu machen sind stored procedures, eine andere ist eine transactionscope. ob und wie das funktioniert weiß ich nicht. das sind nur die ideen die mir so spontan einfallen um das sicher hinbekommen zu können.
warum nicht einfach ein "SELECT IDfeld FROM tabel ORDER BY IDfeld DESC /oder doch ASC bin gerade in feierabendmodus/ LIMIT 1;1"
MfG Paul
weil du das problem haben kannst das du einen insert machst und bevor du es schaffst ein select zu machen ein anderes programm einen weiteren insert gemacht hat.
edit: außerdem musst du das order zeugs nicht machen wenn das ding auf autoincrement ist, da ein einfacher select max(idfeld) from tabelle ausreichen würde
Select @@Identity bezieht die letzte identity einer Connection.
Und da du ja ganz bestimmt die connection nicht falsch benutzt, ist die dann schon eindeutig.
Was ist mit
SELECT LAST_INSERT_ID();
? Ist das das selbe/gleiche wie @@IDENTITY?
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
@FZelle
ich benutze so die connection, kann es da zu problemen kommen?
using (MySqlConnection cn = new MySqlConnection(Utils.GetConnString()))
{
cn.Open();
MySqlCommand cmd = new MySqlCommand("INSERT INTO users (usr_Loginname) VALUES (?s1)", cn);
cmd.Parameters.AddWithValue("?s1", "asdf");
cmd.Prepare();
cmd.ExecuteNonQuery();
}
es muss doch dafür eine gängige lösung geben oder? ich meine, das braucht man ja oft bei web-anwendungen. wenn ich z.b. einen benutzer anlege und gleich ein paar rollen in einer anderen tabelle einfügen muss, dann benötige ich ja gleich die letzte id.
oder soll man gleich ne GUID im code erzeugen und so arbeiten statt auto-increment?
@JAck30lena:
Aber eine in benutzung befindliche connection wird nicht von anderen benutzt.
@Savage:
Prepare brauchst du nicht, und genau in dem using machst du als nächstes
das SELECT LAST_INSERT_ID();
Denn danach ist die connection ja schon wieder geschlossen.
danke für die infos, werde es dann mal so umsetzten.
also ich habs jetzt mal probiert.
funktioniert ohne probleme wenn mehrere threads gleichzeitig auf die funktion zugreifen (es bekommt jeder die richtige id).
kompakt dargestellt:
using (MySqlConnection cn = new MySqlConnection(connStr))
{
cn.Open();
MySqlCommand cmd = new MySqlCommand("INSERT INTO tab01 (uname) VALUES (?s1);SELECT LAST_INSERT_ID();", cn);
cmd.Parameters.AddWithValue("?s1", "asdf");
int LastID = Convert.ToInt32(cmd.ExecuteScalar());
Response.Write(LastID);
}
@JAck30lena:
Nein, das ist nicht richtig.
Es werden nur nicht "geöffnete" Connections ( connectionstate == closed)
aus dem pool weiterverwendet.
Und in den pool gehen sie erst wieder nach dem close.