2012-04-17 82 views
1

編輯:數據庫名稱已被修改爲簡單起見與動態列名的SQL更新

我試圖得到一些動態sql到位,以更新的一些關鍵生產表靜態拷貝到另一個數據庫(sql2008r2 )。這裏的目標是在一段時間內允許數據的一致傳播(來自'靜態'數據庫),因爲我們的生產數據庫幾乎每天都在更新。

我正在使用一個CURSOR來遍歷包含要複製到「靜態」數據庫中的對象的表。 的prod表不發生變化頻繁,但我想使這個有些「面向未來」(如果可能的話!),併爲每個對象提取INFORMATION_SCHEMA.COLUMNS列名(而不是使用SELECT * FROM ...

  • 1)從我的其他職位已閱讀,EXEC()似乎限制,所以我認爲我會需要使用EXEC sp_executesql,但我有一個小麻煩讓我的頭周圍一切。

  • 2)作爲一個附加的額外費用,如果可能的話,我也想排除某些列的特定表(結構中的「靜態」數據庫略有不同)

這裏就是我迄今爲止。 執行時,@colnames返回NULL,因此@sql返回NULL ...

有人可以指導我在哪裏可以找到解決方案嗎?
任何意見或幫助與此代碼非常感謝。

CREATE PROCEDURE sp_UpdateRefTables 
    @debug bit = 0 
AS 
declare @proddbname varchar(50), 
    @schemaname varchar(50), 
    @objname varchar(150), 
    @wherecond varchar(150), 
    @colnames varchar(max), 
    @sql  varchar(max), 
    @CRLF  varchar(2) 

set @wherecond = NULL; 
set @CRLF = CHAR(10) + CHAR(13); 

declare ObjectCursor cursor for 
select databasename,schemaname,objectname 
from Prod.dbo.ObjectsToUpdate 

OPEN ObjectCursor ; 

FETCH NEXT FROM ObjectCursor 
INTO @proddbname,@schemaname,@objname ; 

while @@FETCH_STATUS=0 
begin 

if @objname = 'TableXx' 
    set @wherecond = ' AND COLUMN_NAME != ''ExcludeCol1''' 
if @objname = 'TableYy' 
    set @wherecond = ' AND COLUMN_NAME != ''ExcludeCol2''' 

--extract column names for current object 
select @colnames = coalesce(@colnames + ',', '') + QUOTENAME(column_name) 
from Prod.INFORMATION_SCHEMA.COLUMNS 
where TABLE_NAME = + QUOTENAME(@objname,'') + isnull(@wherecond,'') 

if @debug=1 PRINT '@colnames= ' + isnull(@colnames,'null') 

--replace all data for @objname 
[email protected] is used as schema name in Static database 
SELECT @sql = 'TRUNCATE TABLE ' + @proddbname + '.' + @objname + '; ' + @CRLF 
SELECT @sql = @sql + 'INSERT INTO ' + @proddbname + '.' + @objname + ' ' + @CRLF 
SELECT @sql = @sql + 'SELECT ' + @colnames + ' FROM ' + @proddbname + '.' + @schemaname + '.' + @objname + '; ' 

if @debug=1 PRINT '@sql= ' + isnull(@sql,'null') 

EXEC sp_executesql @sql 

FETCH NEXT FROM ObjectCursor 
INTO @proddbname,@schemaname,@objname ; 

end 
CLOSE ObjectCursor ; 
DEALLOCATE ObjectCursor ; 

P.S.我已閱讀關於SQL注入,但因爲這是一個內部管理任務,我猜我在這裏安全!?對此的任何建議也表示讚賞。

非常感謝提前。

回答

1

您在查詢中混合使用SQL和動態SQL,與information_schema對比。在where子句中也不需要QUOTENAME,因爲SQL Server在元數據中存儲了column_name而不是[column_name],所以實際上將完全阻止匹配。最後,我會將其更改爲sys.columns,因爲這是we should be deriving metadata in SQL Server的方式。嘗試:

SELECT @colnames += ',' + name 
    FROM Prod.sys.columns 
    WHERE OBJECT_NAME([object_id]) = @objname 
    AND name <> CASE WHEN @objname = 'TableXx' THEN 'ExcludeCol1' ELSE '' END 
    AND name <> CASE WHEN @objname = 'TableYy' THEN 'ExcludeCol2' ELSE '' END; 

SET @colnames = STUFF(@colnames, 1, 1, ''); 
+0

非常感謝阿龍,我會試試這個。我認爲INFORMATION_SCHEMA.Columns會是最好的,但會按照您的答案修改爲sys.columns。我也知道我不得不將IF更改爲CASE聲明,但不知道「STUFF」,並且會看起來這個! :) – MarkusBee 2012-04-17 11:55:04

+0

STUFF只是刪除前導',' - 這比在查詢中執行所有'COALESCE'連接的東西要容易得多。 – 2012-04-17 11:59:06

+0

你的回答像一個魅力。非常感謝。我想我太過複雜了。 雖然我個人喜歡COALESCE,但我發現它更加優雅一些,在這種情況下,它減輕了對STUFF語句的需求。不過,我可以看到STUFF的其他用途,所以請記住這一點。 :) – MarkusBee 2012-04-17 12:12:26