我正在创建一个新的SQL数据库,需要连接到几个现有的数据库,所有这些数据库都具有相同的模式。
我想创建可用于访问任何现有数据库的存储过程,同时尽可能地重用代码。我的问题是,编写可用于访问这些现有数据库中任何一个的通用SP的最佳方法是什么?
到目前为止,我已经考虑了一些选项。请注意,这些只是简单的代码片段来说明问题,而不是现实世界的代码。首先,我尝试打开数据库名称:
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对性能的影响。
有没有人对我如何构建代码以减少重复声明有任何其他想法?也许有一个更简单的方法,我错过了?我会非常感谢任何建议。
答案 0 :(得分:0)
您可以通过删除对数据库和架构的引用来实现此目的
SELECT * FROM SERIES_DATA
这是一个在所有数据库中创建模式,并授予对数据库和模式的登录访问权限的问题(在这种情况下,您使用的是默认的dbo模式)。 如果您正在使用管理工作室,则在创建登录时,您可以使用用户映射处理其余部分。 如果您具有相同的架构(例如dbo),则可以将选择更改为:
SELECT * FROM dbo.SERIES_DATA
除非要跨数据库连接表,否则您实际上不希望包含数据库名称。