"ВЫБРАТЬ * ИЗ пользователей, ГДЕ id IN ()" == FAIL

У меня есть функция sqlf (), которую я использую, она имитирует подготовленные операторы. Например, я могу делать такие вещи, как:

$sql = sqlf("SELECT * FROM Users WHERE name= :1 AND email= :2",'Big "John"','[email protected]') ;

По разным причинам я не могу использовать подготовленные операторы, но я хотел бы их подражать. Проблема, с которой я сталкиваюсь, связана с такими запросами, как

$sql = sqlf("SELECT * FROM Users WHERE id IN (:1)",array(1,2,3) );

Мой код работает, но не работает с пустыми массивами, например. следующее вызывает ошибку mysql:

SELECT * FROM Users WHERE id IN ();

У кого-нибудь есть предложения? Как мне преобразовать пустой массив в sql, который можно вставить в предложение IN? Замена NULL не сработает.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
4
0
5 346
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

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

Ну, я только что попробовал, и это действительно работает. «IN (NULL)», я думал, будет делать то же самое, что и IS NULL, но они разные. Спасибо за ответ.

jcampbell1 24.09.2008 04:02

Есть ли вероятность, что вы могли бы обнаружить пустые массивы с sqlf и изменить SQL, чтобы не было предложения IN?

В качестве альтернативы вы можете выполнить постобработку SQL перед передачей его «реальному» исполнителю SQL, чтобы удалить разделы «IN ()», хотя вам придется проделывать всевозможные уловки, чтобы увидеть, какие другие элементы нужно удалить, чтобы:

SELECT * FROM Users WHERE id IN ();
SELECT * FROM Users WHERE a = 7 AND id IN ();
SELECT * FROM Users WHERE id IN () OR a = 9;

станет:

SELECT * FROM Users;
SELECT * FROM Users WHERE a = 7;
SELECT * FROM Users WHERE a = 9;

Это может быть сложно в зависимости от сложности вашего SQL - вам в основном понадобится полноценный интерпретатор языка SQL.

Единственный способ, которым я могу это сделать, - это сканировать вашу функцию sqlf(), чтобы увидеть, идет ли конкретная замена вскоре после «IN (», а затем, если переданная переменная является пустым массивом, вставьте что-то, что вы точно знаете не будет в этой колонке: "m,znmzcb~~1", например.Это хакерство, но это сработает.

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

Если ваша функция, похожая на подготовку, просто заменяет: 1 эквивалентным аргументом, вы можете попробовать, чтобы ваш запрос содержал что-то вроде (': 1'), так что если: 1 пусто, он разрешается в (''), что не будет вызвать ошибку синтаксического анализа (однако это может вызвать нежелательное поведение, если это поле может иметь пустые значения - хотя, если это int, это не проблема). Однако это не очень чистое решение, и вам лучше определить, является ли массив пустым, и просто использовать альтернативную версию запроса, в которой отсутствует компонент «IN (: 1)». (Если это единственная логика в предложении WHERE, то, по-видимому, вы не хотите выбирать все, поэтому вы просто не выполняете запрос.)

Я бы сказал, что передача пустого массива в качестве аргумента для предложения IN () является ошибкой. Вы можете управлять синтаксисом запроса при вызове этой функции, поэтому вы также должны нести ответственность за входные данные. Предлагаю перед вызовом функции проверить пустоту аргумента.

Я бы использовал ноль, если бы ваш столбец «id» - это псевдоключ, которому автоматически присваиваются номера.

Насколько мне известно, автоматические генераторы ключей в большинстве типов баз данных начинаются с 1. Это соглашение, а не требование (поля с автоматической нумерацией не определены в стандартном SQL). Но это соглашение достаточно распространено, и вы, вероятно, можете на него положиться.

Поскольку ноль, вероятно, никогда не появляется в вашем столбце «id», вы можете использовать это значение в предикате IN (), когда ваш входной массив пуст, и он никогда не будет совпадать.

Другие вопросы по теме