我有这个MSSQL SQLCMD代码,它可以登录数据库,并且只需执行SELECT语句:
:CONNECT czasql-001
SELECT * FROM [Lps_Hepper_Cz].[config].[LpsPlant]
GO
:CONNECT LS_Hepper_DK
SELECT * FROM [LPS_Hepper_NY].[config].[LpsPlant]
:CONNECT LS_Hepper_DK
SELECT * FROM [LPS_Hepper_DK].[config].[LpsPlant]
:CONNECT LS_Hepper_DK
SELECT * FROM [LPS_Hepper_SUPPLIER].[config].[LpsPlant]
GO
:CONNECT LS_Hepper_372
SELECT * FROM [LPS_Hepper_MO].[config].[LpsPlant]
GO
:CONNECT LS_Hepper_678
SELECT * FROM [LPS_Hepper_678].[config].[LpsPlant]
GO
此解决方案可以正常工作,但要求我多次复制粘贴副本以更改数据库名称。但是有人可以通过使用循环来帮助我改进这一点。我试过使用临时表。像这样:
declare @tbl table (ServerName nvarchar(50), DbName nvarchar(50), IsDone bit default(0))
insert into @tbl (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]')
但是,当我的数据是nvarchar时,我无法想出通过数据库迭代连接到服务器并设置数据库名称的逻辑。 有人有建议吗?
更新 我只会将其用于INSERT / UPDATE或DELETE。所以我不使用存储过程。我喜欢用它来更新我们所有数据库的数据。这就是为什么我只使用应该成为脚本一部分的临时表。
Servernames和数据库名称将来自上面的临时表。表名在所有数据库中都是相同的,因为我们在全球范围内拥有数据库副本以限制数据下载,我需要确保在更新时,我还会更新其余数据库。
更新2: 我试图玩它,但我一直停滞不前,因为无法使用临时表中的值。这意味着我无法使用:SETVAR来设置服务器名称:
declare @tbl table (ServerName nvarchar(50), DbName nvarchar(50), IsDone bit default(0))
insert into @tbl (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]')
insert into @tbl (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]')
WHILE (SELECT COUNT(*) FROM @tbl WHERE IsDone = 0) > 0
BEGIN
DECLARE @selectedRow INT = (SELECT TOP 1 Id FROM @tbl WHERE IsDone = 0)
--DECLARE @ServerName NVARCHAR(50)= (SELECT ServerName FROM @tbl WHERE Id = @selectedRow)
--DECLARE @DatabaseName NVARCHAR(50) = (SELECT DbName FROM @tbl WHERE Id = @selectedRow)
DECLARE @ServerName sysname= (SELECT ServerName FROM @tbl WHERE Id = @selectedRow)
DECLARE @DatabaseName sysname = (SELECT DbName FROM @tbl WHERE Id = @selectedRow)
:SETVAR DatabaseName @DatabaseName
:SETVAR ServerName @ServerName
SELECT ServerName --This looks correctly
print CONVERT(NVARCHAR(100),@selectedRow)
:CONNECT ServerName
USE @DatabaseName
GO
SELECT * FROM [config].[LpsPlant]
GO
UPDATE @tbl SET IsDone = 1 WHERE Id = @selectedRow
END;
答案 0 :(得分:1)
我只会将其用于INSERT / UPDATE或DELETE。所以我不使用存储过程。我喜欢用它来更新我们所有数据库的数据
如果是这种情况,您可以考虑使用 Registered Servers
:
注册服务器的好处
使用已注册的服务器,您可以:
注册服务器以保留连接信息。
确定注册的服务器是否正在运行。
轻松将对象资源管理器和查询编辑器连接到已注册的服务器。
编辑或删除已注册服务器的注册信息。
创建服务器组。
通过在注册服务器名称框中提供与其不同的值,为注册服务器提供用户友好名称 服务器名称列表。
提供已注册服务器的详细说明。
提供已注册服务器组的详细说明。
导出已注册的服务器组。
导入已注册的服务器组。
查看SQL Server的联机或脱机实例的SQL Server日志文件
- Execute Statements Against Multiple Servers Simultaneously
您可以根据以下内容创建多个组:服务器/数据库/环境(DEV / PROD / QA)。
另一种可能性是将注册的服务器导出到文件,放入源控制系统(SVN / Git)并与其他开发人员共享。
使用SSMS,您可以根据服务器组单击新查询,并立即对多个数据库执行相同的查询。
答案 1 :(得分:1)
执行以下步骤:
1)创建链接服务器。
2)运行以下脚本我修改了你的代码片段
IF OBJECT_ID('tempdb..##Results') IS NOT NULL
Truncate TABLE ##Results
else
CREATE TABLE ##Results
(id int identity ,ServerName nvarchar(50), DbName nvarchar(50), IsDone bit default(0))
-- populat link server name and db name
insert into ##Results (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]')
insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]')
insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]')
insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]')
insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]')
insert into ##Results (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]')
WHILE (SELECT COUNT(*) FROM ##Results WHERE IsDone = 0) > 0
BEGIN
DECLARE @selectedRow INT = (SELECT TOP 1 Id FROM ##Results WHERE IsDone = 0)
DECLARE @sq1 varchar (100) ='SELECT * FROM ' ; --
DECLARE @sql varchar (8000) = '';
DECLARE @FROM varchar (100) ='[config].[LpsPlant]' ;
select @sql = @sq1 + ServerName + '.'+ DbName+ @FROM FROM ##Results WHERE Id = @selectedRow
print @sql
exec @sql
UPDATE ##Results SET IsDone = 1 WHERE Id = @selectedRow
END;
答案 2 :(得分:1)
使用光标,可能是:
CREATE TABLE #TEMP (ServerName nvarchar(50), DbName nvarchar(50))
insert into #TEMP (ServerName,DbName) VALUES ('CZASQL-001', '[Lps_Hepper_CZ]')
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_DK]')
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_NY]')
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_DK', '[Lps_Hepper_Supplier]')
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_372', '[Lps_Hepper_MO]')
insert into #TEMP (ServerName,DbName) VALUES ('LS_Hepper_678', '[Lps_Hepper_678]')
DECLARE @ServerName VARCHAR(100),
@DatabaseName VARCHAR(100);
DECLARE CRS CURSOR LOCAL
FOR SELECT * FROM #TEMP
FETCH NEXT FROM CRS INTO @ServerName, @DatabaseName;
WHILE @@FETCH_STATUS=0
BEGIN
print CONVERT(NVARCHAR(100),@selectedRow)
:CONNECT @ServerName
GO
USE @DatabaseName
GO
SELECT * FROM [config].[LpsPlant]
GO
FETCH NEXT FROM CRS INTO @ServerName, @DatabaseName;
END
DROP TABLE #TEMP
答案 3 :(得分:1)
我没有运行你的代码,但我发现使用单词GO
可能存在问题,这不是SQL关键字,而是SQL Server / SqlCmd关键字意味着“这里结束了一个脚本块,运行一切在其中等待所有后果“。我不确定它是否可以在WHILE
循环内工作。
然后我看到你正在尝试
:CONNECT ServerName
但在documentation中,我看到语法为
:CONNECT $(ServerName)
还有你的循环问题。如果不使用SELECT
,SQL Server不保证ORDER BY
指令的顺序。如果你不关心执行指令的顺序,那就没关系,否则你需要用光标更改它,或者至少添加一个数字列,并在你选择TOP 1
时按顺序排序。