知识卡片

命名子表达式技术简化复杂变换的推导过程

普通读书笔记卡

内容

当逻辑表述式变得复杂(如”获得所供应零件都在同一城市的供应商”这类嵌套多层 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代码”想表达的核心态度。

参考来源

- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第11章"使用逻辑 表述SQL表达式"11.6节"例5:命名子表达式"、11.7节"例6:关于命名子表达式的 更多内容"(源文件:OEBPS/text00124.html、text00125.html) - 结论依据:原文明确"一个有用的技术就是为子查询引入符号名称来进行稍微的 抽象……我们可以既见森林又见树木……为子表达式引入名称的策略会多少让人 想起第6章中使用WITH简化复杂查询。然而两者是有区别的:对于WITH,子表达式 要求是闭合的,而这是当前上下文中并未要求的……我们确信这些表达式是正确 的,因为导出它们的方式是系统化的方式"。 - 原始内容:一个有用的技术就是为子查询引入符号名称来进行稍微的抽象…… 两者是有区别的:对于WITH,子表达式要求是闭合的……我们确信这些表达式是 正确的,因为导出它们的方式是系统化的方式。