动态 USE 语句
Dynamic USE statement
我正在寻找是否有人认为下面的代码是个坏主意。
这个挑战涉及我在几个不同的地方和情况下遇到的挑战。如何针对多个数据库中相同的 table 结构 运行 相同的查询。对于许多尝试多站点的小型 ERP 安装来说,这是一个问题。每个位置在服务器上都会有匹配的 tables 和不同的数据库。当涉及报告数据收集时,通常在每个数据库中部署一个 proc,它是一个精确的副本。我在拥有多达 14 个独立网站的网站上看到过这种情况。代码扩散和管理部署可能非常具有挑战性。最近,我想到了一个别人没有提出过的想法,至少我没有找到它,虽然简单但似乎可行。我不知道我是否遗漏了一些微妙的东西或一些技术原因,为什么这是一个坏主意。
代码:
DECLARE @i AS INT
SET @i = 1
WHILE @i < 3
BEGIN
IF @i = 1 USE [DB1]
IF @i = 2 USE [DB2]
INSERT INTO ThirdDB.dbo.ReportTable (field)
SELECT TOP 1 SomeNumber
FROM CommonTable WITH (NOLOCK)
SET @i = @i + 1
END
我的初步测试表明它有效。
我建议不要使用循环。无论如何,您基本上都必须对每个数据库名称进行硬编码。一点动态 sql 可以减少很多工作量。此外,NOLOCK 提示几乎总是一个坏主意。没有 order by 的 TOP 也是一个坏主意。我从这个示例代码中删除了这两个。
您可以通过以下几种方式利用动态 sql。第一个是生成单独的插入语句。第二个将使用 UNION ALL 生成单个插入语句。
declare @Prefix nvarchar(max) = 'INSERT INTO ThirdDB.dbo.ReportTable (field) SELECT MAX(SomeNumber) FROM '
, @PostFix nvarchar(max) = '.dbo.CommonTable;'
, @SQL nvarchar(max) = ''
select @SQL = @SQL + @Prefix + DBName + @PostFix
from
(
values('DB1'),('DB2')
) Names(DBName)
select @SQL
--uncomment the line below when you are satisfied the query is correct
--exec sp_executesql @SQL
或者第二种方式。
declare @SQL nvarchar(max) = ''
select @SQL = @SQL + 'SELECT MAX(SomeNumber) From ' + Names.DBName + '.dbo.CommonTable union all '
from
(
values('DB1'),('DB2')
) Names(DBName)
set @SQL = 'INSERT INTO ThirdDB.dbo.ReportTable (field) ' + left(@SQL, len(@SQL) - 10)
select @SQL
--uncomment the line below when you are satisfied the query is correct
--exec sp_executesql @SQL
我正在寻找是否有人认为下面的代码是个坏主意。
这个挑战涉及我在几个不同的地方和情况下遇到的挑战。如何针对多个数据库中相同的 table 结构 运行 相同的查询。对于许多尝试多站点的小型 ERP 安装来说,这是一个问题。每个位置在服务器上都会有匹配的 tables 和不同的数据库。当涉及报告数据收集时,通常在每个数据库中部署一个 proc,它是一个精确的副本。我在拥有多达 14 个独立网站的网站上看到过这种情况。代码扩散和管理部署可能非常具有挑战性。最近,我想到了一个别人没有提出过的想法,至少我没有找到它,虽然简单但似乎可行。我不知道我是否遗漏了一些微妙的东西或一些技术原因,为什么这是一个坏主意。
代码:
DECLARE @i AS INT
SET @i = 1
WHILE @i < 3
BEGIN
IF @i = 1 USE [DB1]
IF @i = 2 USE [DB2]
INSERT INTO ThirdDB.dbo.ReportTable (field)
SELECT TOP 1 SomeNumber
FROM CommonTable WITH (NOLOCK)
SET @i = @i + 1
END
我的初步测试表明它有效。
我建议不要使用循环。无论如何,您基本上都必须对每个数据库名称进行硬编码。一点动态 sql 可以减少很多工作量。此外,NOLOCK 提示几乎总是一个坏主意。没有 order by 的 TOP 也是一个坏主意。我从这个示例代码中删除了这两个。
您可以通过以下几种方式利用动态 sql。第一个是生成单独的插入语句。第二个将使用 UNION ALL 生成单个插入语句。
declare @Prefix nvarchar(max) = 'INSERT INTO ThirdDB.dbo.ReportTable (field) SELECT MAX(SomeNumber) FROM '
, @PostFix nvarchar(max) = '.dbo.CommonTable;'
, @SQL nvarchar(max) = ''
select @SQL = @SQL + @Prefix + DBName + @PostFix
from
(
values('DB1'),('DB2')
) Names(DBName)
select @SQL
--uncomment the line below when you are satisfied the query is correct
--exec sp_executesql @SQL
或者第二种方式。
declare @SQL nvarchar(max) = ''
select @SQL = @SQL + 'SELECT MAX(SomeNumber) From ' + Names.DBName + '.dbo.CommonTable union all '
from
(
values('DB1'),('DB2')
) Names(DBName)
set @SQL = 'INSERT INTO ThirdDB.dbo.ReportTable (field) ' + left(@SQL, len(@SQL) - 10)
select @SQL
--uncomment the line below when you are satisfied the query is correct
--exec sp_executesql @SQL