Should I use a localhost linked server or the HOST_NAME() function to avoid hard-coding this SQL Server hostname?

StackOverflow https://stackoverflow.com/questions/17934098

سؤال

I inherited a legacy system that has two SQL Server instances on the same server. Occasionally, some user action causes some records to be "synchronized" across the instances. The system uses a "linked server" so a sproc on the main instance can query the other instance. The sys.servers table has these records:

| server_id | name        | 
=========================== 
| 0         | sql08\main  |
| 1         | sql08\other |

The website that invokes the sproc stores the linked server name in a configuration file. I guess they expected it to change at some point, but it never has. It's always on the same host as the main instance.

<appSettings>
  <add key="LinkedServer" value="sql08\other" />
</appSettings>

And that is passed to the sproc to generate a dynamic SQL statement. I'll skip the ADO.NET command/parameter stuff, it's all normal. The sproc does something like this:

DECLARE @sql VARCHAR(MAX) = 'SELECT * FROM [' + @LinkedServer + '].db.schema.table WHERE ...'
EXEC sp_executesql @sql

I used web.config transforms to support pointing the Debug configuration to a test environment and the Release configuration to production. But, I also need it to function on any developer workstation, which implies using localhost, not the actual hostname.

Option A: Add a Special Linked Server

I can require a special linked server using localhost instead of the hostname. I don't like that it's different than the test/production environments and will require custom setup. Are there any "gotchas" here? I couldn't find any guidance one way or the other.

EXEC sp_addlinkedserver 'localhost\other', @srvproduct = 'SQL Server'

Option B: Drop the Setting

Or, given that the linked server is always on the same host, I could use the host_name() function in the sproc, removing the need for configuration at all. Is there anything to watch out for if I use this option, besides the chance that the linked server moves?

DECLARE @sql VARCHAR(MAX) = 'SELECT * FROM [' + HOST_NAME() + '\other].db.schema.table WHERE ...'
EXEC sp_executesql @sql
هل كانت مفيدة؟

المحلول

I would suggest using a SYNONYM in your server and in production. This way you can have different linked servers and the rest of the system is unaware.

In development:

CREATE SYNONYM dbo.linkedtable FOR [LOCALHOST\other].db.schema.table;

In production:

CREATE SYNONYM dbo.linkedtable FOR [SQL08\other].db.schema.table;

If you have a large number of these, create an additional linked server in both locations that has the same name.

If you have a script that runs on every single server you set up, then you can generate the synonym dynamically, e.g.:

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'CREATE SYNONYM dbo.linkedtable FOR ['
  + HOST_NAME() + '\other].db.schema.table;';

EXEC sp_executesql @sql;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top