2014-02-28 28 views
2

當我有鏈接到其他數據庫服務器超過100個數據庫服務器。這些數據庫具有鏈接表的視圖。我需要每週更新視圖以查看鏈接服務器中的任何對象更改,即列添加。「<xyz>必須在查詢批處理的第一條語句」使用生成的DDL

我經歷了所有的數據庫創建此腳本中循環,並抓住所有的意見,並通過執行ALTER VIEW刷新它們。 sp_refreshview不適用於鏈接的服務器。

當我打印@sql變量,它在另一個查詢窗口工作正常。當我嘗試執行@sql變量,它給了我下面的錯誤:

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 

回答

3

"GO" is not actually valid T-SQL.這只是其中的各種SQL工具如SSMS識別爲批處理分隔符(如,如果您單獨運行每個塊)的字符串。

所以你可能沿着「附近有語法錯誤‘GO’」還有的線條得到了一個錯誤。

爲了創造另一個數據庫的視圖,則需要在該數據庫的情況下運行sp_executesql的,如:

EXEC OtherDatabase.dbo.sp_executesql @SQL; 

感謝Bob Pusateri's blog爲洞察力。

但是,你有一個動態的數據庫名稱,這使得它額外的複雜。我相信你大概可以使用EXEC動態SQL,它包含用動態數據庫名稱Incpetion-style限定的sp_executesql命令。但是你必須小心你的單引號編碼。

1

,可以嘗試通過使用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) 
0

我喜歡使用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)." 
    } 
} 
相關問題