每天进步一点点:SQL 当标识符(字段名、列名)遇到保留关键字

这两天在用HIVESQL查询时遇到个有意思的小问题,那就是当字段名为SQL关键字时,会被提示语句不正确。

image.png
(图源 :pixabay)

比如下面这条语句:

SELECT TOP 20 * 
FROM txtransfers 
WHERE from = 'binance-hot2' 
ORDER BY timestamp DESC;

尝试执行时就会出现如下错误:

Error 156: Incorrect syntax near the keyword 'from'.

image.png

其中txtransfers表(视图)结构如下:
1701752786996.png

上述SQL查询,我期待的是,返回最近20条从币安热钱包转出记录。但是很明显,解释程序将字段名from当作了关键字,所以就没法正常解释并执行上述语句啦。

同理,想查询这个账户最近20条转入记录,也是无法执行的:
image.png

那么问题来了,如果想按我们设想的那样,去查询币安热钱包(或者任意账户)的最近20条转出或者转入记录,该如何处理呢?

我首先尝试地是给字段名加上单引号'',将查询语句变成这个样子:

SELECT TOP 20 * 
FROM txtransfers 
WHERE 'from'= 'binance-hot2' 
ORDER BY timestamp DESC;

很开心,这次没报错😀,但是等等?先不要开心,为什么一条结果都没有查询出来?

这个样子显然是不对的呀?
image.png

尝试使用双引号,则一且正常(为了便于截图展示,改成查询5条内容)

1701753997946.png

好,现在我们已经解决了这个问题,那就是在查询中,把作为字段名的关键字用双引号""包裹起来,这样就不会有歧义啦。

那新疑问来了?这就是最佳或者说最优雅的解决方案吗?查了一下微软的相关文档,文档中有以下内容:

Microsoft SQL Server uses reserved keywords for defining, manipulating, and accessing databases. Reserved keywords are part of the grammar of the Transact-SQL language that is used by SQL Server to parse and understand Transact-SQL statements and batches. Although it is syntactically possible to use SQL Server reserved keywords as identifiers and object names in Transact-SQL scripts, you can do this only by using delimited identifiers.

加粗的地方翻译过来就是尽管在语法上可以使用 SQL Server 保留关键字作为 Transact-SQL 脚本中的标识符和对象名称,但只能通过使用分隔标识符来实现此目的。

而在另外一篇文章中,找到了如下两段内容:

Delimited identifiers
Are enclosed in double quotation marks (") or brackets ([ ]). Identifiers that comply with the rules for the format of identifiers might not be delimited.

Rules for regular identifiers中的第三条部分内容:

The identifier must not be a Transact-SQL reserved word. SQL Server reserves both the uppercase and lowercase versions of reserved words. When identifiers are used in Transact-SQL statements, the identifiers that do not comply with these rules must be delimited by double quotation marks or brackets.

综上,在数据库中使用保留关键字作为标识符是不被建议的,如果这样做了,那么查询等操作用到到这个标识符的时候,就要用双引号或者方括号括起来( enclosed in double quotation marks (") or brackets ([ ]).)

而对于HIVESQL中txtransfers表,我觉得尽管用fromto两个保留关键字作了标识符(字段名),但是对于HIVE区块链的Transfer操作而言,这么命名无疑是最清晰明朗的。所以只能在查询语句上费一丁点小周折啦。

嗯,相比双引号,我觉得用方括号更优雅一些,所以最终的查询应该是这个样子:

SELECT TOP 5 * 
FROM txtransfers 
WHERE [from] = 'binance-hot2' 
ORDER BY timestamp DESC;

试了一下,完美工作:

1701768671835.png

虽然只是小小的一丁点技巧,但是我翻了纸质的数据库教材《数据库系统概论》,里边还真没这个内容。我就说当年这教材我学的如此透彻,怎么遇到这个问题还被绊倒了呢?

把这个小技巧记录于此,一则避免自己忘记,二则给可能遇到类似问题的朋友一点小帮助吧。

相关链接

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center