【发布时间】:2014-06-13 08:01:59
【问题描述】:
我正在创建一个新的 SQL 数据库,它需要连接到多个现有数据库,所有这些数据库都具有相同的架构。
我想创建可用于访问任何现有数据库的存储过程,同时尽可能重用代码。我的问题是,编写可用于访问这些现有数据库中的任何一个的通用 SP 的最佳方法是什么?
以下是我目前考虑过的一些选项。请注意,这些只是简单的代码 sn-ps 来说明问题,而不是真实世界的代码。首先我尝试打开数据库名称:
IF @db = 'A'
BEGIN
SELECT * FROM A.dbo.SERIES_DATA
END
IF @db = 'B'
BEGIN
SELECT * FROM B.dbo.SERIES_DATA
END
这样做的缺点是同一个 SQL 语句会重复多次。于是我想到了使用动态SQL:
DECLARE @Command varchar(100)
SET @Command = 'select * from ' + @db + '.dbo.SERIES_DATA'
EXEC (@Command)
这解决了重复语句的问题,但存在动态 SQL 的风险(例如注入攻击等)。所以最后我想到了创建一个表值函数:
CREATE FUNCTION [dbo].[ufnSeries_Data] (@db varchar(10))
RETURNS TABLE
AS
RETURN (
SELECT * FROM A.dbo.Series_Data WHERE @db = 'A'
UNION
SELECT * FROM B.dbo.Series_Data WHERE @db = 'B'
)
GO
这使我能够编写单个通用代码来访问任何数据库:
SELECT * FROM ufnSeries_Data(@db)
这种方法的问题在于,我必须按顺序授予系统的所有用户对所有数据库的读取权限为使此查询正常工作,否则我会收到拒绝访问错误。我也不确定创建这样的 TVF 对性能的影响。
对于如何构建代码以最大程度地减少语句重复,是否有人有任何其他想法?也许我缺少一种更简单的方法?如果有任何建议,我将不胜感激。
【问题讨论】:
-
你能写一个
VIEW来进行连接并让存储过程查询该视图吗? -
你应该可以使用
EXECUTE AS解决权限问题,但是我不能说性能影响部分。 -
View 是比 TVF 更好的选择
-
@adrianm 设计视图不会查询所有数据库,而 TVF 只会查询一个?在那种情况下,哪个“更好”将取决于用例。还是您有其他的视图设计?
-
@JoachimIsaksson,视图的定义不会成为执行计划的一部分,并且只访问需要的数据库/表。即如果查询包含
WHERE [Database] = 'A',则只会访问数据库“A”。 TVF 的定义不是计划的一部分
标签: sql sql-server database