2010-06-09 55 views
2

这是我的第一篇文章!忍受着我。 我有一个更新声明,我想了解SQL Server如何处理它。更新表设置字段

UPDATE a 
    SET a.vField3 = b.vField3 
FROM tableName a 
    INNER JOIN tableName b on a.vField1 = b.vField1 
     AND b.nField2 = a.nField2 – 1 

这是我的查询以其最简单的形式。

vField1 is a Varchar 
nField2 is an int (autonumber) 
vField3 is a Varchar 

我已经离开了WHERE子句,所以明白了逻辑,否则会使得这个nessessity。

说vField1是客户编号,客户有3个记录 nField2中的值是1,2和3连续。 vField3是一个状态

当更新来a.nField2 = 1没有a.nField2 -1所以它继续 当更新来a.nField2 = 2,b.nField2 = 1 当更新到a.nField2 = 3,b.nField2 = 2

因此,当更新是在a.nField2 = 2上,别名b反映了先前行上的内容(b.nField2 = 1) 而且它SET a.vField3的Varchar值= b.vField3

当更新位于a.nField2 = 3时,别名b反映了先前行上的内容(b.nField2 = 2) 而且它(应该)设置a.vField3 = b.vField3的Varchar值

当过程完成时 - 三条记录中的第二条记录与预期相符 - 第二条记录的vField3中的值反映第一条记录中vField3的值

但是,第三条记录的vField3并不反映第二条记录中vField3的值。

我认为这表明SQL Server可能正在生成某种事务然后进行更新。

问题:如何在每次事务后获得数据库更新,以便我可以引用每个事务生成的值?

谢谢。 davlyo

+0

“但是,第三条记录的vField3不反映第二条记录中vField3的值。”你得到了什么?你是指第二个记录的新值或原始值? – mdma 2010-06-09 21:58:34

+0

你从完全错误的角度出发,根据游标而不是逻辑集合操作来思考 - 阅读一本书并挖掘其中的差异,但不用担心,对于第一个处理SQL的程序员来说,这是一个非常常见的缺陷时间。 – Cruachan 2010-06-09 22:23:15

+0

我认为“tablename a”和“tablename b”实际上是2个不同的表,而不是一个具有两个不同别名的表? (这会使它成为一个自连接,而且毫无意义) – BradC 2010-06-09 22:28:23

回答

1

整个更新查询是一个操作 - 如果这是事务中唯一的事务,则为一个事务。所以,查询没有看到它自己的结果。该查询没有任何隐含的顺序 - 几乎就像它一次发生一样。

还要记住,这是一个自加入,所以最初的第二个/第三个记录不会在查询运行后。一个记录将被“丢失” - 原始的第三个记录,并且价值1的记录重复。

E.g.你开始,客户,aField2,aField3

mdma 1  A 
mdma 2  B 
mdma 3  C 

运行你的更新后,值将

mdma 1 A 
mdma 2 A 
mdma 3 B 

这就是你看到/期待?

3

首先,最重要的是,您误以为您的记录是“连续”保存的,因此事务将在逻辑上实现某种定义的循环。事实上,您的数据库中的记录的顺序是undefined,并且在所有以这种有序的方式考虑您的表存储是没有意义的。事实上,你应该尽量彻底摆脱它,否则它会导致你陷入各种陷阱和坏习惯。相反,试着从逻辑上考虑按照设置(数学意义上)操作执行的语句,而不是光标遍历。

当然,在大多数关系数据库中,没有ORDER BY子句的SELECT检索记录的顺序是按照插入顺序,但这是一个实现问题,实际上绝不应该依赖于任何逻辑(如果您关心订单,总是使用ORDER BY子句检索数据)。为了强调,根据ANSI SQL,没有ORDER BY子句的情况下,从数据库检索记录的顺序是未定义的 - 从技术上讲,甚至不需要在同一个SELECT语句的顺序执行上保持一致。

因此,为了使关系数据库上的UPDATE操作产生一致的结果,任何查询必须作为单个事务操作。该事务捕获它将更新的记录的快照,以一致的原子方式更新它们,然后将结果应用到数据。根本没有逻辑上的SQL循环记录或任何东西的概念。

+1

实际上,在大多数关系数据库中,如果没有指定ORDER BY,记录将按照* clustered index *的顺序检索,所以即使实现细节不支持FIFO记录排序的概念,除非你没有聚集索引(坏主意),或者你总是以与聚簇索引相同的顺序插入(只有当索引位于'IDENTITY'列上时才为真)。 – Aaronaught 2010-06-10 01:23:22

+0

@Aarounaught是的,你是正确的,尽管当然在大多数数据库上我使用大多数数据库,聚集索引是一个标识列,所以它实际上是插入顺序,但正如你指出的那样,这也是一个神器。 – Cruachan 2010-06-10 08:50:26