"ВЫБЕРИТЕ * ОТ ПОЛЬЗОВАТЕЛЕЙ, ГДЕ ИД В ()" == СБОЙ - PullRequest
4 голосов
/ 24 сентября 2008

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

$sql = sqlf("SELECT * FROM Users WHERE name= :1 AND email= :2",'Big "John"','bj@example.com') ;

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

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

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

SELECT * FROM Users WHERE id IN ();

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

Ответы [ 6 ]

7 голосов
/ 24 сентября 2008

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

1 голос
/ 24 сентября 2008

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

0 голосов
/ 24 сентября 2008

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

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

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

0 голосов
/ 24 сентября 2008

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

0 голосов
/ 24 сентября 2008

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

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

0 голосов
/ 24 сентября 2008

Есть ли вероятность, что вы можете обнаружить пустые массивы с помощью 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...