3

经过近乎无休止的不同方面的测试,我确定 PDO 连接有效(我可以运行一个简单的查询并显示结果),我确定该语句已成功准备,并且值已正确绑定. 由于某种原因,该语句不会执行。为了可爱起见,我尝试删除所有绑定变量并执行静态查询,但这也行不通。

代码:

$dbh = new PDO( "mysql:host=localhost;dbname=".$GLOBALS['data_name'], $GLOBALS['data_user'], $GLOBALS['data_pass'] );
$dbh->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

$sth = $dbh->prepare( "SELECT * FROM :table WHERE :field = :value" );
if( $sth != false ) TCDebug( 'prepared' );
if( $sth->bindValue( ":table", $table ) ) TCDebug( "table true" );
if( $sth->bindValue( ":field", $field ) ) TCDebug( "field true" );
if( $sth->bindValue( ":value", $value ) ) TCDebug( "value true" );
$flag = $sth->execute();

if( $flag === true ) {
    TCDebug( 'flag = true' );
} else if( $flag === false ) {
    TCDebug( 'flag = false' );
}
$result = $sth->fetchAll();

foreach( $result as $c ) TCDebugArr( $c );
TCDebug( count( $result ) );
if( count( $result ) > 0 ) {
    return $result;
} else {
    return null;
}

一致地回显'prepared''table true''field true''value true''flag = false'的调试文本,它告诉我准备和绑定工作,但执行没有,$result为空并且函数返回null。

我可能忽略了一些非常明显的事情,我完全准备好低下头来完全感到羞耻。先感谢您...

更新

啊,串联——我今天的朋友。工作代码如下:

$dbh = new PDO( "mysql:host=localhost;dbname=".$GLOBALS['data_name'], $GLOBALS['data_user'], $GLOBALS['data_pass'] );
$dbh->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

$prepare_str = "SELECT * FROM ". $table ." WHERE ". $field ." = :value";

$sth = $dbh->prepare( $prepare_str );
if( $sth != false ) TCDebug( 'prepared' );
if( $sth->bindValue( ":value", $value ) ) TCDebug( "value true" );
$flag = $sth->execute();

if( $flag === true ) {
    TCDebug( 'flag = true' );
} else if( $flag === false ) {
    TCDebug( 'flag = false' );
}
$result = $sth->fetchAll();

foreach( $result as $c ) TCDebugArr( $c );
TCDebug( count( $result ) );
if( count( $result ) > 0 ) {
    return $result;
} else {
    return null;
}

在这种情况下这是安全的,因为$table$field是系统生成的,并且无法通过用户输入访问;只有 $value 被暴露。

谢谢 StackOverflow!你是我的最爱!:)

4

1 回答 1

8

当您有一个如下所示的参数化查询时:

SELECT * FROM :table WHERE :field = :value

并且您将值替换为:table:field:value,您会得到类似于以下内容(实际上这是一个过于简单化但说明了这一点):

SELECT * FROM 'sometable' WHERE 'somefield' = 'somevalue'

因为:table:field得到与 相同的语义处理:value,即。它们被视为字符串。您通常不能使用参数化查询来参数化表名和列名。您将不得不重新考虑您的方法。您可能会考虑动态构造您准备好的语句字符串,以便查询的表和列名部分是简单的连接,而不是使用 PDO 绑定它们。但是您必须非常小心地验证/清理表和列名,因为 PDO 不会保护您免受该级别的 SQL 注入。

于 2011-06-21T04:00:31.447 回答