我正在为StackQL下一次更新。
有一件事我想要做的是有查询过几个版本的能力。 所以,当我装了10月份数据,例如,我没有删除旧的数据库九月。 它仍然在那里。 事实上,你甚至可以仍然包括数据库名称这样的查询它:
select top 10 * from SO_Sept09..Posts
当他们开始提供ServerFault和超级用户数据,这将是更重要的。
但我不喜欢有一大堆的数据库都来支持这一点。 我宁愿把所有的数据在同一个数据库和分隔每个组不同的到它自己的模式。 但要做到这一点,我需要能够设置默认模式为运行查询的存储过程的一部分,基于传递给存储过程,告诉它从未来的选择的用户下拉列表中的数据库参数出现在工具栏中。
在StackQL查询最终都只是传递到exec()
这样的功能:
exec(@QueryText)
有什么我可以在存储过程或预先准备的QUERYTEXT字符串做任何(ALA USE [DatabaseName]
)来设置一个查询中使用的默认模式?
还有如何做到这一点在不同的地方在这里件,但不完全。 要做到这一点的方法是:
为每个模式的唯一的登录和用户
让这些用户各种不同架构的所有者。
设置每个这样的用户的默认架构是他们自己的模式。
使用语法EXECUTE ('sql commands') AS USER = 'schema-owner'
在默认模式的上下文中执行的SQL命令。
下面的脚本演示了这一点:
--====== Create the Login for the User:
CREATE LOGIN [UserTest1] WITH PASSWORD='whatever', DEFAULT_DATABASE=[TestUsers], DEFAULT_LANGUAGE=[us_english]
GO
--====== Make a User for the Login:
CREATE USER [UserTest1] FOR LOGIN [UserTest1]
GO
--====== Make a Schema owned by the User and default to it:
-- (I assume that you already have the schemas)
CREATE SCHEMA [UserTest1] AUTHORIZATION [UserTest1]
GO
ALTER USER [UserTest1] WITH DEFAULT_SCHEMA=[UserTest1]
GO
--====== Make a sProc in dbo
CREATE PROCEDURE [dbo].[TestSchema_Exec] AS
SELECT 'executing in schema [dbo]'
GO
--====== Make a similar sProc in New Schema
CREATE PROCEDURE [UserTest1].[TestSchema_Exec] AS
SELECT 'executing in schema [UserTest1]'
GO
--========= Demonstrate that we can switch Default Schemas:
EXEC('TestSchema_Exec')
EXEC('TestSchema_Exec') AS USER = 'UserTest1'
除了修改@QueryText
本身,我能想到的唯一的事情就是用户的默认架构:
ALTER USER SO_Sept09_Reader WITH DEFAULT_SCHEMA = SO_Sept09
......然后连接为您要使用的每个模式的不同用户。 Hackity破解。
但是,如果您的查询是动态反正构造(我敢肯定,你知道为什么这往往不是一个好主意),这可能是最简单的,只是增加一个模式占位符的查询文本,并通过查询一起传递模式名更换功能。
另一种可能性是在每个模式中的每个SP的生成副本,在SP未修饰的表名指的是在相同的模式的表。
注意,这与动态SQL这样的SP内部不工作:
CREATE PROCEDURE schema_a.SP
@somesql AS varchar(MAX)
AS
BEGIN
EXEC ( @somesql )
END
CREATE PROCEDURE schema_b.SP
@somesql AS varchar(MAX)
AS
BEGIN
EXEC ( @somesql )
END
就不行,因为架构亲和力的EXEC赔了进去。
虽然这样的:
CREATE PROCEDURE schema_a.SP
AS
BEGIN
SELECT * FROM tbl -- Will use schema_a.tbl first
END
CREATE PROCEDURE schema_b.SP
AS
BEGIN
SELECT * FROM tbl -- Will use schema_b.tbl first
END
工作良好。
同理:
EXEC ( 'EXEC schema_a.SP' )
显然做工精细。
未经考验的,但是:你能在不同的架构的数据合并到一个视图中,并添加一列召唤出架构的名字吗?
CREATE VIEW AllPosts AS
SELECT Data1, Data2, 'Sept09' AS Partition FROM SO_Sept09..Posts
UNION ALL
SELECT Data1, Data2, 'Oct09' AS Partition FROM SO_Oct09..Posts
...
SELECT * FROM AllPosts WHERE Partition = 'Sept09'
SELECT * FROM dbo.AllPosts('Sept09') -- if use table-valued function instead
好吧,我有一个新的方式来做到这一点,可能效果更好一点对我来说。 这是我对迈克尔Petrotta的回答评论变种:
但它确实给我的想法也许有多个用户,并挑选在飞行中的连接字符串。
我将做什么是只有一个用户执行这些查询,但我会换出连接字符串就飞到指定正确的初始目录。