2012-09-04 27 views
2

我是新來的SQLServer腳本(通常是C++開發人員),並會很感激有點幫助。SQLServer的條件執行「EXEC」如果一列中存在

我試圖在一個SQL Server數據庫中包含一個「PROJID」列中的所有表進行「查找和替換」更新。我真的在努力尋找一種方法來做到這一點,不向我報告:

消息207,級別16,狀態1,行1無效的列名稱PROJID「。

我執行語句是:

EXEC 
(
    'IF EXISTS(SELECT * FROM sys.columns WHERE name = N''PROJID'' AND Object_ID = Object_ID(N''' + @TableName + '''))' + 
    ' BEGIN' + 
    ' UPDATE ' + @TableName + 
    ' SET ' + @ColumnName + ' = REPLACE(' + @ColumnName + ',''' + @ReplaceIDStr + ''',''' + @FindIDStr + ''')' + 
    ' WHERE ' + @ColumnName + ' LIKE ''' + @ReplaceIDStr + '''' + ' AND PROJID = ''1000''' + 
    ' END' 
) 

我一直在使用也嘗試:

'IF COL_LENGTH(''' + @TableName + ''',''PROJID'') IS NOT NULL' + 

而不是列,存在檢查上面。這仍然給我「無效的列名稱」消息。

我會很樂意將列並存檢查執行Exec聲明之外,但我不知道如何去任何這樣做。

回答

1

將此查詢的結果輸出到文本。不要忘記改變變量的值!採取這個結果並運行它。

SET NOCOUNT ON 

DECLARE @ColumnName VARCHAR(200) = 'ReplaceColumn' 
    , @ReplaceIdStr VARCHAR(200) = 'ExampleReplaceIdStr' 
    , @FindIdStr VARCHAR(200) = 'ExampleFindIdStr' 

PRINT 'BEGIN TRAN' 
PRINT 'SET XACT_ABORT ON' 

SELECT 
    'UPDATE ' + C.TABLE_NAME + CHAR(13) 
    + 'SET ' + @ColumnName + ' = REPLACE(' + @ColumnName + ', ''' + @ReplaceIdStr + ''', ''' + @FindIdStr + ''')' + CHAR(13) 
    + 'WHERE ' + @ColumnName + ' LIKE ''%' + @ReplaceIdStr + '%'' AND PROJID = ''1000''' + CHAR(13) 
FROM INFORMATION_SCHEMA.COLUMNS C 
WHERE C.COLUMN_NAME = 'PROJID' 

PRINT 'COMMIT TRAN' 

SET NOCOUNT OFF 

編輯:另外,一些推理:你說你要更新,他們含有一種叫PROJID列中的所有表。第一個查詢只是說,如果表@TableNamePROJID列,然後更新就可以了@ColumnName。但它不能保證它有@ColumnName。我提供的查詢不檢查,因爲我假設所有有PROJID的表也有@ColumnName。如果情況並非如此,請告訴我,我可以更新答案來檢查。你得到的Invalid Column Name錯誤點不存在@ColumnName

您的查詢將最多更新一個表(@TableName),而我給您的查詢將更新每個有PROJID的表。我希望那是你的目標。

編輯2:這裏是一個版本,會立即運行它:

DECLARE @ColumnName VARCHAR(200) = 'Value' 
    , @ReplaceIdStr VARCHAR(200) = 'ExampleReplaceIdStr' 
    , @FindIdStr VARCHAR(200) = 'ExampleFindIdStr' 


DECLARE @Sql NVARCHAR(MAX) 
DECLARE UpdateCursor CURSOR FOR 
SELECT 
    'UPDATE ' + C.TABLE_NAME 
    + ' SET ' + @ColumnName + ' = REPLACE(' + @ColumnName + ', ''' + @ReplaceIdStr + ''', ''' + @FindIdStr + ''')' 
    + ' WHERE ' + @ColumnName + ' LIKE ''%' + @ReplaceIdStr + '%'' AND PROJID = ''1000''' 
FROM INFORMATION_SCHEMA.COLUMNS C 
WHERE C.COLUMN_NAME = 'PROJID' 

OPEN UpdateCursor 

FETCH NEXT FROM UpdateCursor 
INTO @Sql 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    EXEC sp_executesql @Sql 

    FETCH NEXT FROM UpdateCursor 
    INTO @Sql 
END 


CLOSE UpdateCursor 
DEALLOCATE UpdateCursor 
+0

謝謝@Jeremy。這是一個我迄今爲止沒有遇到的新奇想法。我最好選擇一步操作,因爲我需要將我的SQL發送給客戶來修復他們的數據,但我會稍微研究一下您的方法,因爲這可能有一些優點。 –

+0

@Coder_Dan我添加了一個使用遊標的版本來完成每次更新。這工作更好一點?請注意,如果您有權訪問有問題的數據庫,則可以運行第一個版本,抽查結果,然後只發送生成的腳本。 –

+0

對不起,我提交的代碼只是我的SQL的一個片段。我在整個過程中有2個循環,一個迭代地爲每個表分配TableName,另一個迭代地將ColumnName分配給表中的所有列。這是基於本頁介紹的技術:http://blogs.thesitedoctor.co.uk/tim/2010/02/19/Search+Every+Table+And+Field+In+A+SQL+Server+Database + Updated.aspx @ColumnName不應該代表一個有效的列 - 事實上,當我在EXEC語句中運行這個簡單的查詢時,它運行良好。 –

2

您需要做的僅僅是在不同的範圍。

IF EXISTS (SELECT 1 FROM sys.columns ...) 
BEGIN 
    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N'UPDATE ...'; 
    EXEC sp_executesql @sql; 
END 
+0

有沒有辦法用我的「表名」是正在被反覆地分配到不同的表運行時變量來做到這一點在我的數據庫? (EXEC('SELECT 1 FROM sys.columns ...')) 這種事情會起作用嗎? –

+0

實際上,是這樣做的方式:IF @@ RowCount,使用EXEC與運行時生成的字符串來查找列的存在? –

相關問題