Sql server &引用&书信电报;xyz>;必须是查询批处理中的第一条语句;使用生成的DDL时
我有一个服务器,它有100多个数据库链接到其他数据库服务器。这些数据库具有链接表的视图。我需要每周更新链接服务器中任何对象更改的视图,ie列补充道 我创建这个脚本来循环所有数据库,获取所有视图,并通过执行alterview刷新它们。sp_refreshview不适用于链接服务器 当我打印@sql变量时,它可以在另一个查询窗口中正常工作。当我尝试执行@sql变量时,它会给出以下错误:Sql server &引用&书信电报;xyz>;必须是查询批处理中的第一条语句;使用生成的DDL时,sql-server,tsql,Sql Server,Tsql,我有一个服务器,它有100多个数据库链接到其他数据库服务器。这些数据库具有链接表的视图。我需要每周更新链接服务器中任何对象更改的视图,ie列补充道 我创建这个脚本来循环所有数据库,获取所有视图,并通过执行alterview刷新它们。sp_refreshview不适用于链接服务器 当我打印@sql变量时,它可以在另一个查询窗口中正常工作。当我尝试执行@sql变量时,它会给出以下错误: Msg 111, Level 15, State 1, Line 3 'ALTER VIEW' must be t
Msg 111, Level 15, State 1, Line 3
'ALTER VIEW' must be the first statement in a query batch.
我认为这与LF/CR有关。我尝试过很多方法,但都没有成功
有什么想法吗
DECLARE @command varchar(1000)
CREATE TABLE #tempViewSQL (DBName VARCHAR(255)
,ViewSQL VARCHAR(4000))
SELECT @command = 'IF ''?'' NOT IN(''master''
, ''model''
, ''msdb''
, ''tempdb''
,''pubs''
,''AuditProduction''
,''AuditProductionTest''
,''IID_Support''
,''Insurance_Files''
,''LoansAnalysis''
,''QualityAudit''
,''QualityAuditTest'')
BEGIN
USE ?
INSERT INTO #tempViewSQL
SELECT TABLE_CATALOG, replace(view_definition,''create view'',''alter view'')
FROM information_schema.views
WHERE TABLE_NAME NOT IN (''syssegments'',''sysconstraints'')
END'
EXEC sp_MSforeachdb @command
DECLARE @SQLCursor VARCHAR(2000)
DECLARE @SQL VARCHAR(2000)
DECLARE @DbName VARCHAR(255)
DECLARE MyCursor CURSOR FOR
SELECT DBName, ViewSQL FROM #tempViewSQL
OPEN MyCursor
FETCH NEXT FROM MyCursor INTO @DbName,@SQLCursor
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = 'USE ' + @DBName + CHAR(10) + CHAR(13) + 'GO' + CHAR(10) + CHAR(13) + @SQLCursor
--PRINT (@SQL)
EXECUTE (@SQL)
FETCH NEXT FROM MyCursor INTO @DbName,@SQLCursor
END
CLOSE MyCursor
DEALLOCATE MyCursor
DROP TABLE #tempViewSQL
它只是一个字符串,各种SQL工具(如SSM)将其识别为批处理分隔符(就好像您单独运行每个块一样)
因此,您可能也遇到了“GO”附近语法错误”的错误
为了在另一个数据库中创建视图,您需要在该数据库的上下文中运行sp_executesql,例如:
EXEC OtherDatabase.dbo.sp_executesql @SQL;
这一见解值得赞扬
但是,您有一个动态数据库名称,这使得它变得更加复杂。我相信您可能可以执行包含sp_executesql命令的动态SQL,该命令使用动态数据库名称Incpetion样式进行限定。但是,您必须小心单引号编码。它只是一个字符串,各种SQL工具(如SSM)将其识别为批处理分隔符(就好像您分别运行每个块一样)
因此,您可能也遇到了“GO”附近语法错误”的错误
为了在另一个数据库中创建视图,您需要在该数据库的上下文中运行sp_executesql,例如:
EXEC OtherDatabase.dbo.sp_executesql @SQL;
这一见解值得赞扬
但是,您有一个动态数据库名称,这使得它变得更加复杂。我相信您可能可以执行包含sp_executesql命令的动态SQL,该命令使用动态数据库名称Incpetion样式进行限定。但您必须注意单引号编码。您可以尝试使用sp_executesql sp在特定数据库内执行查询,如下所示:
DECLARE @AlterQuery NVARCHAR(MAX) = N'ALTER VIEW v1 AS SELECT * from T1'
DECLARE @DbName NVARCHAR(MAX) = 'Test'
DELARE @Query NVARCHAR(MAX) = 'exec [' + @DbName + '].sys.sp_executesql N''' + REPLACE( @AlterQuery, '''', '''''' ) + ''''
EXECUTE( @Query )
您可以尝试使用sp_executesql sp在特定数据库内执行查询,如下所示:
DECLARE @AlterQuery NVARCHAR(MAX) = N'ALTER VIEW v1 AS SELECT * from T1'
DECLARE @DbName NVARCHAR(MAX) = 'Test'
DELARE @Query NVARCHAR(MAX) = 'exec [' + @DbName + '].sys.sp_executesql N''' + REPLACE( @AlterQuery, '''', '''''' ) + ''''
EXECUTE( @Query )
我喜欢在这样的部署中使用Powershell,其中我将所有服务器/数据库组合存储在中央服务器上的一个表中,然后使用此表填充要运行的服务器列表,然后循环运行它们以运行某些逻辑。这不是一个纯粹的SQL解决方案,但它可以很容易地修改以完成工作
function Get-ProductionDatabases
{
param
(
[Parameter(Mandatory=$true)]
[string]$centralServer,
[Parameter(Mandatory=$true)]
[string]$centralDatabase
)
$conn = New-Object System.Data.SqlClient.SqlConnection "Server=$centralServer;Database=$centralDatabase;Integrated Security=SSPI;";
$dt = New-Object System.Data.DataTable;
$cmd = $conn.CreateCommand();
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "Select [ServerName],
[DatabaseName]
From [dbo].[ProductionDatabases];";
$conn.Open();
$dt.Load($cmd.ExecuteReader());
$conn.Close();
$dt
}
$productionDatabases = Get-ProductionDatabases -centralServer "ProductionServer\Instance" -centralDatabase "CentralDatabase"
foreach($db in $productionDatabases)
{
$conn = New-Object System.Data.SqlClient.SqlConnection "Server=$($db.ServerName);Database=$($db.DatabaseName);Integrated Security=SSPI;";
$queryOut = New-Object System.Data.DataTable;
$cmd = $conn.CreateCommand();
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "Exec sp_refreshview;";
$conn.Open();
try
{
$queryOut.Load($cmd.ExecuteReader());
$conn.Close();
}
catch
{
"Warning: Error connecting to $($db.ServerName)."
}
}
我喜欢在这样的部署中使用Powershell,其中我将所有服务器/数据库组合存储在中央服务器上的一个表中,然后使用此表填充要运行的服务器列表,然后循环运行它们以运行某些逻辑。这不是一个纯粹的SQL解决方案,但它可以很容易地修改以完成工作
function Get-ProductionDatabases
{
param
(
[Parameter(Mandatory=$true)]
[string]$centralServer,
[Parameter(Mandatory=$true)]
[string]$centralDatabase
)
$conn = New-Object System.Data.SqlClient.SqlConnection "Server=$centralServer;Database=$centralDatabase;Integrated Security=SSPI;";
$dt = New-Object System.Data.DataTable;
$cmd = $conn.CreateCommand();
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "Select [ServerName],
[DatabaseName]
From [dbo].[ProductionDatabases];";
$conn.Open();
$dt.Load($cmd.ExecuteReader());
$conn.Close();
$dt
}
$productionDatabases = Get-ProductionDatabases -centralServer "ProductionServer\Instance" -centralDatabase "CentralDatabase"
foreach($db in $productionDatabases)
{
$conn = New-Object System.Data.SqlClient.SqlConnection "Server=$($db.ServerName);Database=$($db.DatabaseName);Integrated Security=SSPI;";
$queryOut = New-Object System.Data.DataTable;
$cmd = $conn.CreateCommand();
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "Exec sp_refreshview;";
$conn.Open();
try
{
$queryOut.Load($cmd.ExecuteReader());
$conn.Close();
}
catch
{
"Warning: Error connecting to $($db.ServerName)."
}
}