确定 SQL 别名何时可以是开放名称

Determine when an SQL alias can be an open name

确定表示 SQL 别名的字符串是否需要用双引号引起来的最高性能实现是什么?

目前,在 pg-promise 中,我将每个别名用双引号括起来,以确保安全。如果可能的话,我希望使输出 SQL 更简洁。

我认为哪种方法最好 -


基本上,我希望改进功能 as.alias,如果可能的话,不要在不需要时将别名括在双引号中。


到目前为止我尝试了什么...

一开始我想只对 99% 的情况这样做——当你的别名是最典型的时候不要添加双引号,只是一个简单的词:

function skipQuotes(alias) {
    const m = alias.match(/[A-Z]+|[a-z]+/);
    return m && m[0] === alias;
}

这只检查它是一个使用大写或小写的单词,而不是组合。


解决方案

根据答案,我最终实现了应涵盖所有实际用例的 99%,这正是我试图实现的目标:

const m = alias.match(/[a-z_][a-z0-9_$]*|[A-Z_][A-Z0-9_$]*/);
if (m && m[0] === alias) {
    // double quotes will be skipped
} else {
    // double quotes will be added
}

即当别名使用简单语法时,不添加周围的双引号:

删除双引号令人钦佩——它确实使查询更易于阅读。规则很简单。 "valid" 标识符包括:

  • 字母(包括变音符号)、数字、下划线和美元符号。
  • 以字母(包括变音符号)或下划线开头。
  • 不是保留字。

(我想我总结得没错。真正的规则在documentation。)

前两个很容易使用正则表达式实现。最后一个可能需要一个参考 table 来查找(列表因 Postgres 版本而异——尽管比你想象的要少)。

否则,标识符需要用转义字符包围。 Postgres 使用双引号(这是 ANSI 标准)。

您可能想要这样做的一个原因是因为 Postgres 将标识符转换为小写以进行比较。因此,以下工作正常:

select xa, Xa, xA, "xa"
from (select 1 as Xa) y

但是,这不起作用:

select Xa
from (select 1 as "Xa") y

也没有:

select "Xa"
from (select 1 as Xa) y

事实上,不使用引号是无法引用 "Xa" 的(至少 none 我很容易想到)。

强制执行完全匹配的规则可能是好事也可能是坏事。我发现一门学科太多了:我承认在编写 "casual" 代码时经常忽略大小写;没有大写(或使用双引号)的输入更简单。对于更正式的代码,我尽量保持一致。

另一方面,规则允许:

select "Xa", "aX", ax
from (select 1 as "Xa", 2 as "aX", 3 as AX) y

(这个 returns 1, 2, 3.)

这是一个命名约定,如果不允许,我会很高兴。