7

我正在阅读 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)

现在,我了解到第一个查询与关系模型不符,因为元组(行)是无序的属性集(列)。我无法理解第一个查询中的危害在哪里。谁可以给我解释一下这个?

4

9 回答 9

20

每当表架构更改时,第一个查询几乎都会中断。第二个查询适应任何模式更改,使其列保持不变并且不添加无默认列。

出于同样的原因,进行SELECT *查询然后依赖位置符号来提取他们关注的值的人是软件维护的超级恶棍。

于 2009-07-04T21:01:17.003 回答
9

虽然在模式中定义了列的顺序,但通常不应将其视为重要,因为它在概念上并不重要。

此外,这意味着任何阅读第一个版本的人都必须查阅架构以找出这些值的含义。诚然,这就像在大多数编程语言中使用位置参数一样,但不知何故,SQL 在这方面感觉略有不同——我当然会更容易理解第二个版本(假设列名是合理的)。

于 2009-07-04T21:03:19.090 回答
5

我并不真正关心这方面的理论概念(实际上,表确实具有定义的列顺序)。我更喜欢第二个而不是第一个的主要原因是增加了抽象层。您可以修改表中的列,而不会搞砸查询。

于 2009-07-04T21:01:51.150 回答
2

您应该尝试使您的 SQL 查询尽可能少地依赖于表的确切布局。

第一个查询依赖于只有三个字段的表,并且按照这个确切的顺序。对表的任何更改都会中断查询。

第二个查询只依赖表中有这三个字段,字段的顺序无关紧要。您可以在不中断查询的情况下更改表中字段的顺序,甚至可以添加字段,只要它们允许空值或具有默认值即可。

尽管您不经常重新排列表格布局,但向表格添加更多字段是很常见的。

此外,第二个查询更具可读性。您可以从查询本身中看出记录中的值是什么意思。

于 2009-07-04T21:16:00.530 回答
2

尚未提及的事情是,您通常会将代理键作为您的 PK,并使用auto_increment(或类似的东西)分配一个值。对于第一个,你必须在那里指定一些东西——但是如果它不被使用,你可以指定什么值?NULL可能是一个选项,但这并不真正适合考虑将 PK 设置为NOT NULL.

但除此之外,整个“锁定到特定模式”是一个更重要的原因,IMO。

于 2009-07-04T22:21:45.483 回答
1

SQL 为您提供了为 INSERT 和 SELECT 语句指定列名的语法。您应该使用它,因为:

  • 您的查询对于列顺序的变化是稳定的,因此维护工作量更少。
  • 列排序更好地映射了人们的想法,因此更具可读性。将列视为“名称”列而不是第二列更清楚。
于 2009-07-04T21:28:23.500 回答
1

我更喜欢使用类似 UPDATE 的语法:

INSERT t SET one = 1 , two = 2 , three = 3

这比这两个例子更容易阅读和维护。

于 2009-07-04T22:15:44.060 回答
1

从长远来看,如果您在表中再添加一列,则 INSERT 将不起作用,除非您明确指定列列表。如果有人更改了列的顺序,您的 INSERT 可能会默默地成功将值插入错误的列。

于 2009-07-04T22:20:53.567 回答
0

我还要添加一件事,即使在更改表之前,第二个查询也不太容易出错。我为什么这么说?因为使用 seocnd 表单,您可以(并且应该在编写查询时)直观地检查插入表中的列以及 values 子句或 select 子句中的数据实际上是否以正确的顺序开始。否则,您最终可能会意外将社会安全号码放在酬金字段中,并向演讲者支付他们的 SSN,而不是他们应该为演讲支付的金额(示例不是随机选择的,除非我们确实在它实际发生之前抓住了它,这要归功于目视检查!)。

于 2010-12-22T15:31:27.943 回答