Расширенные заполнители для 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
, разделенных запятыми ,
. В то время как :&
представляет собой список столбцов =:, к которому присоединяются AND
s. Для четности я добавил :|
. Однако:& имеет другие варианты использования вне команд ОБНОВЛЕНИЯ.
Но мой вопрос не в полезности, а в том, если:, и:& кажутся запоминающимися?
-> db(" SELECT * FROM all WHERE name IN (::) ", $assoc);
Через некоторое время, хотя я также добавил ::
для интерполяции :named,:value,:list
, очень похожий на ??
, расширяется до ?,?,?
. Аналогичные варианты использования, и разумно иметь для единообразия.
В любом случае, кто-нибудь еще реализовывал подобную схему? Разные заполнители? Или что бы вы порекомендовали для простоты? Обновление: Я знаю, что интерфейс PHP Oracle OCI также может привязывать параметры массива, но не использует для этого определенные заполнители. И я ищу сопоставимые синтаксисы заполнителей.
4 answers
Возможно, вы захотите избежать использования :=
в качестве заполнителя, потому что он уже используется , например, в MySQL.
Смотрите, например, этот ответ для использования в реальном мире.
Мне нравится основная идея, лежащая в основе вашего предложения, но мне не нравится "именование" заполнителей. У меня в основном есть два возражения:
- Ваши заполнители начинаются либо с
:
, либо с?
. Вы должны выбрать одну форму, чтобы заполнитель можно было сразу распознать. Я бы выбрал?
, потому что он имеет меньше возможных столкновений с 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, что плохо.
Очень аккуратно! Я думаю, что заполнители хороши, если вы хорошо их документируете и приводите множество примеров при их распространении. Это нормально, что вы изобрели свои собственные заполнители; в конце концов, кто-то должен был подумать об использовании ?
.
Если вы готовы потратить некоторое время на изучение доктрины, то вы могли бы делать удивительные вещи, такие как:
$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