4

想象一下,我有两个表,t1t2t1有两个字段,一个包含称为a的唯一值,另一个包含称为value的字段。表t2有一个包含唯一值的字段b和一个字段也称为value。现在,如果我使用以下更新查询(这是使用 MS Access 顺便说一句):

UPDATE t1
INNER JOIN t2 ON t1.a=t2.b
SET t1.value=t2.value

如果我有以下数据

     t1                  t2
 a  | value          b  | value
------------        ------------
'm' |  0.0           'm'|  1.1
                     'm'|  0.2

并运行查询 t1.value 中的最终值是什么?我进行了一些测试,但找不到一致的行为,所以我猜它可能只是未定义。或者这种更新查询是不应该做的事情?关于为什么我必须这样做,有一个很长很无聊的故事,但这与我调查的技术性质无关。

4

2 回答 2

3

这被称为非确定性查询,这意味着您发现可以多次运行查询而无需更改查询或基础数据并获得不同的结果。

在实践中发生的情况是该值将使用遇到的最后一条记录进行更新,因此在您的情况下,它将更新两次,但第一次更新将被最后一次覆盖。您完全无法控制的是 SQL 引擎以什么顺序访问记录,它将以任何它认为合适的顺序访问它们,这可能只是从一开始就进行聚集索引扫描,或者它可以使用其他索引并访问聚集索引以不同的顺序。你没有办法知道这一点。多次运行更新很可能会产生相同的结果,因为在不更改数据的情况下,sql 优化器将使用相同的查询计划。但同样不能保证,因此您不应依赖非确定性查询来获得确定性结果。


编辑

要将 T1 中的值更新为 T2 中的最大值对应值,您可以使用DMax

UPDATE  T1
SET     Value = DMax("Value", "T2", "b=" & T1.a);
于 2013-08-15T09:18:08.880 回答
1

当您按照您的指示执行查询时,由于“t2”具有多个用于标识值的行,因此以“t1”结尾的“m”行的“值”实际上将是随机的'我'。

除非您明确指定您想要最大(最大函数)、最小(最小函数)或具有标识“m”的行集合的其他聚合,否则数据库无法做出定义的选择,因此返回任何它首先遇到的价值,因此不一致的行为。

希望这可以帮助。

于 2013-08-15T09:14:36.540 回答