代码之家  ›  专栏  ›  技术社区  ›  Matthew Baker

如何在没有动态sql的情况下将模式参数传递给过程

  •  0
  • Matthew Baker  · 技术社区  · 7 年前

    我试图在不使用动态SQL的情况下将参数化的模式名(或表名)传递到过程中。

    这个过程目前使用的是动态的,但我的任务是从我们的系统中删除尽可能多的动态sql。从研究中,我知道DynamicSQL是常见的答案,历史上一直没有这样的方法,但随着时间的推移,情况会发生变化,所以我想看看是否有人找到了更好的解决方案。

    • 创建动态用户/登录/模式,然后在用户上设置默认模式,包括作为代码执行
      • 不起作用,因为过程模式优先于选择查询-不考虑用户默认模式
    • 创建同义词
      • 不起作用,因为同义词不能成为特定于动态/会话的

    如果不完全重新设计数据库,我目前无法改进现有的数据库,这不是一项我会轻易承担的任务。

    非常感谢您的任何其他选择/建议。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Matthew Baker    7 年前

    非常感谢@Sepupic,虽然最终的答案不是他的,但它帮助我走上了我需要的道路。在他对信用卡的评论中加上几个1。

    我最终使用的解决方案:

    将存储过程从模式“template”复制到模式@SessionID的存储过程

    CREATE PROC [dbo].[usp_CopySproc]
        @SessionID NVARCHAR(255)
        ,   @ProcName NVARCHAR(255)
    AS
    BEGIN
        DECLARE @strSQL AS NVARCHAR(MAX)
        DECLARE @FullProcName AS NVARCHAR(MAX)
    
        SET @FullProcName = @SessionID + '.' + @ProcName
    
        IF OBJECT_ID(@FullProcName) IS NULL
            BEGIN
                PRINT 'Creating ' + @FullProcName
    
                SET @strSQL = OBJECT_DEFINITION(OBJECT_ID('template.' + @ProcName))
                SET @strSQL = STUFF(@strSQL, PATINDEX('%template%', @strSQL), 8, @SessionID)
    
                EXEC (@strSQL)
            END
        ELSE
            PRINT @FullProcName + ' already exists'
    
    END
    

    我在会话启动时设置了一个模式,可以包含过程和会话数据。然后使用以下命令复制过程:

    DECLARE @strSQL NVARCHAR(MAX)
    ,       @SessionID NVARCHAR(255) = 'mySession'
    
    EXEC dbo.usp_CopySproc @SessionID , 'usp_RefreshPriceSummary'
    SET @strSQL = @SessionID + '.usp_RefreshPriceSummary'
    EXEC @strSQL @SessionID
    

    然后,我复制的过程可以从会话模式内的表中进行选择,而无需限定其模式。

    最后,在会话关闭/清理时,我在对象表中导航,删除任何具有该模式id的内容。