【问题标题】:Determine when an SQL alias can be an open name确定 SQL 别名何时可以是开放名称
【发布时间】:2017-11-06 06:49:38
【问题描述】:

确定表示 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
}

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

  • 它是一个相同大小写的单个单词,没有空格
  • 它可以包含下划线,并且可以以一个开头
  • 可以包含数字和$,但不能以这些开头

【问题讨论】:

  • 是关键字(postgresql.org/docs/9.6/static/sql-keywords-appendix.html)吗?它不是以字母开头还是包含除字母(允许变音符号)、数字和下划线以外的任何字符?
  • 不会将每个标识符都放在双引号中,然后检查标识符是否需要它吗?..
  • @GordonLinoff 是的,我相信在双引号中,它绝对可以是任何字符串(至少 1 个符号更长)。为了使它成为开放语法,它肯定不能包含空格,或者至少不同大小写的字母。
  • @VaoTsun - 更便宜 - 是的,但正如我在问题中所说,我希望在不牺牲性能的情况下使 SQL 更精简、更易于阅读。主要是因为您的典型 SQL 是一个非常短的名称,不需要扩展语法。
  • 我认为您可以安全地添加下划线和美元符号alias.match(/[a-z_][a-z_$0-9]*|[A-Z_][A-Z_$0-9]*/);

标签: node.js regex postgresql pg-promise


【解决方案1】:

删除双引号是令人钦佩的——它确实使查询更易于阅读。规则非常简单。 “有效”标识符包括:

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

(我想我的总结是正确的。真正的规则在documentation。)

前两个很容易使用正则表达式实现。最后一个可能需要一个用于查找的参考表(并且该列表因 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"(至少没有我能轻易想到的)。

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

另一方面,规则确实允许:

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

(这将返回 1、2、3。)

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

【讨论】:

  • 我已经用我第一次尝试的例子更新了我的问题。你怎么看?我在想,如果我涵盖了最有用的情况,那就足够了……毕竟,我只是在清理语法。
  • @vitaly-t 。 . .实际上,我的回答的寓意是您需要为任何混合大小写标识符使用引号 - 除非您知道它是唯一的,无论查询中的大小写如何。这很可悲,但如果你做的事情是通用的,你需要支持最后一个例子,或者明确排除它。
  • 谢谢!在此之后,我已经为我最终提出的问题添加了解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 2017-10-24
  • 2012-10-01
  • 2013-09-06
相关资源
最近更新 更多