我有一个存储过程,我在其中插入并通过调用SCOPE_IDENTITY()
检索行的ID
...
INSERT INTO [RemoteDB].[dbo].[Table] (StageID, UserID, Date)
VALUES (4, @userID, @date)
SET @id = SCOPE_IDENTITY()
INSERT INTO [RemoteDB].[dbo].[Table2] (ID)
VALUES (@id)
...
当我在同一台服务器上的3个数据库时,一切正常,但在生产中,其中一个数据库是远程的(所以我使用链接服务器)。
我的查询的第一个插入工作,但第二个插入不运行。我认为这是因为SCOPE_IDENTITY()
。
我的错误是:
OLE DB提供程序无法INSERT INTO ...“该值违反了列的完整性约束。”
这意味着它无法获得@id
的SCOPE_IDENTITY()
请注意,我执行的存储过程不在远程服务器上,它们位于本地存储过程中。
我做错了什么?
SCOPE_IDENTITY
(和类似的)不会像你想象的那样使用链接服务器。来自MSDN docs:
返回插入同一范围内的标识列的最后一个标识值。范围是一个模块:存储过程,触发器,函数或批处理。因此,如果两个语句在同一存储过程,函数或批处理中,则它们在同一范围内。
由于您的插入是在远程服务器上进行的,并且您的SCOPE_IDENTITY
调用是在本地进行的,因此它们在不同的范围内执行。因此,您的SCOPE_IDENTITY
调用可能返回NULL,因此违反约束。
你有几个选择来解决这个问题。第一种方法是在远程服务器上编写一个可以执行的存储过程,它可以a)处理一个proc中的所有插入,或者b)处理单个insert并返回插入的标识。 (或者,您可以使用dynamic-sql-esque解决方案在远程服务器上执行与建议的存储过程相同的语句。)无论您选择做什么的最终目标是您必须确保SCOPE_IDENTITY
调用在同一批次的远程服务器上发生,否则它将无法工作。