2

I'm in the process of creating a view but before doing so I'm testing and working with multiple linked servers returning column values in a select union statement, I use the following simple code:

    SELECT * FROM OPENQUERY ([linkedserver1],'SELECT TOP 1 [Column1], [Column2] FROM [db].[table]')
    UNION ALL
    SELECT * FROM OPENQUERY ([linkedserver2],'SELECT TOP 1 [Column1], [Column2] FROM [db].[table]')
    UNION ALL
    SELECT * FROM OPENQUERY ([linkedserver3],'SELECT TOP 1 [Column1], [Column2] FROM [db].[table]')

It returns the following results as intended:

    |Column1|Column2|
    | 001   | Pass  |
    | 010   | Pass  |
    | 100   | Pass  |

But my problem comes in that when one of the linked servers go offline example [linkedserver2], no results get shown and I only get:

    OLE DB provider "SQLNCLI11" for linked server "[linkedserver2]" returned
    message "Login timeout expired".
    OLE DB provider "SQLNCLI11" for linked server "[linkedserver2]" returned
    message "A network-related or instance-specific error has occurred while
    establishing a connection to SQL Server. Server is not found or not
    accessible. Check if instance name is correct and if SQL Server is
    configured to allow remote connections. For more information see SQL
    Server Books Online.".

    Msg 53, Level 16, State 1, Line 0
    Named Pipes Provider: Could not open a connection to SQL Server [53]. 

The error is obvious, but what I'd like to know is if I can put anything in my query that will continue to execute and return results for the other two linked servers and just skip [linkedserver2] as shown below:

    |Column1|Column2|
    | 001   | Pass  |
    | 100   | Pass  |

I was thinking about using Try...Catch but I'm not a SQL guru to that extent yet. Any help would be appreciated!

Thanks.

Brakkie101
  • 149
  • 1
  • 2
  • 12
  • Take a look @ https://dba.stackexchange.com/questions/36178/linked-server-error-not-caught-by-try-catch – Alex K. Jul 12 '18 at 12:00
  • Not with a `UNION ALL`, but you can split the `SELECT`s into separate statements that are dynamically executed and insert their results in a temp table. This, of course, will not work inside a view, and I'm pretty sure you're absolutely out of luck there, since the command will not even get an execution plan if the server is unreachable. A table-valued function won't work either, since `TRY .. CATCH` is not allowed in there. A stored procedure could do it, though. By now you should have a good idea of why linked servers are often a problem... – Jeroen Mostert Jul 12 '18 at 12:21

1 Answers1

4

Thanks Alex K. for pointing me in what I needed to see regarding the TRY..CATCH to assist me in getting what I needed working. :)

Jeroen Mostert I checked what you were saying and I couldn't let it go so I played around with some stuff as well as the TRY..CATCH link Alex K. commented and I got somewhat of a solution with the UNION ALL working.

It ain't pretty but it at least works:

    DECLARE @name NVARCHAR(100)
    DECLARE @sql as nvarchar(max)=N''
    DECLARE @Query NVARCHAR(MAX)
    DECLARE getid CURSOR FOR
    SELECT name FROM sys.servers where is_linked = 1

    OPEN getid

    FETCH NEXT FROM getid INTO @name

    WHILE @@FETCH_STATUS = 0
    BEGIN
    BEGIN TRY
         exec sys.sp_testlinkedserver @name
         SET @sql=@sql+N'SELECT * FROM ['+ @name +'].[pacific].[Alarms].[Alarm] UNION All '
    END TRY
    BEGIN CATCH
    END CATCH

    FETCH NEXT FROM getid INTO @name

    END

    SET @Query = substring(@sql, 0, (len(@sql) - 9))
    CLOSE getid
    DEALLOCATE getid

    EXEC sp_executesql @Query

Thanks Guys for the help!

Brakkie101
  • 149
  • 1
  • 2
  • 12