我正在阅读CJ Date的SQL and Relational Theory: How to Write Accurate SQL Code,他认为位置查询很糟糕 - 例如,INSERT
:
INSERT INTO t VALUES (1, 2, 3)
相反,您应该使用基于属性的查询,如下所示:
INSERT INTO t (one, two, three) VALUES (1, 2, 3)
现在,我知道第一个查询与关系模型不一致,因为元组(行)是无序的属性集(列)。我无法理解第一个查询中的伤害位置。有人可以向我解释一下吗?
答案 0 :(得分:20)
第一个查询在表架构更改的任何时候都会中断。第二个查询适应任何架构更改,使其列保持不变,并且不添加无默认列。
执行SELECT *
查询然后依靠位置表示法提取他们关注的值的人software maintenance supervillains出于同样的原因。
答案 1 :(得分:9)
虽然在模式中定义了列的顺序,但它通常不应被视为重要,因为它不是在概念上重要。
此外,这意味着阅读第一个版本的任何人都必须查阅架构,以找出值的含义。不可否认,这就像在大多数编程语言中使用位置参数一样,但在某种程度上SQL在这方面感觉略有不同 - 我当然更容易理解第二个版本(假设列名是明智的)。
答案 2 :(得分:5)
我并不关心这方面的理论概念(在实践中,表确实有定义的列顺序)。我更喜欢第二个到第一个的主要原因是添加的抽象层。您可以修改表格中的列而不会搞砸您的查询。
答案 3 :(得分:2)
您应该尝试尽可能少地使SQL查询依赖于表的确切布局。
第一个查询依赖于只有三个字段的表,并且按照确切的顺序。对表格的任何改变都将破坏查询。
第二个查询仅依赖于表中存在这三个字符,并且字段的顺序无关紧要。您可以在不破坏查询的情况下更改表中字段的顺序,甚至可以添加字段,只要它们允许空值或具有默认值。
虽然您不经常重新排列表格布局,但在表格中添加更多字段非常常见。
此外,第二个查询更具可读性。您可以从查询本身判断记录中的值是什么意思。
答案 4 :(得分:2)
尚未提及的一点是,您将经常使用代理键作为PK,使用auto_increment
(或类似的东西)来分配值。对于第一个,您必须在那里指定某些东西 - 但是如果不使用它,您可以指定什么值? NULL
可能是一个选项,但这并不适合考虑将PK设置为NOT NULL
。
但除此之外,整个“锁定到特定架构”是一个更重要的原因,IMO。
答案 5 :(得分:1)
SQL为您提供了为INSERT和SELECT语句指定列名称的语法。你应该使用它,因为:
答案 6 :(得分:1)
我更喜欢使用类似UPDATE的语法:
INSERT t SET one = 1 , two = 2 , three = 3
这比两个示例都更容易阅读和维护。
答案 7 :(得分:1)
长期来看,如果您向表中再添加一列,除非明确指定列列表,否则INSERT将无效。如果有人更改了列的顺序,您的INSERT可能会默默地将值插入到错误的列中。
答案 8 :(得分:0)
我要再添加一个东西,即使在更改表之前,第二个查询也不太容易出错。我为什么这么说?使用seocnd表单可以(并且应该在编写查询时)直观地检查插入表中的列以及values子句或select子句中的数据是否实际上以正确的顺序开头。否则你最终可能会在Honoraria字段中放入社会安全号码,并向发言人支付他们的SSN而不是他们应该为演讲所做的金额(例子不是随机选择的,除非我们确实在实际发生之前抓住了它,因为目视检查!)。