Que tokens podem ser parametrizados em DOP preparado declarações?
-
06-07-2019 - |
Pergunta
Eu estou brincando com declarações preparadas em PHP / DOP. O básico fina consultas de trabalho, passando um valor para a cláusula WHERE:
$stmt = $db->prepare( 'SELECT title FROM episode WHERE id=:id' );
$stmt->bindParam( ':id', $id, PDO::PARAM_INT );
$id = 5;
$stmt->execute();
No entanto Eu tenho uma situação onde eu preciso passar variáveis ??para os nomes de campo. Esta consulta (com ligação apropriada) funciona bem:
SELECT :field FROM episode WHERE id=:id
Este dá um erro:
SELECT title FROM :field WHERE id=:id
Este não dá um erro, mas não retorna nenhuma linha:
SELECT title FROM episode WHERE :field=:id
Então, o que as coisas devem funcionar em declarações preparadas? Posso 'parametrizar os nomes de campo, nomes de tabelas e assim por diante?
Solução
Você não pode parametrizar nomes de tabela, nomes de coluna, ou qualquer coisa em uma cláusula IN
(graças a c0r0ner para apontando a restrição cláusula IN
).
Consulte esta questão , e posteriormente este comentário no PHP manual.
Outras dicas
@ Josh Leitzel
Esse pensamento é muito restritiva (e na minha opinião é apenas uma desculpa para estar com preguiça de implementar uma solução robusta), especialmente para estruturas de árvore dinâmicas expressas numa base de dados.
Considere o seguinte exemplo:
Meu projeto tem uma estrutura lógica:
A hierarquia da empresa é expresso em termos de entidades. Cada entidade pode tratados, no caso geral de ser um membro da hierarquia ou como um membro de um determinado nível de hierarquia. A hierarquia em si é definido em uma tabela como um único ramo de árvore da seguinte forma:
entity_structure (
id
name
parent_entity_structure_id
);
e as entidades em si são expressas como:
entities (
id
name
entity_structure_id
parent_id
);
Para facilidade de uso Eu construí um algoritmo que cria uma vista plana da árvore. O exemplo concreto a seguir ilustra o que quero dizer:
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
Isto resultaria na representação plana seguinte a ser produzida:
entity_tree (
entity_id
division_id
area_id
store_id
)
As entidades que estão no nível de divisão teria division_id, area_id e STORE_ID como NULL, Uma área area_id e STORE_ID como NULL, etc.
A coisa agradável sobre este é que permite consultar todos os filhos de uma divisão usando uma instrução semelhante à seguinte:
SELECT * FROM entity_tree WHERE division_id = :division_id;
No entanto, isto pressupõe que eu sei que o nível da estrutura da entidade estou consultando. Seria bom fazer:
SELECT * FROM entity_tree WHERE :structure = :entity_id;
Eu sei que não é difícil descobrir o nível de estrutura de uma única entidade, mas supor que eu estou looping através de um conjunto de entidades que podem não estar todos no mesmo nível. Como é agora eu tenho que criar uma consulta separada para cada nível da hierarquia, mas se eu pudesse parametrizar campos que eu poderia fazer o seguinte:
$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);
}
resultando em um código mais limpo e apenas uma declaração preparada.
Todo o exemplo não usa qualquer entrada do usuário.
Apenas algo a considerar.
Você não pode parametrizar qualquer coisa dentro cláusula IN
também.