哪些标记可以在 PDO 准备好的语句中参数化?

发布于 2024-08-08 10:38:17 字数 570 浏览 3 评论 0原文

我正在使用 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

那么,在准备好的语句中应该做什么?我可以“参数化”字段名称、表名称等吗?

I'm playing around with prepared statements in PHP/PDO. The basic queries work fine, passing a value to the WHERE clause:

$stmt = $db->prepare( 'SELECT title FROM episode WHERE id=:id' );
$stmt->bindParam( ':id', $id, PDO::PARAM_INT );
$id = 5;
$stmt->execute();

However I have a situation where I need to pass variables for the field names. This query (with appropriate binding) works fine:

SELECT :field FROM episode WHERE id=:id

This one gives an error:

SELECT title FROM :field WHERE id=:id

This one doesn't give an error, but returns no rows:

SELECT title FROM episode WHERE :field=:id

So, what things should work in prepared statements? Can I 'parameterize' field names, table names and so on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

靖瑶 2024-08-15 10:38:17

您无法参数化表名、列名或 IN 子句中的任何内容(感谢 c0r0ner 的 指出 IN 子句限制)。

请参阅此问题,然后PHP 手册中的此注释

You cannot parameterize table names, column names, or anything in an IN clause (thanks to c0r0ner for pointing out the IN clause restriction).

See this question, and subsequently this comment in the PHP manual.

殤城〤 2024-08-15 10:38:17

@ Josh Leitzel

这种想法非常具有限制性(在我看来,这只是懒于实现强大解决方案的借口),特别是对于数据库中表达的动态树结构。

考虑以下示例:

我的项目具有逻辑结构:

公司层次结构以实体的形式表示。每个实体可以在一般情况下被视为层次结构的成员或层次结构的特定级别的成员。层次结构本身在表中定义为单个树分支,如下所示:

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
)

处于部门级别的实体将 Division_id、area_id 和 store_id 设为 NULL,区域 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);
}

生成更清晰的代码并且只有一个准备好的语句。

整个示例不使用任何用户输入。

只是需要考虑的事情。

@ Josh Leitzel

That thinking is very restrictive (and is in my opinion just an excuse for being too lazy to implement a robust solution), especially for dynamic tree structures expressed in a database.

Consider the following example:

My project has a logical structure:

A company hierarchy is expressed in terms of entities. Each entity can treated in the general case of being a member of the hierarchy or as a member of a specific level of the hierarchy. The hierarchy itself is defined in a table as a single tree branch as follows:

entity_structure (
   id
   name
   parent_entity_structure_id
);

and the entities themselves are expressed as:

entities (
   id
   name
   entity_structure_id
   parent_id
);

For ease of use I've built an algorithm that creates a flat view of the tree. The following concrete example illustrates what I mean:

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

This would result in the following flat representation being produced:

entity_tree (
   entity_id
   division_id
   area_id
   store_id
)

Entities that are at the division level would have division_id, area_id and store_id as NULL, An area area_id and store_id as NULL, etc.

The nice thing about this is it lets you query all the children of a division using a statement similar to the follow:

SELECT * FROM entity_tree WHERE division_id = :division_id;

However this assumes that I know the structure level of the entity I'm querying. It would be nice to do:

SELECT * FROM entity_tree WHERE :structure = :entity_id;

I know it's not hard to figure out the structure level of a single entity, but assume I'm looping through a collection of entities that may not all be at the same level. As it is now I have to build a separate query for each level of the hierarchy, but if I could parameterize fields I could do the following:

$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);
}

resulting in cleaner code and only one prepared statement.

The entire example uses no user input whatsoever.

Just something to consider.

他夏了夏天 2024-08-15 10:38:17

您也不能参数化 IN 子句中的任何内容。

You can't parameterize anything within IN clause as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文