Почему mySQL может разрешить эти псевдонимы столбцов, когда обычно нельзя повторно использовать псевдоним?

большинство экспертов SQL сказали бы, что нельзя повторно использовать псевдоним в select на том же уровне; часто для работы с этим используется CTE; или один обертывает запрос как подзапрос, чтобы на псевдоним можно было ссылаться. Однако mySQL, похоже, допускает такую ситуацию при условии, что псевдоним ссылается в подзапрос внутри самого select; так что технически это не на том же уровне.

демо:

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;

SELECT 1 a, 2 b, (SELECT A+B) c
     , concat((SELECT a),(SELECT b)) d 
     , greatest((SELECT a),(SELECT b), (SELECT c))

оба вышеуказанных запроса работают.. да, они работа. (или сделать действительно хорошую работу, чтобы казалось, что они работают)

пока этого нет: как и следовало ожидать.

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

Итак, вопрос здесь в два раза:

  1. это "функция" mySQL, не имеющая документации или кто-то может объяснить, как компилятор может разрешить псевдонимы?

  2. это документированная функция, на которую можно положиться; если да, то где это документировано, чтобы можно было понять последствия использования этого метода?

этот вопрос вытекает из одного уже заданного:выберите столбец по псевдониму в MySQL

2 ответов


это похоже на ошибку разбора для меня (в других базах данных вы получите ошибку в первых двух запросах).

Я могу догадаться, что происходит. MySQL анализирует подзапрос (select c1). Он не находит c1 в подзапросе, поэтому он начинает искать ссылки во внешних запросах.

согласно правилам SQL, он должен смотреть только на столбцы в from предложения. Однако MySQL также, похоже, смотрит на столбец псевдонимы.

хотя я бы назвал это ошибкой, MySQL, похоже, считает это функцией. (Еще один пример MySQL, рассматривающий "ошибку" как "функцию".) Рассмотрим этот запрос:

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;

и ошибка, которую он генерирует:

ссылка " c1 " не поддерживается (прямая ссылка в списке элементов)

ошибка предполагает, что MySQL намеренно анализирует" обратные " ссылки.

для записи, я бы никогда не зависел от этого функциональность. Это не только нарушение стандарта ANSI и уникального поведения среди баз данных. Это сбивает с толку. Рассмотрим эту небольшую модификацию:

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;

, который c1 разрешает ли запрос? Я дам тебе это понять. И это даже не учитывает, что c1 может быть переменной.


  1. расследование привело меня к данное заявление: в качестве расширения MySQL также позволяет им группироваться и иметь. Однако,они недействительны в предложении WHERE и в других частях списка выбора. Дополнительные сведения см. В разделеhttp://dev.mysql.com/doc/refman/5.7/en/problems-with-alias.html. Однако в разделе конкретно не говорится о повторном использовании псевдонима в select и subquery. Ошибка, похоже, указывает на то, что это была функция в предыдущие версии (5.6.23), но не в 5.7.9..
  2. однако далее в приведенной выше ссылке внизу информация:

[9 Декабря 2015 15:35] Рой Lyseng В ...

я читал об Алиасных выражениях (что они не могут использоваться в предложении WHERE), но тогда возникает вопрос:

1. Почему он перестал работать? он перестал работать, потому что мы проверяли расширения MySQL на SQL норматив. И при рассмотрении некоторых сбоев из-за угловых случаев, в которых использовались ссылки на псевдонимные выражения, было решено, что это расширение плохо определено и может быть обработано другими средствами. Но ошибка сбоя использовала подзапрос в предложении WHERE, а не в списке выбора.

2. Почему был изменен стандартный SQL? (или его ранее не давали стандарту?) эта конструкция никогда не была частью стандартного SQL, это был MySQL расширение стандарта. Стандарт никогда не допускал ссылок на псевдонимы, кроме как в предложении ORDER BY.

3. Существует ли опция конфигурации, что запрос будет работать снова или как найти все такие запросы, которые не работают? мы пересмотрели, как справиться с этой проблемой, и попытаемся отменить решение о не поддержке псевдонимов в подзапросах в списке выбора. Таким образом, мы снова открываем ошибку.

здесь более длинный фон для первоначального решения:

вопреки ссылкам на псевдонимы в подзапросах в предложении WHERE (и в GROUP BY, если на то пошло), нет причин (кроме стандартного соответствия), по которым мы не должны допускать ссылки на псевдонимы в списке выбора, поскольку они должны быть доступны на той же стадии выполнения запроса. Но поддержка в 5.6 было весьма условным:

учитывая это: создайте таблицу t1(a int, b int),

псевдоним в списке выбора недопустим:

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

ошибка 1054 (42S22): неизвестный столбец " c " в "списке полей"

но в подзапросе ссылка на c действительна:

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

и подзапрос должен быть после определения псевдонима:

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

ошибка 1247 (42S22): ссылка " c " не поддерживается (прямая ссылка в списке элементов)

Итак, легко сказать, что поддержка для ссылки на псевдонимы в списке выбора был довольно ad-hoc. Тем не менее, мы попытаемся переопределить старое решение, но без попытки очистки очевидных отверстий в поддержке этой функции. Но ссылки на псевдонимы в подзапросах в предложении WHERE не будут переопределены.

выводы:

  • хотя это противоречит общему знанию ссылки на псевдоним в том же select, он делает появится mySQL позволит это. Насколько мне известно, это не обычное место в любой другой РСУБД. Необходимо учитывать порядок, в котором идентифицируется псевдоним (ответ Гордона адресует 3 места, которые нужно учитывать).
  • лично я бы отошел от этой функции, если не будет найдена дополнительная документация, объясняющая, как она работает или должна работать. Большинство разработчиков будут придерживаться использования CTE или подзапроса для обработки повторного использования псевдонима и из стойки обслуживания точка эта может быть более запутанным для других, чем стандартные подходы.
  • " Псевдонимные выражения "или" ссылки на псевдонимы в списке выбора", похоже, это называется. но я не могу найти больше в документации этой " функции "(непреднамеренное следствие?)