У меня есть функция 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 не сработает.






Null - единственное значение, которое, как вы можете гарантировать, отсутствует в наборе. Почему это не вариант? Все остальное можно рассматривать как часть потенциального набора, все они являются ценностями.
Есть ли вероятность, что вы могли бы обнаружить пустые массивы с 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 (), когда ваш входной массив пуст, и он никогда не будет совпадать.
Ну, я только что попробовал, и это действительно работает. «IN (NULL)», я думал, будет делать то же самое, что и IS NULL, но они разные. Спасибо за ответ.