为什么我的 PDO 语句 ->执行返回假?

发布于 2024-11-16 15:13:34 字数 2127 浏览 2 评论 0原文

经过近乎无休止的不同方面的测试后,我确定 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为空并且函数返回无效的。

我可能忽略了一些非常明显的事情,而且我已经做好了羞愧地低下头的准备。提前谢谢您...

更新

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

$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!你是我的最爱! :)

After near endless rounds of testing different aspects of this, I've determined that the PDO connection works (I can run a simple query and display results), I've determined that the statement is successfully preparing, and that the values are binding properly. For some reason, the statement won't execute. Just to be cute, I've tried removing all bound variables and executing a static query, and that won't work either.

Code:

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

Consistently echos debug text of 'prepared' 'table true' 'field true' 'value true' 'flag = false' which tells me that preparing and binding work, but executing doesn't, $result is empty and the function returns null.

I've probably overlooked something horrendously obvious, and I'm fully prepared to hang my head in utter n00b shame. Thank you in advance...

UPDATE

Ahh, concatenation -- my friend today. Working code follows:

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

This is safe in this instance, since $table and $field are system-generated and in no way accessible via user input; only $value is exposed.

Thank you StackOverflow! You're my favorite! :)

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

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

发布评论

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

评论(1

攒一口袋星星 2024-11-23 15:13:34

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

SELECT * FROM :table WHERE :field = :value

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

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

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

When you have a parameterized query that looks like this:

SELECT * FROM :table WHERE :field = :value

and you substitute values for :table, :field, and :value, you get something similar to the following (actually this is an oversimplication but illustrates the point):

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

because :table and :field get the same semantic treatment as :value, ie. they are treated as strings. You generally cannot parameterize table names and column names with parameterized queries. You'll have to rethink your approach a little. You might consider dynamically constructing your prepared statement string so that the table and column name parts of the query are simple concatenations, rather than binding them with PDO. But you must be very careful that you validate/sanitize the table and column names because PDO won't protect you from SQL injection at that level.

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