Расширенные заполнители для SQL, например WHERE id IN (??)

Обновление Bounty : Уже получил очень хороший ответ от Марка. Адаптировано: = в:, ниже. Тем не менее, я все еще ищу аналогичные схемы, кроме DBIx. Я просто заинтересован в том, чтобы быть совместимым ни с чем .


Мне нужно сообщить о синтаксисе, который я выбрал для «расширенных» заполнителей в параметризованных операциях SQL. Поскольку создание некоторых конструкций (предложения IN) вызывало меня, я решил использовать несколько ярлыков синтаксиса, которые автоматически расширяются до обычных? заполнители.
Они мне нравятся. Но я хочу упаковать его для распространения, и я спрашиваю себя, понятны ли они.

В основном мои новые заполнители ?? и :? (перечислены параметры) и :& and :, и :| и :: (для именных заполнителей) со следующими вариантами использования:

 -> db(" SELECT * FROM all WHERE id IN (??) ", [$a, $b, $c, $d, $e]) 

The ?? расширяется в ?,?,?,?,?,... зависимости от числа $ args к моей функции db (). Это довольно ясно, и его синтаксис уже является стандартизированным. Perls DBIx :: Simple также использует его. Поэтому я вполне уверен, что это приемлемая идея.

 -> db(" SELECT :? FROM any WHERE id>0 ", ["title", "frog", "id"]); // Note: not actually parameterized attr, needs cleanup regex 

Признай это. Мне просто понравился смайлик. В основном это :? placeholder расширяет ассоциативные $ args в имена простых столбцов. Фактически это исключает любые значения $ args. Это действительно полезно для INSERT в сочетании с ??, а иногда и для предложений IN. Но здесь я уже задаюсь вопросом, является ли этот новый синтаксис разумным, или не просто неправильным, потому что он смешивает: и? персонажи. Но почему-то это, похоже, хорошо соответствует синтаксической схеме.

 -> db(" UPDATE some SET :, WHERE :& AND (:|) ", $row, $keys, $or); 

Здесь мнемоника :, расширяется в список name=:name пары name=:name разделенных запятыми. В то время как :& – столбец =: список столбцов, соединенный с AND s. Для паритета я добавил :| , Однако: & имеет другие варианты использования команд UPDATE.
Но мой вопрос заключается не в пользе, а в том, что:, и: & кажется, что они запоминаются?

  -> db(" SELECT * FROM all WHERE name IN (::) ", $assoc); 

После некоторых, хотя я также добавил :: для интерполяции a :named,:value,:list очень нравится ?? расширяется до ?,?,? , Подобные варианты использования и разумные для однородности.

Так или иначе, кто-нибудь еще реализовал такую ​​схему? Разные заполнители? Или что бы вы порекомендовали для простоты? Обновление. Я знаю, что интерфейс Oracle OCI PHP также может связывать параметры массива, но не использует для этого специальные заполнители. И я ищу сопоставимые синтаксисы заполнителей.

Возможно, вы захотите избежать использования := в качестве заполнителя, поскольку он уже использует, например, MySQL.

См. Например, этот ответ для использования в реальном мире.

Мне нравится основная идея вашего предложения, но не нравится «именование» заполнителей. У меня в основном есть два возражения:

  • Ваши заполнители начинаются либо с : или с ? , Вы должны выбрать одну форму, поэтому местозаполнитель может быть немедленно распознан. Я бы выбрал ? потому что он имеет меньше возможных столкновений с SQL и более распространен для обозначения заполнителей.
  • Заполнители трудно понять и трудно запомнить. :& and :| кажутся правдоподобными для меня, но различение ?? , :? и : довольно сложно.

Я изменил свой класс DB для поддержки еще нескольких заполнителей и стал более интеллектуальным: DB_intelligent.php (часть README о заполнителях не относится к этому классу. Это только для нормального класса.)

Класс DB имеет два типа заполнителей: многофункциональный ? placeholder и заполнитель ассоциативного массива ?x ( x может быть & или | ).

? placeholder : этот placeholder определяет тип вставки из типа аргумента:

 null => 'NULL' 'string' => 'string' array('foo', 'bar') => ('foo','bar') 

?x placeholder : каждый элемент массива преобразуется в структуру `field`='value' и вставляется в разделитель. Разделитель задается компонентом x :, делится запятой, & помощью AND и | по OR .

Пример кода:

 DB::x( 'UPDATE table SET ?, WHERE value IN ? AND ?&', array('foo' => 'bar'), array('foo', 'bar'), array('hallo' => 'world', 'hi' => 'back') ); // Results in this query: // UPDATE table SET `foo`='bar' WHERE value IN ('foo','bar') AND `hallo`='world' AND `hi`='back' 

Некоторые мысли, которые я имел при разработке этой версии класса DB:

Очевидная мысль, которая может возникнуть: почему бы не использовать ? для всех типов данных, даже ассоциативных массивов. Добавляйте только ?& И ?| дополнительно. Использование ? на ассоциативном массиве будет таким же, как и использование ?, в текущем проекте. Причина, по которой я этого не делал, – это безопасность. Вы часто хотите вставить данные из <select multiple> в запрос ( IN ? ). Но поскольку HTML позволяет массиву ( form[array] ) формировать элементы управления, также может быть представлен ассоциативный массив с тем же именем. Таким образом, мой Query Compositor распознает его как список значений field =>. Хотя это, вероятно, не повредит безопасности, это приведет к ошибке SQL, которая будет плохой.

Очень аккуратный! Я думаю, что заполнители хороши, пока вы хорошо их документируете и предоставляете множество примеров, когда вы его распространяете. Это нормально, что вы изобрели свои собственные заполнители; кто-то должен был подумать об использовании ? , в конце концов.

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

 $q = Doctrine_Query::create() ->select('u.id') ->from('User u') ->whereIn('u.id', array(1, 3, 4, 5)); echo $q->getSqlQuery(); 

что бы вызвало такой запрос:

 SELECT u.id AS u__id FROM user u WHERE u.id IN (?, ?, ?, ?) 

Этот пример был взят из: документации доктрины dql