【问题标题】:Table or column name cannot start with numeric?表或列名不能以数字开头?
【发布时间】:2022-01-27 14:57:17
【问题描述】:

我尝试使用如下语法创建名为 15909434_user 的表:

CREATE TABLE 15909434_user ( ... )

当然会产生错误。然后,在我尝试与 google 进行一些研究后,我发现了一篇很好的文章 here 描述:

当你在 PostgreSQL 中创建一个对象时,你给这个对象一个名字。每个表都有一个名称,每个列都有一个名称,等等。 PostgreSQL 使用单一数据类型来定义所有对象名称:name 类型。

name 类型的值是 63 个或更少字符的字符串。名称必须以字母或下划线开头;字符串的其余部分可以包含字母、数字和下划线。

...

如果您发现需要创建不符合这些规则的对象,可以将名称用双引号括起来。将名称用引号括起来会创建一个带引号的标识符。例如,您可以创建一个名称为“3.14159”的表——双引号是必需的,但实际上不是名称的一部分(也就是说,它们没有被存储并且不计入 63 个字符的限制)。 ...

好的,现在我知道如何使用这种语法来解决这个问题(在表名上加上双引号):

CREATE TABLE "15909434_user" ( ... )

您可以创建表名或列名,例如"15909434_user"user_15909434,但不能创建以数字开头且不使用双引号的表名或列名。

那么,我很好奇这背后的原因(除了它是一个约定)。为什么应用这个约定?是为了避免语法限制还是其他原因?

提前感谢您的关注!

【问题讨论】:

    标签: sql postgresql naming-conventions


    【解决方案1】:

    它来自原始的 sql 标准,通过多层间接最终到达 identifier start 块,这是其中之一,但主要是“一个简单的拉丁字母”。还有其他可以使用的东西,但是如果您想查看所有详细信息,请转到 http://en.wikipedia.org/wiki/SQL-92 并点击实际标准的链接(第 85 页)

    使用非数字标识符引入器可以更轻松、更快速地编写解析器来解码 sql 以执行,但带引号的形式也可以。


    编辑:为什么解析器更容易?

    解析器的问题更多在于SELECT-list 子句而不是FROM 子句。 select-list 是从表中选择的表达式列表,它非常灵活,允许简单的列名和数字表达式。考虑以下几点:

    SELECT 2e2 + 3.4 FROM ...
    

    如果表名和列名可以以数字开头,则 2e2 是列名或有效数字(e 格式通常允许在数字文字中使用)并且是 3.4 表“3”和列“4”还是数值3.4

    标识符以简单的拉丁字母(和其他一些特定的东西)开头的规则意味着看到2e2的解析器可以快速识别这将是一个数字表达式,同样处理@ 987654332@

    虽然可以设计一个允许数字前导字符的方案,但这可能会导致更加晦涩的规则(意见),所以这个规则是一个很好的解决方案。如果您首先允许数字,那么它总是需要引用,这可以说不是“干净”。


    免责声明,我已经稍微简化了上面的内容,忽略了相关名称以保持简短。我对 postgres 并不完全熟悉,但已经根据 Oracle RDB 文档和 sql 规范仔细检查了上述答案

    【讨论】:

    • 我对 postgreSQL 解析器的工作原理还是个新手,我再次好奇为什么像 "123456_name"name_123456 这样的解码标识符比 123456_name 更容易和更快?
    【解决方案2】:

    我想这与语法有关。

    SELECT 24*DAY_NUMBER as X from MY_TABLE

    很好,但如果允许 24 作为列名,则不明确。

    添加引号意味着您明确引用标识符而不是常量。所以为了使用它,无论如何你总是必须逃避它。

    【讨论】:

    • 没错,就是为了减少解析中的歧义。在 PostgreSQL 中,解析器怪癖意味着 SELECT 123abcd 被解释为 SELECT 123 AS abcd 并没有帮助,即即使没有空格,数字后面的字符串也被视为列别名。
    • @LoztInSpace 好的,它明白了你的想法。但这是因为您在其中包含了运算符语法。使用像SELECT 24_DAY_NUMBER as X FROM MY_TABLE 这样的非运算符语法怎么样?它应该是明确的。
    • @CraigRinger +1 for SELECT 123abcd 被解释为 SELECT 123 AS abcd。我仍然缺少 SQL 语法解析中的歧义概念。为什么CREATE TABLE 15909434_userCREATE TABLE user_15909434 有歧义。对不起愚蠢的问题.. ;)
    • @iwawiwi 强制标识符以数字开头可以让解析器更简单并更早地报告错误。标准规定是,所以 PostgreSQL 无论如何都不能随意改变它。它的实现细节;除非你真的对递归下降解析器的胆量感兴趣,否则只要把它当作是这样的。
    • 好吧,我想如果我们继续讨论解析器,这里就跑题了。 @CraigRinger 你能用你的想法回答这个问题吗?或者通过添加您的想法来改进此答案。我愿意接受这个讨论作为答案.. :)
    猜你喜欢
    • 1970-01-01
    • 2020-07-07
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 2018-02-18
    相关资源
    最近更新 更多