从Access迁移至SQLite:自连接更新语句执行后结果全为NULL
Fixing SQLite Update Query for WBS Level Calculation
你的问题出在子查询会对所有行执行更新,包括那些没有匹配父节点的行——当某个ParentWBS在表中找不到对应的WBS时,子查询返回NULL,导致该行的WBSLevel被覆盖成NULL,而原Access的INNER JOIN只会更新存在匹配父节点的行,不匹配的行保持原值。
下面提供两种符合SQLite语法的解决方案,根据你的SQLite版本选择:
方案1:使用UPDATE ... FROM(SQLite 3.33.0+)
这是最接近Access自连接逻辑的写法,利用SQLite的FROM子句实现自连接更新,只修改有匹配父节点的行:
UPDATE FF_WBS_CONSOL SET WBSLevel = P.WBSLevel + 1 FROM FF_WBS_CONSOL AS P WHERE FF_WBS_CONSOL.ParentWBS = P.WBS;
方案2:子查询+WHERE EXISTS(兼容旧版本SQLite)
如果你的SQLite版本低于3.33.0,可以用这个写法,先通过WHERE EXISTS筛选出有匹配父节点的行,再执行更新:
UPDATE FF_WBS_CONSOL SET WBSLevel = ( SELECT P.WBSLevel + 1 FROM FF_WBS_CONSOL AS P WHERE FF_WBS_CONSOL.ParentWBS = P.WBS ) WHERE EXISTS ( SELECT 1 FROM FF_WBS_CONSOL AS P WHERE FF_WBS_CONSOL.ParentWBS = P.WBS );
为什么你的原语句会全为NULL?
当表中存在ParentWBS为空或者没有对应WBS的行时,子查询SELECT P.WBSLevel+1 ...会返回NULL,而你的语句没有添加过滤条件,导致所有行(包括无父节点的)都被更新为NULL。上面的两种方案都会只更新存在有效父节点的行,避免这种问题。
另外,SQLite中不需要给表名和字段名加方括号(除非包含特殊字符),去掉[]能让语句更简洁易读。
内容的提问来源于stack exchange,提问作者midnite11
相关产品推荐
相关产品推荐

