我有以下SP:
ALTER Procedure [dbo].[SP_RegisterComp]
@CompName varchar(100)
,@Check_In datetime
,@ID int output
As
Set NoCount On
Update Host Set [Check_In]=@Check_In
Where [CompName]=@CompName
If @@RowCount=0
Insert into Host values (@CompName, @Check_In)
SET @ID=SCOPE_IDENTITY()
RETURN @ID
这很好用。如果表中已存在计算机名称,则更新签入时间,否则将创建新记录并返回ID。
如果更新记录,我将如何获取@id?
干杯,
约翰
答案 0 :(得分:3)
只需检查行是否已经存在,而不是让@@ROWCOUNT
告诉您是否需要插入。
ALTER PROCEDURE [dbo].[SP_RegisterComp]
@CompName varchar(100)
,@Check_In datetime
,@ID int output
AS
SET NOCOUNT ON;
SELECT TOP 1 @Id = [IdField] FROM Host WHERE [CompName] = @CompName
ORDER BY [Check_In] DESC
IF (@Id IS NOT NULL)
BEGIN
UPDATE Host SET [Check_In]=@Check_In WHERE [IdField] = @Id
END
ELSE
BEGIN
INSERT INTO Host VALUES (@CompName, @Check_In)
SET @ID=SCOPE_IDENTITY()
END
RETURN @ID
答案 1 :(得分:1)
您可以设置Output
参数。代码可能如下所示:
using (SqlConnection c = new SqlConnection(cString))
using (SqlCommand cmd = new SqlCommand("SP_RegisterComp", c))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@CompName", compName);
cmd.Parameters.AddWithValue("@Check_In", checkIn);
var outParm = new SqlParameter("@ID", SqlDbType.Int);
outParm.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
var val = outParm.Value;
}
正如Aaron所说,这是一个非常好的锁定候选者,事务编程也是最好的做法。因此,修改后的代码可能如下所示:
lock (_lockObj)
{
using (SqlConnection c = new SqlConnection(cString))
using (SqlTransaction tran = c.BeginTransaction())
using (SqlCommand cmd = new SqlCommand("SP_RegisterComp", c, tran))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@CompName", compName);
cmd.Parameters.AddWithValue("@Check_In", checkIn);
var outParm = new SqlParameter("@ID", SqlDbType.Int);
outParm.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
// commit the transaction
tran.Commit();
var val = outParm.Value;
}
}
其中_lockObj
被定义为private object _lockObj = new Object();
字段。
注意:您不必担心此处Rollback
,因为如果引发异常,Rollback
将在Dispose
期间发出} SqlTransaction
对象。
答案 2 :(得分:0)
由于您必须已将其发送,因此它已经在@Id
t-sql变量中,这是一个输出变量,因此可以在客户端ado.net代码中访问
我喜欢以下模式
Alter Procedure [dbo].[SP_RegisterComp]
@CompName varchar(100),
@Check_In datetime.
@ID int = null
As
Set NoCount On
If @Id is null
Begin
Insert ...
SET @ID=SCOPE_IDENTITY()
End
Else Begin
Update ...
Where id = @Id
End
Select @Id id
Return 0
然后在客户端代码中,您将获得单行,单列结果集(ADO.Net表),其中包含id值。
答案 3 :(得分:0)
您应该检查记录是否存在:
If EXISTS (SELECT * FROM Host WHERE [CompName] = @CompName)
BEGIN
BEGIN TRAN
SELECT @ID=ID FROM Host WITH(UPDLOCK)
WHERE Comp_Name = @Comp_Name
UPDATE Host
SET [Check_In] = @Check_In
WHERE [Comp_Name] = @Comp_Name
RETURN @ID
COMMIT TRAN
END
ELSE
BEGIN
Insert into Host values (@CompName, @Check_In)
SET @ID=SCOPE_IDENTITY()
RETURN @ID
END