想象一下,我有两个表, t1 和 t2 。 t1 有两个字段,一个包含名为 a 的唯一值,另一个字段名为值。表 t2 的字段不包含名为 b 的唯一值和一个名为值的字段。 现在,如果我使用以下更新查询(这是使用MS Access btw):
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中结束的值是什么?我运行了一些测试,但找不到一致的行为,所以我猜它可能是未定义的。或者这种更新查询是不应该做的事情?关于为什么我必须这样做,有一个漫长的无聊故事,但这与我的调查的技术性质无关。
答案 0 :(得分:2)
这称为非确定性查询,它意味着您发现可以多次运行查询而不更改查询或基础数据并获得不同结果。
在实践中会发生什么是使用上次遇到的记录更新值,因此在您的情况下它将更新两次,但第一次更新将被最后覆盖。你完全无法控制的是SQL引擎访问记录的顺序,它会以它认为合适的顺序访问它们,这可能只是从开始的聚簇索引扫描,或者它可以使用其他索引并访问聚簇索引的顺序不同。你无从知晓这一点。很可能多次运行更新会产生相同的结果,因为没有对数据进行更改,sql优化器将使用相同的查询计划。但同样不能保证,所以你不应该依赖非确定性查询来获得确定性结果。
修改强>
要将T1中的值更新为T2中的最大对应值,您可以使用DMax
:
UPDATE T1
SET Value = DMax("Value", "T2", "b=" & T1.a);
答案 1 :(得分:1)
当你按照你所指示的那样执行查询时,由于“t2”有多行的事实,“m”行中以“t1”结尾的“值”实际上是随机的。身份值'm'。
除非您明确指定您希望最大(最大函数),最小(最小函数)或具有标识“m”的行集合的某些其他聚合,否则数据库无法进行已定义的选择,并且这样返回它首先遇到的任何值,因此行为不一致。
希望这有帮助。