SQL Azure 作为链接服务器 -> 获取插入行的标识

Posted

技术标签:

【中文标题】SQL Azure 作为链接服务器 -> 获取插入行的标识【英文标题】:SQL Azure as a linked server -> get identity of inserted row 【发布时间】:2012-09-03 11:12:31 【问题描述】:

我已经将我们的 Azure 云数据库设置为连接到我们的“SQL server 2008 R2”服务器的链接服务器,如下所述:http://blogs.msdn.com/b/sqlcat/archive/2011/03/08/linked-servers-to-sql-azure.aspx 我启用了 RPC 和 RPC Out,因为我在某处读到过。

现在的问题是我无法获取刚刚插入的记录的 ID。请看一下这个测试表:

CREATE TABLE dbo.TEST
(
   ID INT IDENTITY(1, 1) NOT NULL
   CONSTRAINT PK_TEST_ID PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

我也创建了这个存储过程:

CREATE PROCEDURE test_create @ID INT OUTPUT
AS
  BEGIN
      -- SET NOCOUNT ON added to prevent extra result sets from
      -- interfering with SELECT statements.
      SET NOCOUNT ON;

      INSERT INTO TEST
      DEFAULT VALUES

      SELECT @ID = SCOPE_IDENTITY()
  END

我尝试通过多种方式获取最后插入的值,但没有一种方法有效:

DECLARE @ID INT

EXEC AZURE01.TestDB.dbo.test_create @ID OUTPUT
SELECT @ID

INSERT INTO AZURE01.TestDB.dbo.TEST DEFAULT VALUES
SELECT @ID = SCOPE_IDENTITY();
SELECT @ID

INSERT INTO AZURE01.TestDB.dbo.TEST DEFAULT VALUES
SELECT @ID = @@IDENTITY
SELECT @ID

SELECT * FROM OPENQUERY(AZURE01, 'INSERT INTO TestDB.dbo.TEST DEFAULT VALUES; SELECT SCOPE_IDENTITY() AS ID');

DECLARE @ScopeIdentity TABLE (ID int);
INSERT INTO @ScopeIdentity
EXEC AZURE01.master..sp_executesql N'
  INSERT TestDB.dbo.TEST DEFAULT VALUES;
  SELECT SCOPE_IDENTITY()';
SELECT * FROM @ScopeIdentity;

INSERT AZURE01.TestDB.dbo.TEST 
OUTPUT inserted.ID
INTO @ScopeIdentity
DEFAULT VALUES
SELECT * FROM @ScopeIdentity

我明白为什么 SCOPE_IDENTITY() 和 @@IDENTITY 不起作用(因为它们是本地函数/变量,没有来自链接服务器的信息)但是带有输出参数的存储过程应该起作用,对吗? (在它工作的服务器上本地)

有人吗? :-)

【问题讨论】:

get @@Identity from another server(linked server)的可能重复 唯一的问题是该解决方案对我没有帮助,因为:“在包含 OUTPUT 子句或嵌套 DML 语句的语句中,不能将远程表用作 DML 目标。”跨度> 在他们建议使用存储过程的 cmets 中,这也行不通。 你重试了吗?他们刚刚宣布官方支持链接服务器到 Azure SQL 数据库:blogs.msdn.com/b/windowsazure/archive/2012/09/19/… 我试过了.. 仍然没有运气。我也在 Windows Azure 表单上问过它:social.msdn.microsoft.com/Forums/en-US/ssdsgetstarted/thread/… 【参考方案1】:

您是否考虑过使用 GUID (uniqueidentifier) 字段来代替 int 或同时使用 int

然后您可以在客户端生成 ID(有许多工具可以生成 GUID)并将其直接传递到您的插入中。

然后,您可以选择基于 GUID 列重新选择行以获取新的 int 值,或者仅使用 GUID 字段作为您的 PK 并完成它。

【讨论】:

这是一个很好的建议,但不幸的是不是我要找的那个......无论如何,谢谢!【参考方案2】:

--在 azure 数据库上创建 proc

create proc xxp_GetId

as

begin

--exec xxp_GetId

DECLARE @ID INT

INSERT INTO dbo.bit_CubeGetParameter DEFAULT VALUES 

SELECT @ID = SCOPE_IDENTITY();

SELECT @ID

end

-- 现在在你的 sql server 上运行这个查询

exec <"Link Server">.<"Azure Database Name">.dbo.xxp_GetId

【讨论】:

这确实会选择正确的数字,但我需要将它存储在一个变量中,以便我可以更新本地记录,所以在此之后我需要类似:SET @ID = EXEC ..dbo.xxp_GetId。有什么建议吗?【参考方案3】:

问题是远程服务器执行。

你可以尝试的是:

在 LinkedServer 处执行 @TSqlBatch

它的作用是告诉另一端的数据库在本地执行 tsql。 这有很多用途。也许它也可以在这种情况下使用,因为 Scope_Identity() 应该与插入一起在本地执行。

【讨论】:

以下查询确实返回了插入的 id:EXEC ('INSERT INTO TestDb.dbo.test DEFAULT VALUES; SELECT SCOPE_IDENTITY()') AT [Azure01],但我无法使用结果将其加入或选择到变量中:OLE DB provider "MSDASQL" for linked server "Azure01" returned message "[Microsoft][SQL Server Native Client 10.0]The partner transaction manager has disabled its support for remote/network transactions. The operation could not be performed because OLE DB provider "MSDASQL" for linked server "Azure01" was unable to begin a distributed transaction.

以上是关于SQL Azure 作为链接服务器 -> 获取插入行的标识的主要内容,如果未能解决你的问题,请参考以下文章

Azure ADF 管道无法连接到 Azure SQL

将 SQL 查询结果作为 txt 文件自动导出到 Azure Blob 存储

无法在 Azure 数据工厂中创建链接服务

Azure 托管 SQL - ODBC 驱动程序

从 SQL Azure 迁移到 SQL Server

到 Azure SQL 数据库的数据流输出仅包含 Azure 数据工厂中的 NULL 数据