【问题标题】:Can I set a default schema for within a stored procedure?我可以在存储过程中设置默认架构吗?
【发布时间】:2010-12-06 21:10:27
【问题描述】:

我正在为 StackQL 进行下一次更新。

我想做的一件事是能够查询多个版本。因此,例如,当我加载 10 月份的数据时,我并没有删除旧的 9 月份数据库。它还在外面。事实上,你甚至可以通过像这样包含数据库名称来查询它:

select top 10 * from SO_Sept09..Posts

当他们开始为 ServerFault 和 SuperUser 提供数据时,这将变得更加重要。

但我不喜欢有一大堆数据库来支持这一点。我更愿意将所有数据放在同一个数据库中,并将每个不同的集合分开到它自己的模式中。但是为了使这成为可能,我需要能够将默认模式设置为运行查询的存储过程的一部分,基于传递给存储过程的参数,该参数告诉它用户从未来的下拉列表中选择了哪个数据库出现在工具栏中。

StackQL 中的查询最终只是传递给 exec() 函数,如下所示:

exec(@QueryText)

我可以在存储过程中或在 QueryText 字符串 (ala USE [DatabaseName]) 之前做些什么来设置查询中使用的默认模式吗?

【问题讨论】:

    标签: sql-server sql-server-2005 stored-procedures schema


    【解决方案1】:

    这里的各个地方都有一些如何做到这一点,但不是全部。这样做的方法是:

    1. 为每个架构创建一个唯一的登录名和用户

    2. 让这些用户成为每个不同架构的所有者。

    3. 将每个此类用户的默认架构设置为他们拥有的架构。

    4. 使用语法 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'
    

    【讨论】:

      【解决方案2】:

      除了修改@QueryText本身,我唯一能想到的就是用户的默认架构:

      ALTER USER SO_Sept09_Reader WITH DEFAULT_SCHEMA = SO_Sept09
      

      ...然后为您要使用的每个架构以不同的用户身份连接。黑客攻击。

      但是,如果您的查询无论如何都是动态构建的(我相信您知道为什么这通常不是一个好主意),那么最简单的方法可能是在查询文本中添加一个模式占位符,然后将模式名称与对替换函数的查询。

      【讨论】:

      • 添加模式占位符绝对不是一种选择。该站点允许任何人再次编写和运行 SQL 查询 StackOverflow 公共数据转储,他们几乎可以编写任何内容。更改用户也已退出,因为这会导致并发问题。但它确实让我想到了可能有几个用户并即时选择连接字符串。
      • 是的,后者是我的建议;每个模式一个或多个(静态)用户;即时切换用户(通过匹配的连接字符串连接)。
      【解决方案3】:

      另一种可能性是在每个架构中生成每个 SP 的副本,SP 中未修改的表名指的是同一架构中的表。

      请注意,这不适用于此类 SP 中的动态 SQL:

      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' )
      

      显然可以正常工作。

      【讨论】:

      • 仍然是一个杂牌,但我更喜欢它而不是创建额外的用户。
      • 我会像 RBArryYoung 的回答那样使用 EXECUTE AS,因为您已经在使用动态 SQL。架构亲和力对您不起作用的原因是,一旦您点击 exec,您就会从调用 exec 的 SP 中丢失架构的上下文,就像它丢失了其他所有内容一样。
      【解决方案4】:

      未尝试过,但是:您能否将不同架构的数据合并到一个视图中,并添加一列调用架构名称?

      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
      

      【讨论】:

      【解决方案5】:

      好的,我有一种新的方法可以做到这一点,可能对我来说效果更好。这是我对 Michael Petrotta 回答的评论的变体:

      但它确实让我想到了可能有几个用户并即时选择连接字符串。

      我要做的只是让一个用户来执行这些查询,但我会即时换出连接字符串以指定正确的初始目录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-02
        • 2011-03-17
        • 2015-12-20
        • 1970-01-01
        • 2015-09-08
        • 1970-01-01
        • 2020-07-21
        • 2014-12-09
        相关资源
        最近更新 更多