使用动态 SQL 在不同的数据库中创建视图

Lum*_*mpy 6 sql-server-2008 sql-server dynamic-sql t-sql

作为一个更大项目的一部分,我试图在 SQL Server 实例中的每个数据库上创建一个新视图。

我创建了一个存储过程,其中包括通过游标循环遍历实例中的数据库,然后尝试使用sp_executesql. 不幸的是,我试图在其上创建视图的数据库中不存在存储过程。所以我试图让 sql server 使用该数据库,然后运行创建视图脚本。当我运行它时,我收到错误

'CREATE VIEW' 必须是查询批处理中的第一个语句。

关于我如何做到这一点的任何想法?这是sp_executesql程序的一部分。

declare @DB VARCHAR(50)
declare @SQL NVARCHAR(max)
set @DB = '[dbname]'

SET @SQL =  N'USE ' + @DB + N' CREATE VIEW vNonhiddenCategories 
AS
SELECT categories.categoryid
FROM categories
--WHERE ... irrelevant remainder of view code ...
'
execute sp_executesql @SQL
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 8

这将需要真正享受转义和重新转义单引号的乐趣,但我认为您所追求的技术是:

DECLARE 
  @DB  NVARCHAR(255) = QUOTENAME(N'dbname'),
  @SQL NVARCHAR(MAX);

SET @SQL =  N'EXEC ' + @DB + '.sys.sp_executesql '
+ 'N''CREATE VIEW dbo.vWhatever
AS
  SELECT x = 1, y = ''''x'''', z = GETDATE();''';

EXEC sys.sp_executesql @SQL;
Run Code Online (Sandbox Code Playgroud)

所以你有点嵌套动态 SQL;内部确保 SQL 在目标数据库上执行,而不是在本地执行。

自从这个原始问题出现以来,我采用的另一种方式:

DECLARE 
  @DB  NVARCHAR(255) = QUOTENAME('dbname'),
  @SQL NVARCHAR(MAX),
  @DBExec NVARCHAR(MAX);

SET @DBExec = @DB + N'.sys.sp_executesql';

SET @SQL = N'CREATE VIEW dbo.whatever
  AS
    SELECT x = 1, y = ''x'', z = GETDATE();';

EXEC @DBExec @SQL;
Run Code Online (Sandbox Code Playgroud)

这稍微更整洁,因为您不必双重嵌套单引号。

这是一个稍微整洁的方法,无需游标(好吧,没有设置游标的所有脚手架)。请注意,内部动态 SQL 只会在以下数据库中执行:(a) 存在类别表 (b) 此视图尚不存在 (c) 它不是系统数据库(好吧,不是主要系统数据库之一,反正)。

DECLARE @SQL NVARCHAR(MAX) = N'';

SELECT @SQL += NCHAR(13) + NCHAR(10)    
  + N'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(name) 
  + '.sys.views WHERE name = ''vNonhiddenCategories'')
  AND EXISTS (SELECT 1 FROM ' + QUOTENAME(name)
  + '.sys.tables WHERE name = ''categories'')
  BEGIN
    EXEC ' + QUOTENAME(name) + '.sys.sp_executesql N''
    CREATE VIEW dbo.vNonhiddenCategories3
    AS
      SELECT x = 1, y = ''''x'''';''
  END'
  FROM sys.databases 
  WHERE database_id BETWEEN 5 AND 32766;

PRINT @sql;
-- EXEC sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

当然,“更整洁”是旁观者眼中的。