执行更新查询时获取主键作为输出还是返回?
Posted
技术标签:
【中文标题】执行更新查询时获取主键作为输出还是返回?【英文标题】:Get the primary key as output or return when you performing an Update query? 【发布时间】:2021-05-31 08:57:11 【问题描述】:我正在尝试获取主键的输出参数,即 ID。当我进行更新查询时,我得到Null
。您能建议一种方法吗?
CREATE PROCEDURE sp_InsertTax
(@ID int output,
@TaxAuthorityID int,
@TaxClassificationID int,
@EntityID int,
@AppliesTo_TaxEntityTypeID int)
AS
IF EXISTS (SELECT * FROM Tax
WHERE TaxAuthorityID = @TaxAuthorityID
AND TaxClassificationID = @TaxClassificationID
AND EntityID = @EntityID
AND AppliesTo_TaxEntityTypeID = @AppliesTo_TaxEntityTypeID)
BEGIN
UPDATE Tax
SET TaxAuthorityID = @TaxAuthorityID,
TaxClassificationID = @TaxClassificationID,
EntityID = @EntityID,
AppliesTo_TaxEntityTypeID = @AppliesTo_TaxEntityTypeID
WHERE ID = @ID
END
ELSE
BEGIN
IF @ID IS NULL
BEGIN
INSERT INTO Tax(TaxAuthorityID, TaxClassificationID, EntityID, AppliesTo_TaxEntityTypeID)
VALUES (@TaxAuthorityID, @TaxClassificationID, @EntityID, @AppliesTo_TaxEntityTypeID)
SET @ID = Scope_Identity()
END
END
GO
下面是我调用更新存储过程的ADO.NET代码:
public int InsertFederalTax(int ClassificID, int appliesTo)
int tax_id = 0;
Sqlconn.Open();
SqlCommand cmd = new SqlCommand("sp_InsertTax", Sqlconn);
cmd.CommandType = CommandType.StoredProcedure;
var returnparameter = cmd.Parameters.AddWithValue("ID", SqlDbType.Int);
returnparameter.Direction = ParameterDirection.Output;
cmd.Parameters.Add("@TaxAuthorityID", SqlDbType.Int).Value = 1;
cmd.Parameters.Add("@TaxClassificationID", SqlDbType.Int).Value = ClassificID;
cmd.Parameters.Add("@EntityID", SqlDbType.Int).Value = 0;
cmd.Parameters.Add("@AppliesTo_TaxEntityTypeID", SqlDbType.Int).Value = appliesTo;
cmd.ExecuteNonQuery();
if (!(returnparameter.Value is DBNull))
tax_id = Convert.ToInt32(returnparameter.Value);
Sqlconn.Close();
return tax_id;
【问题讨论】:
returnparameter
您永远不会将此参数添加到您的 cmd.Parameters
集合中。此外,您使用@ID
作为where
子句的一部分,因此参数方向需要为InputOutput
。
您不应该使用 SqlDbType 值添加该参数。
@RobertHarvey 将SCOPE_IDENTITY
选择为输出参数完全没问题,无需ExecuteScalar
; ExecuteNonQuery
在这里很好。
还有一个建议,先看看更新,老实说不要担心存在(不存在就不会有更新)。您可以检查@@ROWCOUNT
,然后根据需要进行插入。您现在这样做的方式可能导致死锁,因为它会扫描所有行以查找这些 id。如果它确实存在,那么你必须再次找到该行,当你不需要时不要多次旅行。
@Nick_H,请与我们分享操作系统。版本、MSSQL 版本和 .NET Framework 版本。我会生成虚拟机来制作真实的模拟案例。
【参考方案1】:
我认为您打算捕获现有重复记录的 ID,您可以执行以下操作。我还为 SP 添加了最佳实践模板项。另请注意marc_c
的评论关于不要在您的 SP 前加上 sp_
。
CREATE PROCEDURE InsertTax
(
@ID int output
, @TaxAuthorityID int
, @TaxClassificationID int
, @EntityID int
, @AppliesTo_TaxEntityTypeID int
)
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
-- This assumes that none of the parameters can ever be null
-- And from your comments we know that no duplicates can exist
SELECT @ID = ID
FROM Tax
WHERE TaxAuthorityID = @TaxAuthorityID
AND TaxClassificationID = @TaxClassificationID
AND EntityID = @EntityID
AND AppliesTo_TaxEntityTypeID = @AppliesTo_TaxEntityTypeID;
IF @ID IS NOT NULL BEGIN
UPDATE Tax
SET TaxAuthorityID = @TaxAuthorityID,
TaxClassificationID = @TaxClassificationID,
EntityID = @EntityID,
AppliesTo_TaxEntityTypeID = @AppliesTo_TaxEntityTypeID
WHERE ID = @ID;
END; ELSE BEGIN
INSERT INTO Tax (TaxAuthorityID, TaxClassificationID, EntityID, AppliesTo_TaxEntityTypeID)
VALUES (@TaxAuthorityID, @TaxClassificationID, @EntityID, @AppliesTo_TaxEntityTypeID);
SET @ID = SCOPE_IDENTITY();
END;
RETURN 0;
END;
GO
我建议将您的返回参数声明为:
var returnparameter = new SqlParameter("@ID", SqlDbType.Int)
Direction = ParameterDirection.InputOutput
;
cmd.Parameters.Add(returnparameter);
【讨论】:
我已经按照您的建议进行了尝试。我得到了返回参数。更新查询仍然存在一些问题。 我两次询问操作系统、SQL Server 和 .NET Framework 的版本列表,因为我想设置一个虚拟机来了解并了解更多正在发生的事情,但我没有还没有答案。听起来是不是很奇怪? @AntonioLeonardo 这不是网站的运作方式。也就是说使用任何版本,问题中使用的代码非常通用。 @DaleK,我只想帮助解决这个问题,使用一个场景,而不是任何场景 @DaleK 我正在从 CSV 文件导入数据。如果它们已经存在,如果不插入,我想更新。尽管我的更新查询是正确的,但它仍然会导入重复值。这意味着它不会更新值。【参考方案2】:请您尝试使用以下更新更改您的 C# 代码,并给我们反馈:
public int InsertFederalTax(int ClassificID, int appliesTo)
int tax_id = 0;
Sqlconn.Open();
SqlCommand cmd = new SqlCommand("sp_InsertTax", Sqlconn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ID", SqlDbType.Int);
cmd.Parameters["@ID"].Direction = ParameterDirection.Output;
cmd.Parameters.AddWithValue("@TaxAuthorityID", 1);
cmd.Parameters.AddWithValue("@TaxClassificationID", ClassificID);
cmd.Parameters.AddWithValue("@EntityID", 0);
cmd.Parameters.AddWithValue("@AppliesTo_TaxEntityTypeID", appliesTo);
cmd.ExecuteNonQuery();
if(!(cmd.Parameters["@ID"].Value is DBNull))
tax_id = Convert.ToInt32(cmd.Parameters["@ID"].Value);
Sqlconn.Close();
return tax_id;
【讨论】:
Nope didn't work Antonio. @Nick_H,拜托,你可以再测试一次吗?我把转换类型错误放在输出变量值上 我已经更改了转换类型,然后我尝试了上述代码。仍然没有工作。谢谢。 @Nick_H,请再次与我们分享操作系统。版本、MSSQL 版本和 .NET Framework 版本。我会生成虚拟机来制作真实的模拟案例。以上是关于执行更新查询时获取主键作为输出还是返回?的主要内容,如果未能解决你的问题,请参考以下文章