SQL Server - 同一事务

时间:2017-05-03 17:45:48

标签: sql sql-server transactions insert alter

我正在尝试向表中添加一列,然后将数据插入其中,然后删除该列。我希望这是一个交易。 出于我的问题的目的,我在这里简化了问题,实际上我暂时使用新列从另一个表中获取一些数据,然后将其插入到更改的表中。我对简化版本有同样的问题。

ALTER TABLE语句之后,我需要GO,但SSMS告诉我

Msg 102, Level 15, State 1, Line 6
Incorrect syntax near ';'.

如果删除GO,则在尝试插入新添加的列时,insert语句将失败。

Msg 207, Level 16, State 1, Line 8
Invalid column name 'NewCol'.

如果我使用ALTER TABLEBEGIN TRAN之前运行GO语句,则可以正常运行。但我需要这是一个交易。

感谢任何帮助。代码如下:

BEGIN TRY
BEGIN TRAN

    ALTER TABLE myTable
    ADD NewCol varchar(6);
    GO

    INSERT INTO myTable (NewCol, BillingName, BillingAddress)
    SELECT * FROM OPENQUERY(linkedServer, 'SELECT * FROM customer');

    ALTER TABLE myTable
    DROP COLUMN NewCol;

COMMIT TRAN
END TRY
BEGIN CATCH
    ROLLBACK TRAN
END CATCH

2 个答案:

答案 0 :(得分:2)

您可以使用表变量:

BEGIN TRY
BEGIN TRAN

    DECLARE @temp TABLE(NewCol <type>, BillingName <type>, BillingAddress <type>);

    INSERT INTO @temp (NewCol, BillingName, BillingAddress)
    SELECT * FROM OPENQUERY(linkedServer, 'SELECT * FROM customer');

    INSERT INTO myTable
    SELECT BillingName, BillingAddress FROM @temp;

COMMIT TRAN
END TRY
BEGIN CATCH
    ROLLBACK TRAN
END CATCH

答案 1 :(得分:1)

这里有两个不同的问题。首先是批次的概念。 GO是一个&#34;命令&#34; SSMS(以及其他一些工具)理解这一点;它用于将一串文本分成批次。批处理是应用程序(SSMS)提交给数据库引擎执行的工作单元(代码)。当引擎收到批处理时,它将首先编译它。并且一次完成整个批次的编译。尽管您的批处理在尝试使用该列之前添加了该列,但编译器在评估插入查询时不会考虑您的alter语句。因此,你得到错误。

不幸的是,您无法将脚本分成多个批次,因为由于使用了逻辑,整个脚本必须在一个批处理中运行。为了解决这个问题,您可以对alter语句后面的所有语句使用动态sql。但这是一项高级技能,我无法推荐它。说实话,这种方法似乎有缺陷;我认为你应该重新评估导致你走这条道路的决定。一个重要的考虑因素是纯tsql中的错误处理是困难和不一致的 - 即使对于有经验的人来说也是如此。