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'.
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'
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