SQL 服务器链接服务器查询 w/ ANSI_WARNINGS OFF
SQL Server Linked Server Queries w/ ANSI_WARNINGS OFF
我正在尝试使用 SQL Server (2014) 中的链接服务器功能来 运行 来自存储过程的跨服务器查询(计算)。
存储过程最初设计用于运行使用动态T-SQL(通过sp_executeSQL
)的本地查询(计算)。该表达式由我们的应用程序生成,可以是任何算术表达式。
一个简单的例子(A / B)
查询实现如下:
(dynamic sql)
SELECT f1.Value / f2.Value
FROM dbo.DimDate d
INNER JOIN
dbo.vAverageData f1 ON f1.ParentID=x and f1.TimeStamp = d.TimeStamp
INNER JOIN
dbo.vAverageData f2 ON f2.ParentID=y f2.TimeStamp = d.TimeStamp
WHERE d.TimeStamp BETWEEN @StartDateTime AND @EndDateTime
现在,有趣的是 none 的计算表达式检查或处理条件,例如被零除。相反,原始开发人员决定在执行任何动态 T-SQL 之前发出两条语句:
SET ANSI_WARNINGS OFF
SET ARITHABORT OFF
这多年来一直运作良好,直到有一天,有人问我们是否可以执行跨服务器查询。自然地,我脑海中浮现的第一个选择是实现 (1) 两个服务器之间的链接服务器连接,以及 (2) 修改动态 T-SQL 生成代码(在我们的应用程序中)为每个对象添加前缀链接服务器名称和数据库名称。
上面的例子会被转换成这样:
(dynamic sql)
SELECT f1.Value / f2.Value
FROM dbo.DimDate d
INNER JOIN
dbo.vAverageData f1 ON f1.ParentID=x and f1.TimeStamp = d.TimeStamp
INNER JOIN
*<LinkedServer>.<RemoteDatabase>*.dbo.vAverageData f2 ON f2.ParentID=y f2.TimeStamp = d.TimeStamp
WHERE d.TimeStamp BETWEEN @StartDateTime AND @EndDateTime
第一次,我尝试 运行 其中一个跨服务器查询,我收到了臭名昭著的:
"Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS
options to be set for the connection. This ensures consistent query
semantics. Enable these options and then reissue your query."
显然,最简单的方法是删除上面提到的 SET
调用。但是,在我们的例子中,它们确实有一个目的,可以防止 query/transaction 在被零除、溢出等情况下中止
在这一点上(没有重大重写),假设我们必须有那些 SET 调用......
有什么办法可以在不删除 SET 调用的情况下完成这项工作吗?遥控器server/database有什么设置可以设置吗?在链接服务器对象上呢?
我没试过,但是有启用 ANSI 警告等的数据库属性。如果在两个数据库上设置一致,这会修复它吗?这是 bad/dangerous 做法吗?
两个服务器都是 SQL Server (2014) 的完全相同版本,两个数据库都包含我们的代码,即我们可以更改任何我们想要的。
无论链接服务器的类型是什么,根据找到的 BOL 都无法绕过它 here。
A connection must have the ANSI_NULLS and ANSI_WARNINGS options set ON
before the connection can execute distributed queries. For more
information, see SET ANSI_DEFAULTS (Transact-SQL)
一种解决方法是通过添加如下语句来修改查询。通过制作远程的本地副本 table,您可以最大限度地减少不需要的选项的使用,并最大限度地减少其他地方的更改。
SET ANSI_WARNINGS ON;
SELECT Columns_Used_For_Query INTO #Temporary_Table
FROM Remote_Table
WHERE Search_Condition;
SET ANSI_WARNINGS OFF;
--Do other stuff
就性能而言,这可能不是最佳解决方案,尤其是当适当的索引至关重要时。但那是你的测试。
附带说明一下,如果您仍然收到相同的错误消息,那么这很可能意味着存储过程是使用 ANSI_NULLS OFF
创建的,在这种情况下,您需要打开该选项然后 ALTER
。存储过程在创建和更改时记住 ANSI_NULLS 和 QUOTED_IDENTIFIER 设置。
我正在尝试使用 SQL Server (2014) 中的链接服务器功能来 运行 来自存储过程的跨服务器查询(计算)。
存储过程最初设计用于运行使用动态T-SQL(通过sp_executeSQL
)的本地查询(计算)。该表达式由我们的应用程序生成,可以是任何算术表达式。
一个简单的例子(A / B)
查询实现如下:
(dynamic sql)
SELECT f1.Value / f2.Value
FROM dbo.DimDate d
INNER JOIN
dbo.vAverageData f1 ON f1.ParentID=x and f1.TimeStamp = d.TimeStamp
INNER JOIN
dbo.vAverageData f2 ON f2.ParentID=y f2.TimeStamp = d.TimeStamp
WHERE d.TimeStamp BETWEEN @StartDateTime AND @EndDateTime
现在,有趣的是 none 的计算表达式检查或处理条件,例如被零除。相反,原始开发人员决定在执行任何动态 T-SQL 之前发出两条语句:
SET ANSI_WARNINGS OFF
SET ARITHABORT OFF
这多年来一直运作良好,直到有一天,有人问我们是否可以执行跨服务器查询。自然地,我脑海中浮现的第一个选择是实现 (1) 两个服务器之间的链接服务器连接,以及 (2) 修改动态 T-SQL 生成代码(在我们的应用程序中)为每个对象添加前缀链接服务器名称和数据库名称。
上面的例子会被转换成这样:
(dynamic sql)
SELECT f1.Value / f2.Value
FROM dbo.DimDate d
INNER JOIN
dbo.vAverageData f1 ON f1.ParentID=x and f1.TimeStamp = d.TimeStamp
INNER JOIN
*<LinkedServer>.<RemoteDatabase>*.dbo.vAverageData f2 ON f2.ParentID=y f2.TimeStamp = d.TimeStamp
WHERE d.TimeStamp BETWEEN @StartDateTime AND @EndDateTime
第一次,我尝试 运行 其中一个跨服务器查询,我收到了臭名昭著的:
"Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS options to be set for the connection. This ensures consistent query semantics. Enable these options and then reissue your query."
显然,最简单的方法是删除上面提到的 SET
调用。但是,在我们的例子中,它们确实有一个目的,可以防止 query/transaction 在被零除、溢出等情况下中止
在这一点上(没有重大重写),假设我们必须有那些 SET 调用......
有什么办法可以在不删除 SET 调用的情况下完成这项工作吗?遥控器server/database有什么设置可以设置吗?在链接服务器对象上呢?
我没试过,但是有启用 ANSI 警告等的数据库属性。如果在两个数据库上设置一致,这会修复它吗?这是 bad/dangerous 做法吗?
两个服务器都是 SQL Server (2014) 的完全相同版本,两个数据库都包含我们的代码,即我们可以更改任何我们想要的。
无论链接服务器的类型是什么,根据找到的 BOL 都无法绕过它 here。
A connection must have the ANSI_NULLS and ANSI_WARNINGS options set ON before the connection can execute distributed queries. For more information, see SET ANSI_DEFAULTS (Transact-SQL)
一种解决方法是通过添加如下语句来修改查询。通过制作远程的本地副本 table,您可以最大限度地减少不需要的选项的使用,并最大限度地减少其他地方的更改。
SET ANSI_WARNINGS ON;
SELECT Columns_Used_For_Query INTO #Temporary_Table
FROM Remote_Table
WHERE Search_Condition;
SET ANSI_WARNINGS OFF;
--Do other stuff
就性能而言,这可能不是最佳解决方案,尤其是当适当的索引至关重要时。但那是你的测试。
附带说明一下,如果您仍然收到相同的错误消息,那么这很可能意味着存储过程是使用 ANSI_NULLS OFF
创建的,在这种情况下,您需要打开该选项然后 ALTER
。存储过程在创建和更改时记住 ANSI_NULLS 和 QUOTED_IDENTIFIER 设置。