J'utilise un objet SqlCommand pour insérer un enregistrement dans une table avec une clé primaire générée automatiquement. Comment puis-je écrire le texte de la commande pour obtenir l'ID nouvellement créé lorsque j'utilise la méthode ExecuteScalar ()?
INSERT INTO YourTable(val1, val2, val3 ...)
VALUES(@val1, @val2, @val3...);
SELECT SCOPE_IDENTITY();
N'oubliez pas les points-virgules à la fin de chaque instruction.
Ajoutez la ligne suivante à la fin de la requête SQL ...
SELECT SCOPE_IDENTITY()
Et puis utilisez la méthode ExecuteScalar sur l'objet SqlCommand ...
var rowCount = command.ExecuteScalar()
insert into Yourtable()
values()
SELECT SCOPE_IDENTITY()
Je viens de lancer un test et de vérifier que les points-virgules sont facultatifs à l'aide de SQL Server 2005 SP2 et .Net 3.5
Ajoutez un paramètre de sortie à l'objet de commande, puis définissez la valeur sur le nouvel ID dans la procédure stockée.
Procédure stockée:
@ID AS INT OUTPUT
[Insert Command]
SET @ID = SCOPE_IDENTITY()
. NET:
cmd.CommandText = "stored_procedure";
SqlParameter pID = new SqlParameter("ID", DBType.Int32, 4);
pID.Direction = ParameterDirection.Output;
cmd.ExecuteScalar();
int id = Convert.ToInt32(cmd.Parameters["ID"].Value.ToString());
N'utilisez pas @@ IDENTITY, aussi simple que cela puisse paraître. Il peut renvoyer des valeurs incorrectes.
SELECT SCOPE_IDENTITY()
semble être le choix évident.
Immédiatement après votre insertion, utilisez
SELECT CAST(scope_identity() AS bigint) ---- incase you have a return result as int64
Cela retournera la colonne créée id/identité.
Bien que j'aime la réponse de Dave Markle , (et je vois que vous aussi, puisque vous l'avez marquée comme votre réponse), cette méthode peut échouer si vous avez des déclencheurs sur votre base de données, qui auditent les opérations CUD et votre la table d'audit a une colonne IDENTITY. Il retournerait la valeur de l'identité de la table d'audit, pas la table que vous venez d'insérer, car la table d'audit se produit réellement après.
Dans ce cas, une méthode plus générique peut être utilisée qui fonctionnera dans les deux cas, indépendamment de tout audit. C'est un peu plus verbeux, mais vous en avez pour votre argent.
exemple:
@"DECLARE @tmp AS TABLE ( id int )
INSERT INTO case
(
caseID,
partID,
serialNumber,
hardware,
software,
firmware
)
OUTPUT Inserted.ID into @tmp
VALUES
(
@caseID,
@partItemID,
@serialNumber,
@hardware,
@software,
@firmware
)
Select ID from @tmp" )
Si votre identifiant est un Guid, j'ai trouvé que cette solution était la meilleure:
INSERT INTO YourTable (val1, val2, val3)
OUTPUT inserted.id
VALUES (@val1, @val2, @val3)
Merci @Scott Ivey
Démo complète:
internal static Guid InsertNote(Note note)
{
Guid id;
using (
var connection =
new SqlConnection(ConfigurationManager.ConnectionStrings["dbconn"].ConnectionString))
{
connection.Open();
using (
var command =
new SqlCommand(
"INSERT INTO Notes ([Title],[Text]) " +
"OUTPUT inserted.id " +
$"VALUES ('{title}','{text}');", connection))
{
command.CommandType = CommandType.Text;
var reader = command.ExecuteReader();
reader.Read();
id = reader.GetGuid(reader.GetOrdinal("id"));
}
connection.Close();
}
return id;
}
Je recommanderais d'utiliser une procédure stockée, mais c'est pour les tests unitaires de notre référentiel.
Tout droit sorti du Whirlpool :
Si vous utilisez MS SQL, vous pouvez utiliser "SELECT @@ IDENTITY as Value" après votre insertion pour obtenir le dernier ID généré
et:
@@IDENTITY
etSCOPE_IDENTITY
renvoie la dernière valeur d'identité générée dans une table de la session en cours. Pourtant,SCOPE_IDENTITY
renvoie la valeur uniquement dans la portée actuelle;@@IDENTITY
n'est pas limité à une portée spécifique.
Edit: Comme indiqué dans les commentaires, vous devez toujours utiliser SCOPE_IDENTITY
, ne pas @@IDENTITY
.