我有查询,它可以
select *, id, from_unixtime(start_timestamp) from log limit 1;
这也很好:
select * from log limit 1;
如果将*
移动到末尾,为什么会出现错误?
select id, from_unixtime(start_timestamp), * from log limit 1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '* from log limit 1' at line 1
原因是他们在SQL解析器中实现了一条捷径。
SQL-2003规范显示SELECT的语法规则如下:
<query specification> ::=
SELECT [ <set quantifier> ] <select list> <table expression>
<select list> ::=
<asterisk>
| <select sublist> [ { <comma> <select sublist> }... ]
<select sublist> ::=
<derived column>
| <qualified asterisk>
这表明SELECT *
与逗号分隔列或限定星号的列表互斥。如果使用不合格的*
,那么这必须是整个选择列表。为了实现这种语法,它们需要<select list>
规则和<select sublist>
规则。
但是MySQL的SQL解析器Yacc文件显示:
query_specification:
SELECT_SYM
select_options
select_item_list
...
select_item_list:
select_item_list ',' select_item
| select_item
| '*'
他们基本上将<select list>
和<select sublist>
的规则合并为一个递归规则。因此,他们对select_item_list
的规则允许SELECT *, <select_item>, <select_item>, ...
,而根据SQL-2003标准,它不应该允许。
由于他们语法中的这个捷径,他们不允许*
通配符作为select_item_list
中的尾随项。
如果MySQL要";"修复";现在这个问题,要使它符合标准语法规则,无疑将打破成千上万依赖非标准语法的遗留应用程序。
您可以通过避免SELECT *, ...
语法来使代码符合标准语法。仅使用SELECT * FROM ...
。您也可以合法地使用限定星号,如SELECT t1.*, ...
。