Расширенные заполнители для SQL, например, ГДЕ идентификатор В (??)


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


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

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

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

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

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

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

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

Здесь мнемонический :, расширяется в список пар name=:name, разделенных запятыми ,. В то время как :& представляет собой список столбцов =:, к которому присоединяются ANDs. Для четности я добавил :|. Однако:& имеет другие варианты использования вне команд ОБНОВЛЕНИЯ.
Но мой вопрос не в полезности, а в том, если:, и:& кажутся запоминающимися?

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

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

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

 10
Author: mario, 2010-09-12

4 answers

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

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

 3
Author: Mark Byers, 2017-05-23 10:30:25

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

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

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

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

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

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

?x заполнитель: Каждый элемент массива преобразуется в структуру `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'

Некоторые мысли, которые у меня были при разработке этого версия класса БД:

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

 4
Author: NikiC, 2010-09-27 16:00:58

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

 2
Author: Chris Laplante, 2010-09-12 19:53:51

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

$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 (?, 
?, 
?, 
?)

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

 2
Author: ITroubs, 2010-10-01 11:51:51