如何在不同的数据库中动态创建视图/过程

问题描述 投票:0回答:1

我正在编写一个动态查询,它将大量视图和存储过程从一个数据库复制到另一个数据库。我无法使用本机 SSMS 功能,因为这将从 Web 前端驱动。有许多可能的源数据库和目标数据库:

DECLARE @TargetDatabase nvarchar(20) = 'DatabaseA'
DECLARE @Query nvarchar(MAX)

SET @Query = 'USE [' + @TargetDatabase + ']' + CHAR(10) + 'GO' + CHAR(10) + 'CREATE VIEW dbo.ViewA AS SELECT 1 FROM dbo.[TableA]'

EXEC(@Query)
--PRINT @Query

我如何填充 @Query 变量比上面复杂得多,但就这个问题而言,这应该足够了。

如果没有“GO”来分隔两个批次,我会收到错误消息“'CREATE VIEW'必须是查询批次中的第一个语句”

当我添加“GO”时,我收到该错误消息,但我也收到“'GO'附近的语法不正确。”

如果我打印 @Query,将结果复制/粘贴到 SSMS,它可以正常工作。

我能想到的最好的结果是它失败了,因为它不喜欢“GO”之前的 CHAR(10)。

想法?

sql sql-server dynamic-sql
1个回答
0
投票

GO
不是 SQL 关键字。它是由 SSMS 等工具解释的批次分隔符,以便在单个文件中分隔批次。

在动态 SQL 中,要分隔批次,您需要多次实际使用

EXEC

但是

USE
不能跨批次工作。正确的方法是调用
Otherdb.sys.sp_executesql
。如果数据库名称本身是动态的,那么您可以在变量中构造该过程名称并执行
EXEC @proc @query...

您还应该使用

QUOTENAME
来正确引用名称。

DECLARE @TargetDatabase sysname = 'DatabaseA';
DECLARE @Query nvarchar(MAX) = '
CREATE VIEW dbo.ViewA
AS
SELECT 1
FROM dbo.TableA;
';

DECLARE @proc nvarchar(1000) = QUOTENAME(@TargetDatabase) + '.sys.sp_executesql';

PRINT @Query  -- your friend

EXEC @proc @Query;
© www.soinside.com 2019 - 2024. All rights reserved.