2011-09-15 59 views
4

這裏是我試圖通過sqlcmd(SQL Server 2005)運行的一些Transact-SQL。問題與改變,然後嘗試使用Transact-SQL更新更新

USE PUK; 
GO 
BEGIN TRANSACTION; 
BEGIN TRY 

    -- - Modify RETRIEVAL_STAT 
    alter table dbo.RETRIEVAL_STAT add 
     SOURCE nvarchar(10) NULL, 
     ACCOUNTNUMBER nvarchar(50) NULL, 
     PUK nvarchar(20) NULL; 

    -- transform logic. 
    update dbo.RETRIEVAL_STAT set 
     SOURCE = 'XX', 
     ACCOUNTNUMBER = 'XX', 
     PUK = 'XX'; 

END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_SEVERITY() AS ErrorSeverity 
     ,ERROR_STATE() AS ErrorState 
     ,ERROR_PROCEDURE() AS ErrorProcedure 
     ,ERROR_LINE() AS ErrorLine 
     ,ERROR_MESSAGE() AS ErrorMessage; 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRANSACTION; 
END CATCH; 
IF @@TRANCOUNT > 0 
    COMMIT TRANSACTION; 
GO 

我收到以下錯誤:

(0 rows affected) 
Changed database context to 'PUK'. 
Msg 207, Level 16, State 1, Server localhost\SQLEXPRESS, Line 11 
Invalid column name 'SOURCE'. 
Msg 207, Level 16, State 1, Server localhost\SQLEXPRESS, Line 11 
Invalid column name 'ACCOUNTNUMBER'. 
Msg 207, Level 16, State 1, Server localhost\SQLEXPRESS, Line 11 
Invalid column name 'PUK'. 

我猜測,這是因爲通過ALTER語句引入了新列尚未提交,以便更新失敗。

我的問題是我如何得到這個工作呢?我希望這可以作爲單個事務運行,如果出現問題,我可以回滾。這很重要,因爲我還有更多的alter語句可供使用,而且我有點沮喪,我無法克服這一點。

任何援助將不勝感激!當代碼被編譯

羅布 :)

回答

5

即使我寫我自己的答案 - 一切歸功於@Mikael埃裏克森,誰建議我需要不同批次用GO分開 - 這樣能改變表不與代碼衝突的代碼使用改變的表格。感謝Mikael!

USE PUK; 
GO 
BEGIN TRANSACTION; 
BEGIN TRY 

    -- - Modify RETRIEVAL_STAT 
    alter table dbo.RETRIEVAL_STAT add 
     SOURCE nvarchar(10) NULL, 
     ACCOUNTNUMBER nvarchar(50) NULL, 
     PUK nvarchar(20) NULL; 

END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_SEVERITY() AS ErrorSeverity 
     ,ERROR_STATE() AS ErrorState 
     ,ERROR_PROCEDURE() AS ErrorProcedure 
     ,ERROR_LINE() AS ErrorLine 
     ,ERROR_MESSAGE() AS ErrorMessage; 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRANSACTION; 
END CATCH; 
IF @@TRANCOUNT > 0 
    COMMIT TRANSACTION; 
GO 


USE PUK; 
GO 
BEGIN TRANSACTION; 
BEGIN TRY 

    -- transform logic. 
    UPDATE  dbo.RETRIEVAL_STAT 
    SET   SOURCE = 'ABC', 
       ACCOUNTNUMBER = ABC.ACCOUNTNUMBER, 
       PUK = ABC.PUK 
    FROM  RETRIEVAL_STAT RS 
    INNER JOIN ABC 
    ON   RS.SERVICE_NUMBER = ABC.SERVICENUMBER; 

    UPDATE  dbo.RETRIEVAL_STAT 
    SET   SOURCE = 'DEF', 
       ACCOUNTNUMBER = DEF.BILLINGACCOUNTNUMBER , 
       PUK = DEF.PUK 
    FROM  RETRIEVAL_STAT RS 
    INNER JOIN DEF 
    ON   RS.SERVICE_NUMBER = DEF.SERVICENUMBER; 

    UPDATE  dbo.RETRIEVAL_STAT 
    SET   SOURCE = 'No Match' 
    WHERE  SOURCE IS NULL; 

    -- Fix other columns that should be not nullable. 
    alter table dbo.RETRIEVAL_STAT 
     alter column SERVICE_NUMBER nvarchar (50) NOT NULL; 
    alter table dbo.DEF 
     alter column PUK nvarchar (20) NOT NULL; 


END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_SEVERITY() AS ErrorSeverity 
     ,ERROR_STATE() AS ErrorState 
     ,ERROR_PROCEDURE() AS ErrorProcedure 
     ,ERROR_LINE() AS ErrorLine 
     ,ERROR_MESSAGE() AS ErrorMessage; 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRANSACTION; 
END CATCH; 
IF @@TRANCOUNT > 0 
    COMMIT TRANSACTION; 
GO 
+0

我在這裏寫了這篇文章:[在批量Transact-SQL中分離DDL和DML](http://robertmarkbramprogrammer.blogspot.com/2011/ 09 /分離-DDL-和DML-在-的Transact-sql.html)。 –

3

SQL Server檢查的列。你可以使用動態sql來解決這個問題。

-- transform logic. 
declare @SQL nvarchar(1000) 
set @SQL = 
    'update dbo.RETRIEVAL_STAT set 
    SOURCE = @S, 
    ACCOUNTNUMBER = @A, 
    PUK = @P'; 

declare @Params nvarchar(1000); 
set @Params = N'@S nvarchar(10), @A nvarchar(10), @P nvarchar(20)'; 

exec sp_executesql @SQL, @Params, N'S', N'A', N'P'; 
+0

好的,謝謝你的建議 - 我認爲這意味着我需要分解我的腳本 - 因爲我有很多SQL引用這些新的列(不需要做的SQL動態) –

+0

@羅伯特馬克布拉姆 - 我不明白你爲什麼認爲你需要這一點。此代碼的問題是在同一批次中混合使用DML和DDL。 'GO'是批量分離器,每批都由我自己編譯。其他代碼不需要使用動態,因爲它是另一批次的一部分。針對您的問題的更好解決方案是將添加列的代碼移動到批次添加數據之前的批處理中。結果的區別在於,如果更新失敗,您的表中仍然會有列。 –

+0

Ohhhhh,所以這就是你使用GO!過了一段時間,我盲目地在各處插入GO ...現在我知道如何正確使用它們,我希望。 :) –