在表中复制列名是否有用?

时间:2012-01-10 01:41:15

标签: sql sqlite

在sqlite3中,我可以强制两列别名为同名,如下面的查询所示:

SELECT field_one AS overloaded_name,
       field_two AS overloaded_name
FROM my_table;

返回以下内容:

overloaded_name  overloaded_name
---------------  ---------------
1                2
3                4
...              ...

......等等。

但是,如果我使用相同的语法创建一个命名表,它会将其中一个别名附加:1

sqlite> CREATE TABLE temp AS
          SELECT field_one AS overloaded_name,
                 field_two AS overloaded_name
          FROM my_table;
sqlite> .schema temp
CREATE TABLE temp(
  overloaded_name TEXT,
  "overloaded_name:1" TEXT
);

我运行原始查询只是为了看看这是否可行,我很惊讶它被允许。这样做有什么好的理由吗?假设没有,那么为什么允许这样做呢?

修改

我应该澄清一下:问题是双重的:为什么表格创作能够成功,而且(更重要的是)为什么首先允许原始选择?

另外,请参阅上面有关表创建的说明。

3 个答案:

答案 0 :(得分:3)

  

我可以强制两列别名为同名...   为什么首先允许[这个]?

这可归因于shackles of compatibility。在SQL标准中,没有任何东西被弃用。标准的早期版本允许表表达式的结果包含具有重复名称的列,可能是因为有影响力的供应商允许它,可能是由于包含错误或遗漏了设计特征,并且没有准备好承担破坏客户代码的风险(再次出现兼容性的枷锁)。

  

在表格中复制列名是否有用?

In the relational model, every attribute of every relation has a name that is unique within the relevant relation。仅仅因为SQL允许重复的列名称并不意味着你应该使用诸如功能之类的SQL编码器;事实上,我要说你必须警惕不要错误地调用这个功能。我想不出有任何好的理由在表中有重复的列名,但我可以想到许多明显的坏名称。这样的表格不是关系,也不是一件好事!

  

为什么允许[base]表创建成功

毫无疑问是对SQL标准(有目的地违反)的“扩展”,我认为它可以被视为一个合理的特征:如果我尝试创建具有重复名称的列,系统会通过添加序号来自动消除它们的歧义。事实上,SQL标准指定存在一种依赖于实现的方式来确保表表达式的结果不会隐式地具有重复的列名称(但正如您在问题中指出的那样,这并不包括来自的用户使用重复的AS子句明确。但是,我个人认为禁止重复名称和引发错误的标准行为是正确的。除了上述原因(即同一个表中的重复列没有用处)之外,创建对象的SQL脚本在不知道系统是否符合该名称的情况下容易出错。

答案 1 :(得分:1)

表本身不能有重复的列名,因为插入和更新会搞砸。哪一列获取数据?

在选择期间,“重复”只是列标签,所以不要伤害任何东西。

答案 2 :(得分:1)

我假设你在谈论CREATE TABLE ... AS SELECT命令。这看起来像是我的SQL扩展。

标准SQL不允许您对不同的列使用相同的列名,而SQLite似乎允许在其扩展中使用它,但是要解决它。虽然简单的裸select语句只使用as来设置列名,但create table ... as select使用它来创建包含这些列名的全新表。

  

顺便说一句,当您尝试使用重复列时,看看裸select的作用会很有趣,例如在order by子句中。< / p>

如果允许多个具有相同名称的列,那么执行引擎找出你的意思会有点困难:

select overloaded_name from table;

您可以在选择中执行此操作的原因是:

select id, surname   as name from users where surname is not null
union all
select id, firstname as name from users where surname is     null

这样您最终会得到一个 name列。

至于是否有充分的理由,SQLite 可能假设您在为两个不同的列指定相同的列名时知道自己在做什么。它的本质似乎是为用户提供了很大的自由度(例如,这些列是动态类型的事实所证明的)。

替代方法是简单地拒绝您的请求,这是更喜欢的,但SQLite的开发人员可能比我更自由(或更少肛门保留): - )< / p>