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)
这将需要真正享受转义和重新转义单引号的乐趣,但我认为您所追求的技术是:
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)
当然,“更整洁”是旁观者眼中的。
| 归档时间: |
|
| 查看次数: |
9934 次 |
| 最近记录: |