【问题标题】:Create A View With Dynamic Sql使用动态 Sql 创建视图
【发布时间】:2014-02-06 01:04:11
【问题描述】:

我正在尝试创建一个动态数据库创建脚本。

有很多步骤,我们经常创建这个数据库,所以脚本看起来像这样。

 DECLARE @databaseName nvarchar(100) = 'DatabaseName'
 EXEC('/*A lot of database creation code built off of @databaseName*/')

这一切都很好,除了我们想在@databaseName 中创建一个视图。

我尝试了四种不同的方法来创建此视图,但均未成功:

  1. 我的第一个想法是简单地设置数据库上下文,然后在一个脚本中创建视图。不幸的是,这不起作用,因为CREATE VIEW 必须是其查询块中的第一条语句 (details)。

    --Result: Error message, "'CREATE VIEW' must be the first statement in a query batch"
    EXEC 
    ('
        USE [' + @databaseName + ']
        CREATE VIEW
    ')
    
  2. 为了绕过 (1) 我尝试单独设置上下文,以便 CREATE VIEW 将成为 EXEC 中的第一个命令。这确实创建了视图,但在我当前的上下文中创建了视图,而不是 @databaseName。在EXEC 中调用USE 的效果似乎只持续到EXEC 语句(details)结束。

    --Result: The view is created in the currently active database rather than @databaseName
    EXEC ('USE [' + @databaseName + ']')
    EXEC ('CREATE VIEW')
    
  3. 接下来,我尝试将所有内容放回一个脚本中,但包含了一个 GO 命令,以便使 CREATE VIEW 成为新查询块中的第一个命令。这失败了,因为在 EXEC 脚本 (details) 中不允许使用 GO

    --Result: Error message, "Incorrect syntax near 'GO'"
    EXEC 
    ('
        USE [' + @databaseName + ']
        GO
        CREATE VIEW
    ')
    
  4. 最后我尝试将目标数据库指定为CREATE VIEW 命令的一部分。在这种情况下,脚本失败了,因为 CREATE VIEW 不允许将数据库指定为其创建的一部分 (details)。

    --Result: Error message, "'CREATE/ALTER VIEW' does not allow specifying the database name as a prefix to the object name"
    EXEC ('CREATE VIEW [' + @databaseName + '].[dbo].[ViewName]')
    

有什么建议吗?我认为这应该是一个常见的用例,但 Google 无法帮助我。

【问题讨论】:

    标签: sql-server tsql dynamic-sql


    【解决方案1】:

    您可以通过双重嵌套动态 SQL 语句来做到这一点:

    begin tran
    declare @sql nvarchar(max) = 
        N'use [AdventureWorks2012]; 
          exec (''create view Test as select * from sys.databases'')';
    
    exec (@sql);
    
    select * from AdventureWorks2012.sys.views
    where name = 'Test'
    
    rollback tran
    

    【讨论】:

    • 太棒了。我喜欢它。我会很快测试的。
    • 哇! 3天来一直在抨击一个问题,从来没有想过这种方法!太棒了,谢谢!
    • 两年多过去了,它仍然很有用。谢谢!
    • 太棒了。 7 年多后,这仍然是实现这一目标的唯一 [简单] 方法。
    【解决方案2】:

    另一种方法不是双重嵌套,而是创建一个存储过程,其唯一目的是执行动态 SQL

    CREATE PROCEDURE [dbo].[util_CreateViewWithDynamicSQL] 
    @sql nvarchar(max)
    AS
    BEGIN
        SET NOCOUNT ON;
        EXECUTE (@sql)  
    END
    

    上面的存储过程可以重复使用。每当您需要创建视图时,只需调用存储过程并将动态 sql 传递给它。

    EXECUTE util_CreateViewWithDynamicSQL 'create view Test as select * from sys.databases'
    

    我更喜欢这种方法,因为动态 sql 很混乱,添加双重嵌套会使它更加复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      • 2012-02-24
      • 1970-01-01
      • 2016-03-27
      相关资源
      最近更新 更多