Я играю с подготовленными заявлениями в PHP / PDO. Основные запросы работают нормально, передавая значение в предложение WHERE:
$stmt = $db->prepare( 'SELECT title FROM episode WHERE id=:id' ); $stmt->bindParam( ':id', $id, PDO::PARAM_INT ); $id = 5; $stmt->execute();
Однако у меня есть ситуация, когда мне нужно передать переменные для имен полей. Этот запрос (с соответствующим привязкой) отлично работает:
SELECT :field FROM episode WHERE id=:id
Это дает ошибку:
SELECT title FROM :field WHERE id=:id
Это не дает ошибки, но не возвращает строк:
SELECT title FROM episode WHERE :field=:id
Итак, что должно работать в подготовленных заявлениях? Могу ли я «параметризовать» имена полей, имена таблиц и т. Д.?
Вы не можете параметризовать имена таблиц, имена столбцов или что-либо в предложении IN
(благодаря c0r0ner для указания ограничения предложения IN
).
См. Этот вопрос , а затем этот комментарий в руководстве PHP .
@ Джош Лейтцель
Это мышление очень ограничительно (и, на мой взгляд, просто предлог для ленивости для внедрения надежного решения), особенно для динамических древовидных структур, выраженных в базе данных.
Рассмотрим следующий пример:
Мой проект имеет логическую структуру:
Иерархия компаний выражается в единицах. Каждый объект может рассматриваться в общем случае как член иерархии или как член определенного уровня иерархии. Сама иерархия определяется в таблице как отдельная ветвь дерева следующим образом:
entity_structure ( id name parent_entity_structure_id );
и сами сущности выражаются как:
entities ( id name entity_structure_id parent_id );
Для удобства использования я построил алгоритм, который создает плоский вид дерева. Следующий конкретный пример иллюстрирует, что я имею в виду:
SELECT * FROM entity_structure; id | name | entity_structure_parent_id ----------------------------------------------------------- 1 | Company | null (special one that always exists) 2 | Division | 1 3 | Area | 2 4 | Store | 3
Это приведет к получению следующего плоского представления:
entity_tree ( entity_id division_id area_id store_id )
Объекты, находящиеся на уровне деления, будут иметь значения split_id, area_id и store_id как NULL, Area area_id и store_id как NULL и т. Д.
Самое приятное в этом – это позволяет вам запрашивать все дочерние элементы подразделения, используя оператор, аналогичный следующему:
SELECT * FROM entity_tree WHERE division_id = :division_id;
Однако это предполагает, что я знаю уровень структуры объекта, который я запрашиваю. Было бы неплохо сделать следующее:
SELECT * FROM entity_tree WHERE :structure = :entity_id;
Я знаю, что нетрудно понять уровень структуры одного объекта, но предположим, что я перебираю набор объектов, которые могут быть не все на одном уровне. Поскольку сейчас я должен создать отдельный запрос для каждого уровня иерархии, но если бы я мог параметризовать поля, я мог бы сделать следующее:
$children = array(); $stmt = $pdo->prepare('SELECT entity_id FROM entity_tree WHERE :structure = :entityId'); foreach ($entities AS $entity) { $stmt->execute(array( ':structure' = $entity->getEntityStructureId(), ':entityId' = $entity->getId() )); $children[$entity->getId()] = $stmt->fetchAll(PDO::FETCH_COLUMN); }
в результате получается более чистый код и только один подготовленный отчет.
Весь пример не использует никакого ввода пользователя.
Просто подумать.
Вы не можете параметризовать что-либо внутри предложения IN
.