PHP:PDOStatement 简单 MySQL Select 不起作用

发布于 2024-08-25 23:32:20 字数 1138 浏览 4 评论 0原文

我有以下 PHP 代码,对表进行了非常简单的选择。

$statement = $db->prepare("SELECT * FROM account WHERE fbid = :fbid");
$statement->bindParam(":fbid",$uid, PDO::PARAM_STR,45);
$out = $statement->execute();
print_r($out) // 1;
//$out = $statement->execute(array(':fbid' => $uid)); // also doesn't work
$row = $statement->fetch();

$out 为 true(成功),但 $row 为 null。

编辑:

$statement->debugDumpParams();

输出

SQL: [40] SELECT * FROM account WHERE fbid = :fbid Params: 1 Key: Name: [5] :fbid paramno= -1 name=[5] ":fbid" is_param=1 param_type=2

如果我修改代码如下:

$statement = $db->prepare("SELECT * FROM account WHERE fbid = $uid");
$out = $statement->execute();
$row = $statement->fetch();

$row 包含我期望的记录。

我不知所措。我正在使用 PDO::prepare()、bindParams() 等来防止 SQL 注入(也许我错了)。

编辑: 在我的示例中,$uid 是一个数字字符串(即仅包含数字的字符串)。在数据库中,列类型为 VARCHAR(45)

编辑:

如果我将数据库类型从 VARCHAR(45) 更改为 BIGINT,则两个查询都可以工作。如果我再次将数据库类型中的类型更改回 VARCHAR(45),它就可以工作。那么什么给出呢?

请停下来。

I have the following PHP code doing a very simple select into a table.

$statement = $db->prepare("SELECT * FROM account WHERE fbid = :fbid");
$statement->bindParam(":fbid",$uid, PDO::PARAM_STR,45);
$out = $statement->execute();
print_r($out) // 1;
//$out = $statement->execute(array(':fbid' => $uid)); // also doesn't work
$row = $statement->fetch();

$out is true (success) yet $row is null.

EDIT:

$statement->debugDumpParams();

Outputs

SQL: [40] SELECT * FROM account WHERE fbid = :fbid Params: 1 Key: Name: [5] :fbid paramno=-1 name=[5] ":fbid" is_param=1 param_type=2

If I modify the code as follows:

$statement = $db->prepare("SELECT * FROM account WHERE fbid = $uid");
$out = $statement->execute();
$row = $statement->fetch();

$row contains the record I'm expecting.

I'm at a loss. I'm using the PDO::prepare(), bindParams() etc to protect against SQL Injection (maybe I'm mistaken on that).

EDIT:
In my example, $uid is a numerical string (ie a string containing only numbers). In the database, the column type is VARCHAR(45)

EDIT:

If I change the database type from VARCHAR(45) to BIGINT, both queries work. If I change the type in the database type back to VARCHAR(45) again, it works. So what gives?

Please halp.

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

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

发布评论

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

评论(5

快乐很简单 2024-09-01 23:32:21

您需要检查您的 fbid 值。如果它的整数值大于 2^32(无符号),它应该始终是字符串,简单地通过 (string)$uid 进行转换是行不通的,并且 sprintf("%.0f",...) 仅在整数值时才有效小于 2^52,因为在 32 位操作系统上,当数字大于 2^31(32 无符号)时,PHP 将假定它是 double 类型,并且默认精确值仅为十进制 14,但 fbid 为 20。

您必须将 fbid 保留在string在PHP中只包含[0-9],不管它在MySQL中存储为BIGINT还是VARCHAR,MySQL只接受字符串sql语句,并且总是以字符串格式返回结果。

$mi = new mysqli("localhost", "root", "xxx", "test");
$uid = "12379739851403943597";   // Works
//$uid = 12379739851403943597;   // never Works
//$uid = (string) 12379739851403943597;   // get "1.2379739851404E+19" wrong string !
//$suid = sprintf("%.0f", $uid);          // get "12379739851403943936" lost precise

$stmt = $mi->prepare("select * from bitest where id = ?");
$stmt->bind_param('s', $uid);

$stmt->execute();
$stmt->bind_result($id, $name);

$stmt->store_result();
print "numrow: " . $stmt->num_rows . " - \n";
$stmt->fetch();
print "$id - $name \n";
$stmt->free_result();

$stmt->close();


$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'xxx');
$sql = "select * from bitest where id = ?";

$sth = $pdo->prepare($sql);
$sth->bindParam(1, $uid, PDO::PARAM_STR);

$sth->execute();
var_dump($sth->fetchAll(PDO::FETCH_ASSOC));

You need to check your fbid value. it should be always string if its integer value is greater than 2^32 (unsigned), simply cast by (string)$uid is not work, and sprintf("%.0f",...) will only works when integer value less than 2^52, because on 32-bit OS when a number is greater than 2^31(32 unsigned) PHP will assume it is double type and default precise is only 14 decimal but fbid is 20.

You have to keep fbid in string contains only [0-9] in PHP, doesn't matter it is stored as BIGINT or VARCHAR in MySQL, MySQL accepts only string sql statement and always returns result in string format.

$mi = new mysqli("localhost", "root", "xxx", "test");
$uid = "12379739851403943597";   // Works
//$uid = 12379739851403943597;   // never Works
//$uid = (string) 12379739851403943597;   // get "1.2379739851404E+19" wrong string !
//$suid = sprintf("%.0f", $uid);          // get "12379739851403943936" lost precise

$stmt = $mi->prepare("select * from bitest where id = ?");
$stmt->bind_param('s', $uid);

$stmt->execute();
$stmt->bind_result($id, $name);

$stmt->store_result();
print "numrow: " . $stmt->num_rows . " - \n";
$stmt->fetch();
print "$id - $name \n";
$stmt->free_result();

$stmt->close();


$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'xxx');
$sql = "select * from bitest where id = ?";

$sth = $pdo->prepare($sql);
$sth->bindParam(1, $uid, PDO::PARAM_STR);

$sth->execute();
var_dump($sth->fetchAll(PDO::FETCH_ASSOC));
呆萌少年 2024-09-01 23:32:21

我认为您的 PDO 安装可能存在问题。

$uid = 552192373; // my facebook uid for testing
$statement = $db->prepare("SELECT * FROM users WHERE facebook_uid = :fbid");
$statement->bindParam(":fbid",$uid, PDO::PARAM_STR,45);
$out = $statement->execute();
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo '<pre>';
print_r($row);
echo '</pre>';

返回:

Array
(
    [id] => 1
    [facebook_name] => Jason Boehm
    [facebook_uid] => 552192373
)

I think there may be an issue with your PDO installation.

$uid = 552192373; // my facebook uid for testing
$statement = $db->prepare("SELECT * FROM users WHERE facebook_uid = :fbid");
$statement->bindParam(":fbid",$uid, PDO::PARAM_STR,45);
$out = $statement->execute();
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo '<pre>';
print_r($row);
echo '</pre>';

returns:

Array
(
    [id] => 1
    [facebook_name] => Jason Boehm
    [facebook_uid] => 552192373
)
停顿的约定 2024-09-01 23:32:21

已经有一段时间了...尝试将哈希值传递给 execute :

$statement->execute(array( 'fbid' => $uid ));

It's been a while... try passing a hash to execute instead:

$statement->execute(array( 'fbid' => $uid ));

我偏爱纯白色 2024-09-01 23:32:21

也许可以尝试 PDO::PARAM_INT

除此之外,请记住bindParam() 将变量作为引用。也许您的演示代码没有显示您在调用execute() 之前更改该变量的值。如果需要,请参见bindValue()。

Maybe try PDO::PARAM_INT

Aside from that, keep in mind bindParam() takes the variable as a reference. Maybe your demo code doesn't show you changing the value of that variable before execute() is called. See bindValue() if needed.

娇女薄笑 2024-09-01 23:32:21

尝试删除额外的参数,

$statement->bindParam (":fbid", $uid, PDO::PARAM_STR);

(编辑)
您是否 100% 确信 UID 周围没有多余的空格?使用 trim() 进行测试并通过按价值:

$statement->bindValue (":fbid", trim($uid), PDO::PARAM_STR);

Try dropping the extra parameter,

$statement->bindParam (":fbid", $uid, PDO::PARAM_STR);

(edit)
Are you 100% positive there is no extra whitespace surrounding the UID? Test with trim() and pass by value:

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