2017-05-03 71 views
-1

我想添加一列到表,然后插入数据到它,然后删除该列。我希望这是一个交易。 为了我的问题,我简化了这里的问题,实际上我正在使用新的列临时从另一个表中获取一些数据,然后将其插入到已更改的表中。我有与简化版本相同的问题。SQL Server的 - ALTER TABLE和插入在同一事务

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

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

如果我删除了GO,插入语句试图插入到新添加的列时失败。

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

如果我运行BEGIN TRAN与正常工作的GOALTER TABLE声明。但我需要这个在交易中。

任何帮助表示赞赏。代码如下:

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

为什么不使用临时表而不是像这样添加和删除列? –

回答

1

您可以使用临时表/变量:

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 
+0

这是一个表变量,而不是临时表。不同的动物,他们不能/不应该交替使用。 – alroc

1

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

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