使用链接服务器连接时,使用IF-ELSE的SQL server脚本出错

使用链接服务器连接时,使用IF-ELSE的SQL server脚本出错,sql,sql-server,Sql,Sql Server,在SQL中处理数据迁移脚本时,我们必须使用多个表处理多个数据库。 希望创建一个通用脚本,其中包含我们需要迁移的所有表。 问题是,并非所有数据库都包含每个表。 因此,我采取了检查表是否存在的方法,如果存在,则复制数据 它工作得很好,直到它必须从链接服务器拉取数据为止。当它必须考虑链接服务器时,它似乎忽略了所有if条件 IF (exists (select * from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NA

在SQL中处理数据迁移脚本时,我们必须使用多个表处理多个数据库。 希望创建一个通用脚本,其中包含我们需要迁移的所有表。 问题是,并非所有数据库都包含每个表。 因此,我采取了检查表是否存在的方法,如果存在,则复制数据

它工作得很好,直到它必须从链接服务器拉取数据为止。当它必须考虑链接服务器时,它似乎忽略了所有if条件

IF (exists (select * from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'local_ArCreateLinesLog')
and exists(select * from [SQVM\KUS1].[CAPE].INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' and TABLE_NAME = 'local_ArCreateLinesLog'))    
BEGIN
declare @cnt as int, @cnt1 as int
select @cnt=count(*) from Local_ArCreateLinesLog where local_ArCreateLinesLogSqlID = (select sqlserver from sqlservers where hostname = 'SQVM\KUS1' and databasename = 'CAPE')
--print 'KUS5 Local_ArCreateLinesLog Record Count: ' + cast(@cnt as varchar(5))
select @cnt1=count(*) from [SQVM\KUS1].[CAPE].[dbo].[Local_ArCreateLinesLog] where local_ArCreateLinesLogSqlID = (select sqlserver from sqlservers where hostname = 'SQVM\KUS1' and databasename = 'CAPE')
--print 'KUS1 Local_ArCreateLinesLog Record Count: ' + cast(@cnt1 as varchar(5))
--if @cnt <> @cnt1
--BEGIN
    print '!!!!COUNTS DONOT MATCH!!!!'
--END
END
ELSE
BEGIN
    print 'Table Local_ArCreateLinesLog Does Not Exist in this Partner'
END
这是真的,链接服务器中不存在该表,这就是为什么在进程开始时使用if语句的原因

因此,我的问题是,在处理链接服务器时,我是否缺少使此sql脚本遵守if条件的某些内容

这两台SQL Server都是2008R2,并修补到同一级别。

试试这个

改变这个

IF (
    EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'local_ArCreateLinesLog' )
    AND EXISTS ( SELECT * FROM [SQVM\KUS1].[CAPE].INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'local_ArCreateLinesLog' )
)    
BEGIN ...
SELECT @cnt = COUNT( * ) FROM Local_ArCreateLinesLog WHERE local_ArCreateLinesLogSqlID = ( SELECT sqlserver FROM sqlservers WHERE hostname = 'SQVM\KUS1' AND databasename = 'CAPE' );
对此

IF (
    EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'local_ArCreateLinesLog' )
)    
BEGIN ...
然后改变这个

IF (
    EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'local_ArCreateLinesLog' )
    AND EXISTS ( SELECT * FROM [SQVM\KUS1].[CAPE].INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'local_ArCreateLinesLog' )
)    
BEGIN ...
SELECT @cnt = COUNT( * ) FROM Local_ArCreateLinesLog WHERE local_ArCreateLinesLogSqlID = ( SELECT sqlserver FROM sqlservers WHERE hostname = 'SQVM\KUS1' AND databasename = 'CAPE' );
对此

BEGIN TRY
    EXEC sp_executesql N'SELECT @cnt = COUNT( * ) FROM Local_ArCreateLinesLog WHERE local_ArCreateLinesLogSqlID = ( SELECT sqlserver FROM sqlservers WHERE hostname = ''SQVM\KUS1'' AND databasename = ''CAPE'' )', N'@cnt INT OUTPUT', @cnt=@cnt OUTPUT;
END TRY
BEGIN CATCH
    SET @cnt = 0;
END CATCH

使用链接服务器可能非常奇怪。IF/EXISTS失败的原因是SQL Server在执行之前编译元,而在您的情况下,当表不存在时,会失败。您也不能在TRY/CATCH块中捕获编译错误,因此调用sp_executesql,它不首先编译,而且还有被捕获和处理的额外好处。

检查这一点:查询解析器在编译查询时尝试验证查询的所有部分,这就是此结果的发生方式。要解决此问题,您需要将
计数(*)
查询改为动态查询。SQL Server在到达代码运行的执行步骤之前不会验证动态查询。@CR241我正在使用SQL链接服务器的完全限定名称,因此不认为这是导致问题的原因。这就是我现在所做的,它正在按需工作。谢谢