知识卡片
EXTEND扩展运算符与SQL SELECT-FROM-WHERE模板的局限
内容
原始关系代数(限制/投影/连接/并/交/差)完全没有计算能力,无法表达类似”把零件
重量从磅换算成克”这种需要算术运算的查询。EXTEND补上了这块能力,精确定义是:
给定关系r及r中没有的属性名X,EXTEND r:{X:=exp}是标题为r的标题加上属性X、
主体由r每个元组添加一个按exp计算出的X属性值构成的关系——结果基数不变、度加1。
和RENAME、其他表达式一样,EXTEND只是表达式,不改变数据库中任何关系变量,可以
自由嵌套。EXTEND暴露出SQL的SELECT-FROM-WHERE模板一个结构性缺陷:查询”重量
大于7000克的零件编号和克重”,Tutorial D可以直接写(EXTEND P:{GMWT:=WEIGHT*
454}) WHERE GMWT>7000(先扩展再限制,扩展出来的属性可以立刻在WHERE里用),
但等价的原始SQL写法SELECT PNO,WEIGHT*454 AS GMWT FROM P WHERE GMWT>7000
在标准SQL里编译失败——因为WHERE子句作用于FROM子句的结果,此时表P还没有GMWT
这一列,SELECT子句才是真正引入GMWT的地方,但SELECT-FROM-WHERE模板强制要求
WHERE只能作用在FROM结果上、SELECT必须放在最后一步。这暴露了一个更普遍的问题:
关系代数因为[[关系代数的闭包性质]]支持运算以任意方式组合和嵌套(先扩展、再
限制、再连接、再限制……顺序随意),而SQL固定的SELECT-FROM-WHERE三段式模板
把查询硬性限定为”积→限制→若干投影/扩展/更名的组合”这一种固定顺序,很多查询
其实并不天然符合这个模式,只能靠嵌套子查询(FROM (SELECT... AS GMWT FROM P)
AS TEMP WHERE TEMP.GMWT>7000)来绕过这个限制——这也解释了为什么SQL的FROM
子句里嵌套子查询必须强制加一个AS别名(哪怕这个别名从未被引用),因为语法上
它定义的是一个区间变元(range variable),这个声明步骤本身无法省略。