编辑: 这个问题是关于在SELECT修改关键字和函数上找到对MySQL语法的明确引用。 / EDIT
AFAIK SQL定义了DISTINCT关键字的两种用法 - SELECT DISTINCT字段...和SELECT COUNT(DISTINCT字段)... 但是,在我管理的一个Web应用程序中,我注意到了诸如
之类的查询的性能问题SELECT DISTINCT(field1), field2, field3 ...
单个列上的DISTINCT()毫无意义,我几乎可以肯定它被解释为
SELECT DISTINCT field1, field2, field3 ...
但我怎么能证明这一点?
我搜索了mysql网站以获取有关此特定语法的参考,但找不到任何内容。有没有人在mysql中有关于DISTINCT()定义的链接或知道其他权威来源?
最佳
EDIT 在mysql论坛上问了同样的问题后,我了解到虽然解析SQL mysql并不关心函数和列名之间的空格(但我仍然缺少引用)。
看起来你可以在函数和括号之间有空格
SELECT LEFT (field1,1), field2...
并获取mysql将其理解为SELECT LEFT(field,1)
类似地,SELECT DISTINCT(field1),field2 ......似乎被分解为 SELECT DISTINCT(field1),field2 ...然后DISTINCT不是作为一些未定义(或未记录)的函数,而是作为SELECT修改关键字和field1周围的括号被评估为它们是字段表达式的一部分。
如果某人有指向文档的指针,声明函数和括号之间的空白并不重要,或者提供指向适当的MySQL论坛,邮件列表的链接,我可以提出一个问题将其放入参考
EDIT 我找到了对服务器选项IGNORE SPACE的引用。 它声明“IGNORE SPACE SQL模式可用于修改解析器如何处理对空格敏感的函数名称”,稍后它会声明最新版本的mysql已将此数字从200减少到30。
其余30个中的一个是例如COUNT。 启用IGNORE SPACE后
SELECT COUNT(*) FROM mytable;
SELECT COUNT (*) FROM mytable;
是合法的。
因此,如果这是一个例外,我可以得出结论,通常函数默认忽略空间。
如果函数默认忽略空间,那么如果上下文不明确,例如select表达式的第一项上的第一个函数,则它们与关键字无法区分,并且不能抛出错误,MySQL必须接受它们作为关键词。
尽管如此,我的结论仍然让他们有很多假设,我仍然会感激不尽,并接受任何指示,看看在哪里跟进。
答案 0 :(得分:4)
为了完整起见,我正在回答我自己的问题并链接到我自己的另一个question。 似乎这种行为是SQL标准的直接结果,允许函数和括号之间的空格。
由于(通常)允许说FUNCTION_NAME(x),然后将此功能应用于第一个选择
SELECT FUNCTION_NAME (x)
然后解析器将很难确定这是否是函数名称或SELECT修改关键字的上下文。
因此,在上述情况下,FUNCTION_NAME实际上是解析器的FUNCTION_NAME_OR_KEYWORD。
但它更进一步:因为函数名和括号IS之间的空格允许解析器实际上无法区分
SELECT FUNCTION_NAME_OR_KEYWORD (x)
和
SELECT FUNCTION_NAME_OR_KEYWORD(x)
(它必须测试关键字以查看它们是否是函数),并且由于(x)将被解析为x,因此对于FUNCTION_NAME_OR_KEYWORD - >
之间没有区别DISTINCT(以及所有其他SELECT修改关键字)SELECT DISTINCT x, y, z, ...
和
SELECT DISTINCT(x), y, z, ...
QED,但没有硬引用(假设standard不关心函数名和括号之间的空格,我相信是合理的,但我无法遵循BNF语法,我可以引用它确切的规则)。
注意:mysql有一定数量的函数,它关心函数和括号之间的空格,但我相信这些是异常(因此忽略它的服务器选项)
答案 1 :(得分:1)
有趣的场景。
如你所见,
SELECT DISTINCT(a), b, c
相当于:
SELECT DISTINCT (a), b, c
相当于:
SELECT DISTINCT a, b, c
即。括号被视为表达式分组括号。
有趣的是,VB6 / VBScript中出现了一个非常类似的问题,其中(对于Function(byref x))函数(x),函数x和调用函数(x)在它们通过引用传递的值方面都略有不同(函数( x)传递对(x)表达式结果的引用而不是x)。