Какие маркеры можно параметризовать в подготовленных отчетах PDO?

Я играю с подготовленными заявлениями в 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 .