Я создаю плагин WP, который будет хранить настройки в настраиваемой таблице и извлекать их на основе идентификатора страницы или идентификатора категории, и если это находится в пределах временного интервала. Бит выбора даты работает нормально; проблема не исчезнет, когда часть оператора, содержащая выбор даты, будет удалена.
Проблема в том, что каждый оператор выберите ... или работает с сам по себе, но когда я соединяю их с помощью скобок и селектора ИЛИ, он извлекает только категорию. Это идентичный код, который я использую, с удалением даты (которая работает) для ясности:
$sql = "SELECT * FROM {$tablename}
WHERE (
( start_id = {$postid} OR ( start_id < {$postid} AND stop_id >= {$postid} ) AND scope = 'post' )
OR ( start_id = {$categoryid} OR ( start_id < {$categoryid} AND stop_id >= {$categoryid} ) AND scope = 'category' )
)
AND ( ...date selector... )";
Когда я использую этот код, он извлекает только запись категории, даже если есть запись сообщения, соответствующая критериям (которую она должна захватить первой). Если я удалю селектор категорий, он просто вытянет запись сообщения. Нет интерференции между start / stop_ID из разных строк; это уже проверил.
Базовая структура таблицы такова ... обратите внимание, что некоторые поля являются пустыми, потому что пользователь сможет указать либо диапазон, либо одну страницу или идентификатор категории.
ID start_id stop_id scope storedsettings
1 40 45 post ...
2 50 NULL category ...
3 67 70 category ...
4 71 NULL post ...
Большое спасибо за понимание этой проблемы!
ИЗМЕНИТЬ, чтобы ответить на некоторые комментарии: (1) @JESUS: вставка очень специфична и не допускает дублирования на основе идентификатора, поэтому всегда вытягивает одну строку; (2) @IVANIVAN: Что вы имеете в виду под приоритетом операторов? ИЛИ факторизуется перед И, поэтому я группирую И, а затем использую это как другую сторону ИЛИ. Или я неправильно понимаю твой ответ? Спасибо!
@RiggsFolly Спасибо за внимание, но я правильно справляюсь с этим внутри Wordpress. Это очень урезанный код, поэтому вы можете понять мою проблему.
@RalphTheWonderLlama Интересно. Ваш вопрос кажется правильным. Только для целей тестирования: что произойдет, если вы удалите часть (... селектор даты ...)?
@EvE Никакой разницы. Это меня совершенно сбило с толку.
У вас есть подвыражения формы (x OR (y1 AND y2) AND z) или (x OR y AND z). Вы уверены, что вам не нужно более четко указывать на порядок оценки? Думаю, это должен быть ((x OR y) AND z), он же ((x OR (y1 AND y2)) AND z)
Далее следует комментарий @Uueerdo - когда я делаю такой сложный выбор, я всегда заключаю в круглые скобки и использую их в достаточном количестве и в нужных местах, чтобы сделать все абсолютно конкретным.
Какие критерии вы используете, когда он может вывести более 1 записи, но показывает только 1?
@ivanivan и [at] Jesus Я отредактировал вопрос, чтобы ответить на ваши комментарии. Спасибо!
По внешнему виду параметризованные операторы @RiggsFolly здесь не работают - вы не можете параметризовать имя таблицы. Возможно, оператор OP может безопасно построить параметризованный оператор, используя только имя таблицы в качестве переменной, но им все равно нужны приличные проверки, чтобы предотвратить атаку SQLi.
Чтобы добавить к себе и @ivanivan, я всегда явно указываю порядок оценки с помощью скобок всякий раз, когда смешиваю И и ИЛИ, потому что: (1) честно говоря, мне не нужно помнить их приоритет, и (2) мне нужен «следующий парень» (чаще всего через год или около того), чтобы узнать порядок, который я намеревался.
@Uueerdo мудрые слова. окажет ли такой дополнительный факторинг в операторе select заметное влияние на скорость? Думаю, что нет, но стараюсь сделать это как можно более аккуратным.
@RalphTheWonderLlama AND оценивается до OR. x OR (y1 AND y2) AND z === x OR (y1 AND y2 AND z), но вы, вероятно, захотите (x OR y1 AND y2) AND z
@RalphTheWonderLlama OR обычно вредит больше, чем любые скобки, и производительность в таких ситуациях является второстепенной; поскольку без скобок это даже неправильное условие.






Ваш сценарий широко открыт для Атака с использованием SQL-инъекции Даже если вы избегаете ввода, это небезопасно! Используйте подготовленные параметризованные операторы в API
MYSQLI_илиPDO