确定 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.)
这是一个命名约定,如果不允许,我会很高兴。
确定表示 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.)
这是一个命名约定,如果不允许,我会很高兴。