Why is mySQL able to resolve these column aliases when normally one can't reuse an alias?

青春壹個敷衍的年華 提交于 2019-12-05 05:22:13

This looks like a parsing bug to me (in other databases, you would get an error on the first two queries).

I can guess at what is happening. MySQL is parsing the subquery (select c1). It doesn't find c1 in the subquery, so it starts looking for references in outer queries.

According to the rules of SQL, it should only be looking at columns in the from clause. However, MySQL also seems to be looking at column aliases.

Although I would call this a bug, MySQL seems to consider it a feature. (Yet another example of MySQL considering a "bug" a "feature".) Consider this query:

SELECT CONCAT((SELECT c1), 2), CONCAT(a, b) AS c1
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL 
      SELECT '1', '2', '3') t1;

And the error it generates:

Reference 'c1' not supported (forward reference in item list)

The error suggests that MySQL is intentionally parsing "backwards" references.

For the record, I would never depend on this functionality. It is not only a violation of the ANSI standard and unique behavior among databases. It is confusing. Consider this little modification:

SELECT CONCAT(a, b) AS c1, CONCAT((SELECT c1), 2)
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL 
      SELECT '1', '2', '3') t1 CROSS JOIN
     (SELECT 'abcdef' as c1) x;

Which c1 does the query resolve to? I'll let you figure that out. And this doesn't even take into account that c1 could be a variable.

  1. Investigation has lead me to this statement: As an extension MySQL also allows them in GROUP BY and HAVING. However, they are invalid in the WHERE clause and in other parts of the SELECT list. For more information see http://dev.mysql.com/doc/refman/5.7/en/problems-with-alias.html. However the section doesn't specifically talk about reuse of alias in select and subquery. The bug does seem to indicate this was a feature in prior versions (5.6.23) but not in 5.7.9..
  2. However further in the above link the below information is provided:

[9 Dec 2015 15:35] Roy Lyseng ...

I read about Aliased expressions (that they can't be used in WHERE clause), but then the question arises:

1. Why is it stopped working? It stopped working because we were screening the MySQL extensions to the SQL standard. And when examining some crashing bugs due to corner cases that were using references to aliased expressions, it was decided that this extension was poorly defined and could be handled by other means. But the crashing bug was using a subquery in the WHERE clause, not in the SELECT list.

2. Why standard SQL was changed? (or it did not previously been given to the standard?) This construction has never been part of standard SQL, it was a MySQL extension to the standard. The standard has never allowed references to aliases, except within the ORDER BY clause.

3. Does exists an option of the configuration that query will working again OR how to find all such requests that doesn't working? We have reconsidered how to handle this problem, and will try to revert the decision on not supporting aliases in subqueries in SELECT list. Thus, we are reopening the bug.

Here is a longer background for the original decision:

Contrary to references to aliases in subqueries in the WHERE clause (and in GROUP BY, for that matter), there is no reason (except standard compliance) that we should not allow references to aliases in the SELECT list, since they should be available in the same phase of query execution. But the support in 5.6 was quite arbitrary:

Given this: create table t1(a int, b int),

Alias in SELECT list is not valid:

  select a+b as c,c+1 from t1;

ERROR 1054 (42S22): Unknown column 'c' in 'field list'

But within a subquery, reference to c is valid:

  select a+b as c,(select c+1) from t1;

And subquery must be after definition of alias:

  select (select c+1),a+b as c from t1;

ERROR 1247 (42S22): Reference 'c' not supported (forward reference in item list)

So, it is easy to say that support for references to aliases in SELECT list was rather ad-hoc. Nevertheless, we will try to reimplement the old solution, but with no attempt at cleaning up the obvious holes in the support for this feature. But referencing aliases in subqueries in the WHERE clause will not be reimplemented.

Conclusions:

  • While it is contrary to common knowledge of referencing an alias in the same select, it does appear mySQL will allow this. It is not common place in any other RDBMS to my knowledge. One needs to consider the order in which the alias is identified (Gordon's answer addresses 3 places one needs to considers).
  • Personally I would gravitate away from this functionality unless additional documentation can be found explaining how it works or is to work. Most developers would stick with the use of a CTE or a subquery to handle the alias reuse and from a maintenance stand point this may be more confusing to others than the standard approaches.
  • "Aliased Expressions" or "references to aliases in the SELECT list" seems to be what this is called. but I can't find much more in documentation of this "feature" (unintended consequence?)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!