这两天在用HIVESQL查询时遇到个有意思的小问题,那就是当字段名为SQL关键字时,会被提示语句不正确。
(图源 :pixabay)
比如下面这条语句:
SELECT TOP 20 *
FROM txtransfers
WHERE from = 'binance-hot2'
ORDER BY timestamp DESC;
尝试执行时就会出现如下错误:
Error 156: Incorrect syntax near the keyword 'from'.
其中txtransfers表(视图)结构如下:
上述SQL查询,我期待的是,返回最近20条从币安热钱包转出记录。但是很明显,解释程序将字段名from
当作了关键字,所以就没法正常解释并执行上述语句啦。
同理,想查询这个账户最近20条转入记录,也是无法执行的:
那么问题来了,如果想按我们设想的那样,去查询币安热钱包(或者任意账户)的最近20条转出或者转入记录,该如何处理呢?
我首先尝试地是给字段名加上单引号''
,将查询语句变成这个样子:
SELECT TOP 20 *
FROM txtransfers
WHERE 'from'= 'binance-hot2'
ORDER BY timestamp DESC;
很开心,这次没报错😀,但是等等?先不要开心,为什么一条结果都没有查询出来?
这个样子显然是不对的呀?
尝试使用双引号,则一且正常(为了便于截图展示,改成查询5条内容)
好,现在我们已经解决了这个问题,那就是在查询中,把作为字段名的关键字用双引号""
包裹起来,这样就不会有歧义啦。
那新疑问来了?这就是最佳或者说最优雅的解决方案吗?查了一下微软的相关文档,文档中有以下内容:
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表,我觉得尽管用from
与to
两个保留关键字作了标识符(字段名),但是对于HIVE区块链的Transfer操作而言,这么命名无疑是最清晰明朗的。所以只能在查询语句上费一丁点小周折啦。
嗯,相比双引号,我觉得用方括号更优雅一些,所以最终的查询应该是这个样子:
SELECT TOP 5 *
FROM txtransfers
WHERE [from] = 'binance-hot2'
ORDER BY timestamp DESC;
试了一下,完美工作:
虽然只是小小的一丁点技巧,但是我翻了纸质的数据库教材《数据库系统概论》,里边还真没这个内容。我就说当年这教材我学的如此透彻,怎么遇到这个问题还被绊倒了呢?
把这个小技巧记录于此,一则避免自己忘记,二则给可能遇到类似问题的朋友一点小帮助吧。