Связанный подзапрос MySQL в синтаксисе СОЕДИНЕНИЯ

Ссылки, которые я опубликовал в моих комментариях к вопросу, очень хорошо объясняют проблему. Я обобщил свои чувства по поводу того, почему проблема сохраняется, ниже:

  1. Те, кто только начинает, могут не знать о введении SQL.
  2. Некоторые из них знают о SQL-инъекции, но считайте, что побег - это (только?) решение. Если вы выполните быстрый поиск в Google php mysql query, первая страница появится на странице mysql_query , на которой есть пример, который отображает интерполяцию экранированного пользовательского ввода в запрос. Нет никакого упоминания (по крайней мере, не того, что я могу видеть) вместо использования подготовленных инструкций. Как говорили другие, существует так много учебных пособий, которые используют интерполяцию параметров, что не удивительно, как часто она все еще используется.
  3. Недостаточное понимание того, как работают параметризованные утверждения. Некоторые считают, что это просто фантастическое средство избежать ценностей.
  4. Другие знают о параметризованных утверждениях, но не используют их, потому что слышали, что они слишком медленны. Я подозреваю, что многие люди слышали, как невероятно медленные фразовые высказывания, но на самом деле не проводили никаких собственных испытаний. Как отметил Билл Карвин в своем выступлении, разница в производительности редко должна использоваться в качестве фактора при рассмотрении использования подготовленных заявлений. Преимущества готовятся один раз, выполняют многие , часто, как представляется, забываются, также как и улучшения безопасности и надежности кода.
  5. Некоторые используют параметризованные утверждения везде, но с интерполяцией непроверенных такие как имена таблиц и столбцов, ключевые слова и условные операторы. Динамические поиски, такие как те, которые позволяют пользователям указывать несколько разных полей поиска, условия сравнения и порядок сортировки, являются яркими примерами этого.
  6. Ложное чувство безопасности при использовании ORM. ORM все еще допускают интерполяцию частей инструкции SQL - см. [5].
  7. Программирование - большой и сложный вопрос, управление базами данных - большой и сложный вопрос, безопасность - большой и сложный вопрос. Разработка защищенного приложения базы данных непросто - даже опытные разработчики могут быть обнаружены.
  8. Многие ответы на stackoverflow не помогают. Когда люди пишут вопросы, которые используют динамический SQL и интерполяцию параметров, часто возникает нехватка ответов, которые предполагают использование параметризованных утверждений. В некоторых случаях у меня были люди, опровергающие мое предложение использовать подготовленные заявления - обычно из-за воспринимаемых неприемлемых служебных расходов. Я серьезно сомневаюсь, что те, кто задает большинство этих вопросов, находятся в положении, когда дополнительные несколько миллисекунд, принятые для подготовки параметризованного заявления, окажут катастрофическое влияние на их применение.

18
задан Bill Karwin 14 February 2009 в 20:32
поделиться

5 ответов

Ответ на Ваш вопрос не, это не возможно к ссылочным именам корреляции, как Вы делаете. Полученная таблица производится Вашим внутренним запросом, прежде чем внешний запрос начнет оценивать соединения. Таким образом, имена корреляции как t, tp, и u не доступны внутреннему запросу.

Для решения этого я рекомендовал бы использовать то же постоянное целочисленное значение во внутреннем запросе и затем присоединился бы к полученной таблице во внешнем запросе с помощью реального условия вместо 1=1.

SELECT t.ticketid, u.userid, t.fullname, u.loginapi_userid, t.email,
  tp.subject, tp.contents, a.PhoneNumber, a.Location, a.Extension,
  a.BusinessUnit, a.Department
FROM swtickets t
 INNER JOIN swticketposts tp ON (t.ticketid = tp.ticketid)
 INNER JOIN swusers u ON (t.userid = u.userid)
 LEFT OUTER JOIN (
  SELECT cfv.typeid,
    MIN(CASE cfv.customfieldid WHEN 1 THEN cfv.fieldvalue END) AS 'PhoneNumber',
    MIN(CASE cfv.customfieldid WHEN 3 THEN cfv.fieldvalue END) AS 'Location',
    MIN(CASE cfv.customfieldid WHEN 5 THEN cfv.fieldvalue END) AS 'Extension',
    MIN(CASE cfv.customfieldid WHEN 8 THEN cfv.fieldvalue END) AS 'BusinessUnit',
    MIN(CASE cfv.customfieldid WHEN 9 THEN cfv.fieldvalue END) AS 'Department'
  FROM swcustomfieldvalues cfv
  WHERE cfv.typeid = 2458
  GROUP BY cfv.typeid
  ) AS a ON (a.typeid = t.ticketid)
WHERE t.ticketid = 2458;
30
ответ дан 30 November 2019 в 07:44
поделиться

Вы используете дизайн Значения атрибута объекта, и нет в конечном счете никакого способа сделать это масштабируемым, при попытке генерировать стандартные наборы результатов. Не пытайтесь сделать это в одном запросе.

Вместо этого запросите свои нормализованные таблицы сначала:

SELECT t.ticketid, u.userid, t.fullname, u.loginapi_userid, t.email, 
  tp.subject, tp.contents
FROM swtickets t
 INNER JOIN swticketposts tp ON (t.ticketid = tp.ticketid)
 INNER JOIN swusers u ON (t.userid = u.userid)
WHERE t.ticketid = 2458;

Затем запрашивают Ваши пользовательские поля, с результатом на нескольких строках набора результатов:

SELECT cfv.customfieldid, cfv.fieldvalue
FROM swcustomfieldvalues cfv
WHERE cfv.typeid = 2458;

Вы получите несколько строк в наборе результатов, одну строку для каждого пользовательского поля:

+---------------+--------------+
| customfieldid | fieldvalue   |
+---------------+--------------+
|             1 | 415-555-1234 |
|             3 | Third office |
|             5 | 123          |
|             8 | Support      |
|             9 | Engineering  |
+---------------+--------------+

затем необходимо записать код приложения для отображения полей набора результатов на поля объекта приложения в цикле.

Используя таблицу Entity-Attribute-Value таким образом более масштабируемо и с точки зрения производительности и с точки зрения обслуживания кода.

2
ответ дан 30 November 2019 в 07:44
поделиться

Я записал бы это с несколькими соединениями. Когда Вы говорите, что это "возможно подверглось бы дополнительным издержкам", которые говорят мне, что Вы не протестировали его, чтобы быть уверенными. Если у Вас есть достойные индексы, соединения должны быть довольно тривиальными.

Это также показывает только, что одна из ловушек дженерика "содержит все" шаблон разработки таблицы.

1
ответ дан 30 November 2019 в 07:44
поделиться

Мое предложение было тем, что Вы исключили по причине эффективности. Например, не учитывая, где пункт и использование соединения (согласно t.ticketid = a.ticketid)

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

0
ответ дан 30 November 2019 в 07:44
поделиться

Я предполагаю, что проблема 'cfv.typeid = t.ticketid' затем? Мои взгляды об этом состояли бы в том, что, в то время как MySQL поддерживает связанные подзапросы, что Вы пытаетесь сделать, кажется, что он мог перестать работать в соединении, потому что 'внутренний' запрос не является действительно 'внутренней' остальной частью запроса как он, находится в операторе Where. Но похоже, что Вы могли просто взять, где пункт из подзапроса и делает Ваше условие объединения на a.typeid = t.ticketid.

0
ответ дан 30 November 2019 в 07:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: