Search code examples
sql-server-2008t-sqllinked-server

Programatically check for existing login for a linked server


I'm writing an admin script I can use for creating linked servers. The script does a IF EXISTS check on the linked server before creating, this works fine.

I have added the sp_addlinkedsrvlogin details to the script to generate the appropriate permissions to access the linked server.

When I try to re-run thescript again it throws the error:

Msg 15190, Level 16, State 1, Procedure sp_dropserver, Line 56 There are still remote logins or linked logins for the server 'LinkedServerName'.

So my question is:

What is the specific code to check for existence of a login for a linked server?

This will allow me to conditionally EXEC sp_droplinkedsrvlogin before issuing the conditional EXEC sp_dropserver



Code as it stands now:

-- Set to master
    USE master
    GO

-- Set linked server vars
    DECLARE
        @ServerName         varchar(max)    =   'Server Name'       -- Name you wish to give to the Linked Server connection. To remove ambiguity you can name this the same as the Data Source you are connecting to.
        ,@ProductName       nvarchar(128)   =   'Product Name'      -- Type of OLE DB product you are connecting too, i.e. Oracle or SQL Server, e.g. SQl Server = N'MSSQL'.
        ,@ProviderName      nvarchar(128)   =   'Provider Name'     -- The OLE DB provider is expected to be registered with the specified PROGID in the registry, e.g. SQL Server = N'SQLNCLI'.
        ,@DataSource        nvarchar(4000)  =   'Source Name'       -- Is the name of the data source as interpreted by the OLE DB provider, i.e. the actual server name if connecting to MS SQL Server.
        ,@Location          nvarchar(4000)  =   'Location'          -- Not really worth using, listed for compelteness according to Reference 1 Location.           
        ,@ProviderString    nvarchar(4000)
        ,@CatalogName       nvarchar(4000)  =   'Database Name'     -- (Optional) Name of the database/catalog you will connect to. 
    SET
        @ProviderString =   'PROVIDER=SQLOLEDB; SERVER=' + @ServerName

-- Set linked server login vars
    DECLARE
        @Useself            varchar(8)      =   'Option'            -- 'TRUE' or 'FALSE' or NULL. Determines whether to connect to @rmtsrvname\@ServerName by impersonating local logins or explicitly submitting a login and password.
        ,@LocalLogin        varchar(100)    =   'Domain\Login'      -- Domain account.
        ,@User              varchar(50)     =   'SQL user'          -- Is the remote login used to connect to rmtsrvname when @useself\@Useself is FALSE.
        ,@Password          varchar(20)     =   'Password'          -- Is the password associated with @rmtuser\@User.

-- Drop linked server if already exists to prevent error when creating
    IF  EXISTS
        (
            SELECT  *
            FROM    sys.servers
            WHERE   server_id   !=  0
                    AND name    =   @ServerName
        )  
        EXEC    sp_dropserver
                @ServerName

-- Create linked server         
    EXEC    sp_addlinkedserver  
            @server         =   @ServerName
            ,@srvproduct    =   @ProductName
            ,@provider      =   @ProviderName
            ,@datasrc       =   @DataSource
            ,@location      =   @Location
            ,@provstr       =   @ProviderString
            ,@catalog       =   @CatalogName

-- Add permissions for usage            
    EXEC    sp_addlinkedsrvlogin 
            @rmtsrvname     =   @ServerName
            ,@useself       =   @Useself
            ,@locallogin    =   @LocalLogin
            ,@rmtuser       =   @User
            ,@rmtpassword   =   @Password

Answer accepted below. I also found that you can force logins to be dropped when dropping a linked server by passing the argument ,@droplogins = 'droplogins' to the EXEC sp_dropserver proc:

IF  EXISTS
    (
        SELECT  1
        FROM    sys.servers
        WHERE   server_id   !=  0
                AND name    =   @ServerName
    )  
    EXEC    sp_dropserver
            @server         =   @ServerName
            ,@droplogins    =   'droplogins'

Solution

  • select 1 
    from sys.remote_logins l
    inner join sys.servers s
    on l.server_id = s.server_id
    where s.name = @ServerName 
    and l.remote_name = @User --check on remote user
    

    or

    select 1 
    from sys.remote_logins l
    inner join sys.servers s
        on l.server_id = s.server_id
    inner join sys.server_principals p
        on l.local_principal_id = p.principal_id
    where s.name = ServerName 
    and p.name = @LocalLogin --check on local user