Jam*_*ean 14 sql-server linked-server
我正在设置一个作业来遍历链接服务器列表并对每个服务器执行特定查询。我正在尝试在 TRY-CATCH 块内执行查询,因此如果某个特定服务器出现问题,我可以将其记录下来,然后继续处理其他服务器。
我在循环内执行的查询如下所示:
BEGIN TRY
SELECT *
FROM OPENQUERY([server1], 'SELECT 1 AS c;');
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH;
PRINT 'We got past the Catch block!';
Run Code Online (Sandbox Code Playgroud)
如果连接到服务器出现问题,代码会立即失败并且不会传输到CATCH块。如果服务器连接但在实际查询中存在错误,例如被零除,那么这会被CATCH块按预期捕获。
例如,我为一个我知道不存在的名称创建了一个链接服务器。执行上述操作时,我只得到:
OLE DB provider "SQLNCLI" for linked server "nonserver" returned message
"Login timeout expired".
OLE DB provider "SQLNCLI" for linked server "nonserver" returned message
"An error has occurred while establishing a connection to the server.
When connecting to SQL Server 2005, this failure may be caused by the
fact that under the default settings SQL Server does not allow remote
connections.".
Msg 53, Level 16, State 1, Line 0
Named Pipes Provider: Could not open a connection to SQL Server [53].
Run Code Online (Sandbox Code Playgroud)
我已经阅读了 BOLTRY-CATCH并且知道它不会捕获破坏连接的 20+ 级错误,但情况似乎并非如此(这只是 16 级)。
有谁知道为什么没有正确捕获这些错误?
Aar*_*and 11
您可以尝试的一件事是使用sp_testlinkedserver. 您还可以发出OPENQUERYusing 动态 SQL(正如 Max 正确指出的那样),将验证服务器名称的解析器推迟到运行时。
BEGIN TRY
EXEC sp_testlinkedserver N'server1';
EXEC sp_executesql N'SELECT * FROM OPENQUERY([server1],
''SELECT 1 AS c;'');';
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH;
PRINT 'We got past the Catch block!';
Run Code Online (Sandbox Code Playgroud)
虽然这在没有sp_testlinkedserver.
此外,由于如果sp_testlinkedserver失败,它实际上在编译时失败,您可以推迟它并仍然通过在那里使用动态 SQL 来捕获它:
BEGIN TRY
EXEC master.sys.sp_executesql N'EXEC sp_testlinkedserver N''server1'';';
...
END TRY
Run Code Online (Sandbox Code Playgroud)
你有没有尝试过这样的事情?
BEGIN TRY
DECLARE @cmd nvarchar(max);
SET @cmd = 'SELECT * FROM OPENQUERY([server1], ''SELECT 1 AS c;'');';
EXEC sp_executesql @cmd;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH;
Run Code Online (Sandbox Code Playgroud)
根据下面的评论,这是有效的,因为在编译时不再生成错误。该错误现在发生在运行时,位于 sp_executesql 存储过程中。