知识卡片
SQL列命名与位置依赖:关系化使用SQL的实践规则
内容
关系模型强制要求所有属性都有名称、且同一关系内属性名互不相同(不允许匿名或
重名属性);SQL对这条规则的执行并不彻底——只有当表恰好是CREATE TABLE/CREATE
VIEW定义的表变量当前值时才强制执行,一旦表是某个表达式(如VALUES(...)表值
构造器、未加AS的聚合列)的返回结果,就可能出现匿名列或重名列。这直接关系到
关系代数运算符(如UNION)依赖属性名而非位置来匹配对应列的语义能否在SQL里被
正确复现,因此产生一组关系化使用SQL的实践规则:只要有必要就用AS子句给列
起恰当名字;两个SQL列如果代表”同种类型的信息”应尽量用同一个名字(这也是
suppliers-and-parts示例里两个表的供应商编号列都统一叫SNO的原因);反之如果
两列代表不同类型的信息,应给不同名字;同一张表内两个列代表同种信息时(如员工表
里的员工编号ENO和经理编号MNO,经理编号本质也是员工编号)则必须用不同名字区分,
必要时通过重命名SELECT/AS来达成。面对不受自己控制、命名本就不规范的既有数据库,
可行的变通策略是为每张基表定义一个列名规范化的视图,后续查询一律针对视图而不是
底层基表操作。除了命名,SQL还有大量位置依赖的地方是关系模型完全没有对应物的
(SELECT *、多表FROM子句、显式JOIN、未指定CORRESPONDING的UNION/INTERSECT/
EXCEPT、无列名列表的INSERT、VALUES表达式、行赋值与比较等),书中强烈建议
:不要编写依赖列位置的SQL代码。
参考来源
- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第3章"元组、关系、行、表"
3.8节"SQL中的表"、3.9节"SQL中的列命名"(源文件:OEBPS/text00038.html、
text00039.html)
- 结论依据:原文明确"规则在表恰好是通过CREATE TABLE和CREATE VIEW定义的表变量
的当前值时被执行,但是对于表是某些表达式的返回结果的情况则不执行……如果SQL
中的两列表示'同种类型的信息',无论如何也要尽可能给它们同一名称……不要编写
依赖于位置的SQL代码",并列出多处位置依赖场景。
- 原始内容:只要有必要(且可能),就要使用AS子句给列取恰当的列名,否则就会
根本没有名字或者会有不唯一的名字……如果SQL中的两列表示"同种类型的信息",
无论如何也要尽可能给它们同一名称……不要编写依赖于位置的SQL代码。