知识卡片
命名子表达式技术简化复杂变换的推导过程
内容
当逻辑表述式变得复杂(如”获得所供应零件都在同一城市的供应商”这类嵌套多层
FORALL/EXISTS的查询)时,[[全称量词化的系统化SQL映射步骤]]的固定五步流程
本身会被大量重复的子表达式文本淹没,难以看清整体结构。书中给出的实用技巧
是引入命名子表达式:把参与变换的子表达式(如PX.COLOR='Purple'记作exp1,
EXISTS SPX(SPX.SNO=SX.SNO AND SPX.PNO=PX.PNO)记作exp2)先用符号名代替,
让整条推导链变成FORALL PX(IF exp1 THEN exp2)→NOT EXISTS PX(NOT(IF
exp1 THEN exp2))→…→NOT EXISTS PX(exp1 AND NOT(exp2))这种”既见森林
又见树木”的简洁形式,等推导完成后再把exp1、exp2展开回具体SQL文本、拼装成
最终的CREATE ASSERTION或SELECT语句。这个技巧和[[逐步形成表达式]](第6章)
里的WITH子句有本质区别:WITH要求被命名的子表达式必须是”闭合的”(不依赖
外部上下文即可独立求值),而这里的命名子表达式技术只是单纯的文本替换,
对exp1、exp2是否闭合没有任何要求——命名的目的纯粹是帮助人类在推导过程中
保持思路清晰,不是为了生成一段真正可执行、可复用的中间表达式。这个技巧
的价值在于揭示了本章方法论的一个诚实局限:即使推导过程本身完全严谨、可
验证,最终产出的SQL表达式往往依然十分晦涩难懂(比如”获得所供应零件都在
同一城市的供应商”最终对应的NOT EXISTS嵌套写法,脱离推导过程直接去看几乎
无法一眼理解),书中的立场是——这种晦涩是可以接受的代价,因为通过系统化
方法推导出来的表达式即使难懂,也一定是正确的,这也正是全书副标题”如何写
精确的SQL代码”想表达的核心态度。