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