在使用UNION时,SQL查询是否保证以原子方式执行?

时间:2011-04-08 16:38:13

标签: sql transactions

我发出一个SQL查询,包含使用UNION分组的多个SELECT:

SELECT *
FROM   employee 
       LEFT JOIN department 
          ON employee.DepartmentID = department.DepartmentID
UNION
SELECT *
FROM   employee
       RIGHT JOIN department
          ON employee.DepartmentID = department.DepartmentID;

假设我在READ_COMMITTED事务隔离下执行此查询,两个SELECT语句是否保证以原子方式执行?或者我是否存在各个SELECT语句之间数据更改的风险? SQL规范是否讨论过这类问题?

澄清:当我说“原子”时,我不是指ACID中的“A”。我的意思是我希望在查询完成之前对department和employee表进行读锁定。

3 个答案:

答案 0 :(得分:3)

是的,该声明是原子的,但是数据可以在2次读取之间发生变化。

Read Committed只能保证你不会读取脏数据,因为你需要更高的隔离级别,所以不会对读取的一致性做出任何承诺。

正如您所说,您将接受SQL Server示例...

连接1

(假设在悲观的读取提交隔离级别下)

CREATE TABLE employee
(
name VARCHAR(50),
DepartmentID INT
)

CREATE TABLE department
(
DepartmentID INT
)

INSERT INTO department VALUES (1)
INSERT INTO employee VALUES ('bob',1)

declare @employee TABLE
(
name VARCHAR(50),
DepartmentID INT
)


WHILE ((SELECT COUNT(*) FROM @employee) < 2)
BEGIN
DELETE FROM  @employee

INSERT INTO @employee
SELECT employee.*
FROM   employee 
       LEFT JOIN department 
          ON employee.DepartmentID = department.DepartmentID
UNION
SELECT employee.*
FROM   employee
       RIGHT JOIN department
          ON employee.DepartmentID = department.DepartmentID

END;          

SELECT * FROM @employee

连接2

while (1=1)
UPDATE employee SET name = CASE WHEN name = 'bob' THEN 'bill' else 'bob' END

现在回到连接1

name                                               DepartmentID
-------------------------------------------------- ------------
bill                                               1
bob                                                1

(请记得切换回连接2以杀死它!)

涵盖此READ COMMITED行为is here

的具体文档
  

共享锁定类型决定何时   它将被释放。行锁是   在下一行之前发布了   处理。页锁已发布   当读取下一页时,和表   在声明时释放锁   饰面。

答案 1 :(得分:1)

使用UNION将删除可能从任何联合查询返回的任何重复记录,因此不完全是原子的。如果您想要所有联合查询的所有记录,请使用UNION ALLUNION ALL也可以UNION快得多。

答案 2 :(得分:1)

编辑:请注意,我的回答是不正确的,但我不想删除它,因为我认为它链接到好问题并且有很好的评论。

每笔交易都是原子的。

使用多个子查询的UNION是单个T-SQL命令,单个事务,并且是原子的。

这部分地是避免低效查询(或者sprocs)的原因,因为它们的原子性质可以延迟其他事务。

编辑: 有关子查询原子性的更多有趣信息,请参阅此问题

Is update with nested select atomic operation?

编辑:显然我错了。

这是关于这个主题的一个很好的讨论:Atomic UPSERT in SQL Server 2005 Remus就是一个很好的例子。很抱歉怀疑你,马丁......