SQL Server - 事务中的一个语句的结果立即对下一个语句可见?

kub*_*003 2 sql-server sql-server-2008

这个:

use test;

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;


BEGIN TRANSACTION;

EXEC sp_RENAME 'table1.asd' , 'ads', 'COLUMN';

INSERT INTO table1 (ads) VALUES (12);

COMMIT
Run Code Online (Sandbox Code Playgroud)

是一个简单的例子,展示了我想做的事情.

我想以某种方式更改表并在一个事务中执行插入/删除(或对表的其他修改).

问题是语句中的结果sp_RENAME永远不会立即可见INSERT.我玩过不同的事务隔离级别 - 它始终是相同的(因此事务永远不会提交).

通常我只是将GO语句用于不同的批次,但我需要一批,因为...

我的真正任务是编写一个脚本,将标识和FK添加到表中(这需要使用新模式创建另一个表,从旧模式执行标识插入,重命名表并应用约束).我需要安全地玩它 - 如果程序的任何部分失败,我必须回滚整个事务.这就是为什么我想做这样的事情:

BEGIN TRAN
    --some statement

    IF (@@ERROR <> 0) GOTO ERR_HANDLER

    -- some other statement

    IF (@@ERROR <> 0) GOTO ERR_HANDLER

COMMIT TRAN

RETURN 0

ERR_HANDLER:
PRINT 'Unexpected error occurred!'
ROLLBACK TRAN
RETURN 1
Run Code Online (Sandbox Code Playgroud)

由于标签仅在批处理内部工作,因此我无法使用GO语句.

那么我怎么能:

  • make语句(即ALTER TABLE,sp_RENAME)会立即生效吗?

要么

  • 以其他方式编写整个解决方案,以便在生产数据库中运行是安全的吗?

Mar*_*ith 5

问题是批处理解析在遇到对重命名列的引用时失败,因此整个批处理永远不会被执行 - 而不是事务的影响不可见.

您可以将您的语句引用到块中新列的名称,EXEC('')以推迟编译,直到重命名该列为止.

EXEC sp_rename 'table1.asd' , 'ads', 'COLUMN';
EXEC('INSERT INTO table1 (ads) VALUES (12);')
Run Code Online (Sandbox Code Playgroud)