我一直在使用动态SQL查询(在存储过程中),以便为具有公共表的许多类似结构的数据库运行单个语句。
例如:
解决方案1:
ALTER PROC [dbo].[Example]
@vc_db VARCHAR(16)
, @vc_example VARCHAR(32)
AS
BEGIN
-- Dummy query for SSRS to allow columns to be read in Visual Studio
IF 1 = 2
BEGIN
SELECT
T1.C1
, T1.C2
, T2.C3
, T2.C4
FROM
DB1.dbo.T1
LEFT JOIN
DB1.dbo.T2
ON
T2.C1 = T1.C1
WHERE
T2.C4 = @vc_example
END
-- Dynamic query
DECLARE @vc_SQL VARCHAR(MAX) = '
SELECT
T1.C1
, T1.C2
, T2.C3
, T2.C4
FROM
' + @vc_db + '.dbo.T1
LEFT JOIN
' + @vc_db + '.dbo.T2
ON
T2.C1 = T1.C1
WHERE
T2.C4 = ''' + @vc_example + '''
'
PRINT @vc_SQL
EXEC (@vc_SQL)
END
到目前为止,它一直运行良好,因为它允许我们在运行多个数据库的语句/报告时传递其他参数。
然而,随着查询变得越来越复杂,管理虚拟查询以及将标准SQL转换为动态格式变得很困难。
因此,我们已开始研究实现此目的的其他方法。
解决方案2
我们最新的解决方案是为每个公用表创建一个视图(添加数据库列),基本上采用以下格式:
ALTER VIEW [dbo].[v_T1]
AS
SELECT *, 'DB1' DB FROM DB1.T1
UNION ALL
SELECT *, 'DB2' DB FROM DB2.T1
UNION ALL
SELECT *, 'DB3' DB FROM DB3.T1
这使我们能够以更简单,更简单的方式编写查询(在存储过程中)(不转换为“动态查询”,不需要Visual Studio拾取虚拟查询),而是利用用于限制和加入数据的附加数据库列,如下所示:
SELECT
T1.C1
, T1.C2
, T2.C3
, T2.C4
FROM
v_T1
LEFT JOIN
v_T2
ON
v_T2.C1 = v_T1.C1
AND v_T2.DB = v_T1.DB -- JOIN condition on database to limit data
WHERE
v_T2.C4 = @vc_example
AND v_T1.DB = @vc_db -- WHERE on database to limit data
此外,我已经能够通过输入(公共)表名来编写存储过程来动态构建这些视图,并且只要添加任何新数据库就可以重建这些视图。
然而,我们仍然不确定上述两种解决方案的效率/性能,尽管在大多数情况下,解决方案1似乎稍微快一点,但解决方案2在奇怪的情况下更快。我们还要进一步研究这个问题。我的问题是......我能以更好的方式实现这一目标吗?
道歉,我不希望这是一个讨论。我真的想要一些关于某人是否已经知道实现上述目标的更简单有效方法的输入。非常感谢。