我正在使用VB.Net事务来执行两个查询。有两张桌子和一张桌子。以下是一个示例结构。
USER
----
1. USER_ID - int (PK) AUTO_INCREMENT
2. USER_NAME - varchar(20)
ADDRESS
-----
1. USER_ID
2. USER_ADDRESS
由于这个基本结构代表一个用户可以拥有很多照片。每当我向USER表插入新记录时,应使用自动创建的USER_ID保存用户的照片。
我知道我需要为此目的使用SCOPE_IDENTITY(),但我总是为SCOPE_IDENTITY()值获取NULL,这不是因为触发器或其他任何原因。问题在于VB.Net如何创建我的INSERT语句。
以下是SQLServer Profiler中查询的外观
插入USER表
exec sp_executesql N'INSERT INTO USER(USER_NAME) VALUES (@USER_NAME)',N'@USER_NAME nvarchar(4)',@USER_NAME =N'ABCD'
插入地址表
exec sp_executesql N'INSERT INTO ADDRESS(USER_ID,USER_ADDRESS) VALUES ((SELECT SCOPE_IDENTITY()),@USER_ADDRESS)',N'@ USER_ADDRESS nvarchar(10)',@USER_ADDRESS=N'ABCDEFGHIJ'
我已将SELECT SCOPE_IDENTITY()直接附加到第二个查询&我认为SQL认为命令SCOPE_IDENTITY()是一个字符串,我该如何防止这种情况发生。
答案 0 :(得分:4)
顾名思义,scope_identity()
是范围的本地。 sp_executesql
在its own scope内运行。稍后对sp_executesql
的调用没有对早期范围的记忆。
最合乎逻辑的解决方案是在同一范围内运行两个查询。我不确定你使用sp_executesql
的原因;也许你可以省略它。大多数客户运行如下:
INSERT INTO USER(USER_NAME) VALUES (@USER_NAME);
SELECT SCOPE_IDENTITY() AS ID;
客户端程序可以从生成的行集中获取ID
。然后,它可以将ID
作为参数传递给INSERT
地址查询。不需要sp_executesql
。
如果您必须使用多个sp_executesql
,请考虑使用output
参数来传送身份:
declare @ID bigint
exec sp_executesql
N'INSERT INTO USER(USER_NAME) VALUES (@USER_NAME);
SELECT @ID = SCOPE_IDENTITY();',
N'@USER_NAME nvarchar(4), @ID bigint output',
@USER_NAME = N'ABCD',
@ID = @ID output;
现在,您可以将@ID
作为变量传递给第二个sp_executesql
。