这是我的第一篇帖子!忍受我。 我有一个更新声明,我试图了解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) 它设置了a.vField3 = b.vField3
的Varchar值当更新位于a.nField2 = 3时,别名b反映了先前行上的内容(b.nField2 = 2) 它(应该)设置a.vField3 = b.vField3
的Varchar值当进程完成时 - 三条记录中的第二条按预期显示 - 第二条记录的vField3中的值反映了第一条记录中vField3中的值
但是,第三条记录的vField3没有反映第二条记录中vField3中的值。
我认为这表明SQL Server可能正在生成某种事务,然后进行更新。
问题:如何在每次交易后让数据库更新,以便我可以引用每笔交易产生的值?
谢谢。 davlyo
答案 0 :(得分:3)
首先,最重要的是,你错误地认为交易会在逻辑上实现某种定义的循环,因为你的记录是“连续”保存的。实际上,您的数据库中记录的顺序是未定义,根本根据这种有序的方式考虑您的表存储是没有意义的。事实上,你应该试着完全摆脱它,否则它会引导你陷入各种各样的陷阱和坏习惯。请尝试逻辑地考虑以set(在数学意义上)操作而不是光标遍历执行的语句。
在大多数关系数据库中,没有ORDER BY子句的SELECT将检索记录的顺序当然是按插入顺序排列的,但这是一个实现问题,实际上永远不应该依赖于任何逻辑(如果您关心订单,请始终使用ORDER BY子句检索数据)。为了强调,根据ANSI SQL,没有ORDER BY子句就没有定义从数据库中检索记录的顺序 - 从技术上讲,它甚至不必在顺序执行相同的SELECT语句时保持一致。
因此,为了使关系数据库上的UPDATE操作产生一致的结果,任何查询都必须作为单个事务运行。该事务抓取它将更新的记录的快照,以一致的原子方式更新它们,然后将结果应用回数据。没有逻辑概念的SQL循环记录或其他任何东西。
答案 1 :(得分:1)
整个更新查询是一个操作 - 如果这是事务中的唯一事务,则是一个事务。因此,查询不会看到它自己的结果。查询在没有任何隐含顺序的情况下运行 - 几乎就像一次性发生一样。
另外请记住,这是一个自联接,所以最初的第二个/第三个记录不会在查询运行之后。一条记录将“丢失” - 原始的第三条记录,而值为1的记录重复。
E.g。首先是Customer,aField2,aField3
mdma 1 A
mdma 2 B
mdma 3 C
运行更新后,值将为
mdma 1 A
mdma 2 A
mdma 3 B
这是你所看到/期待的吗?