为什么我的PDO声明 - >执行return false?

时间:2011-06-21 03:57:11

标签: php pdo execute prepare

经过无数次测试不同方面的这个,我已经确定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''调试文本字段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!你是我的最爱! :)

1 个答案:

答案 0 :(得分:8)

如果您的参数化查询如下所示:

SELECT * FROM :table WHERE :field = :value

并且您替换了:table:field:value的值,您得到的内容类似于(实际上这是一个过度复制但是说明了点):

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

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