我将PHP MySQL语句更改为预准备语句,并将浮点数从句点更改为逗号

I changed my PHP MySQL statement to a prepared statement, and floats changed decimal point from period to comma

提问人:OZ1SEJ 提问时间:9/27/2022 最后编辑:DharmanOZ1SEJ 更新时间:9/27/2022 访问量:377

问:

我有一个带有浮点数的MySQL表。在PHPMyAdmin中,它们被列为例如“55.123”

我曾经用它们把它们拉出来

$sql = "SELECT latitude,longitude FROM table WHERE id=" . $id;
$conn->query($sql);

当我打印我的浮标时,我得到例如“55.123”——这并不奇怪。 出于显而易见的原因,我需要将此查询更改为准备好的语句:

$sql = "SELECT latitude,longitude FROM table WHERE id=?;";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i",$id);
$stmt->execute();

现在,当我打印浮点数时,我得到例如“55,123” - 带有逗号而不是句点。

我想我的

setlocale(LC_ALL, 'da_DK.utf8');

可能与此有关,但我真的不知道该怎么办。因为要么我应该停止将我的查询更改为准备好的语句,要么我应该将浮点数转换为字符串并将逗号替换为句点。任何一种解决方案都不太理想。建议?

php mysql mysqli 浮点

评论

1赞 Barmar 9/27/2022
传统方法使用MySQL的格式将所有结果作为字符串返回。当您使用较新的方法时,数据库中的浮点数将作为 PHP 浮点数返回,因此 PHP 会根据语言环境对其进行格式化。
0赞 Dharman 9/27/2022
你如何打印这个数字?我无法通过使用来重现它echo

答:

0赞 Barmar 9/27/2022 #1

当您使用预准备语句时,您也在使用 MySQL 本机驱动程序 (MYSQLND)。当它获取MySQL列时,默认情况下,它会将它们作为PHP浮点数而不是字符串返回。因此,在格式化它们时会使用 PHP 的语言环境。FLOAT

这由选项 控制。您可以像以前一样取消设置以获取字符串。MYSQLI_OPT_INT_AND_FLOAT_NATIVE

$conn->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, false);

请注意,必须在创建对象和连接到服务器之间调用此函数。所以你不能用,你必须调用和:mysqlinew mysqlimysqli_init()$conn->real_connect()

$conn = mysqli_init();
$conn->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
$conn->real_connect('server', 'user', 'pass', 'database');

评论

0赞 Dharman 9/27/2022
该选项可以在连接到服务器后调用。它可以随时调用。此外,当不使用预准备语句时,您也在使用 mysqlnd。唯一的区别是使用哪种协议。
1赞 Your Common Sense 9/27/2022
@Dharman 有趣的是,该MYSQLI_OPT_INT_AND_FLOAT_NATIVE似乎不会影响准备好的语句,而只会影响常规查询的结果(是的,我也用real_connect进行了测试)
0赞 Your Common Sense 9/27/2022
总的来说,这个答案相当具有误导性。如果解释上面评论中提到的区域设置问题,那就更好了。
0赞 Dharman 9/27/2022
@YourCommonSense 是的,该设置未用于预准备语句。请注意,该方法中未使用该参数,并且仅在下一个方法中使用。as_int_or_float
1赞 Barmar 9/28/2022
@Dharman 文档说“mysqli_options() 应该在 mysqli_init() 之后和 mysqli_real_connect() 之前调用。我可能夸大了将“应该”视为“必须”——也许这取决于选项,因为其中一些会影响连接,并且在连接后毫无意义。
1赞 Dharman 9/27/2022 #2

这意味着您使用的是旧版本的 PHP。在 PHP 8.0 之前,语言环境设置会影响浮点数到字符串的转换。这意味着,如果你有一个浮点数,并且你使用了类似的东西来输出它,那么到字符串的转换将替换为使用小数分隔符的区域设置。例如echo.,,

setlocale(LC_ALL, "de_DE.UTF-8");
$number = 42.42;
echo $number; // outputs 42,42 in PHP 7

升级到 PHP 8 或更高版本后,无论语言环境如何,输出都应始终相同。


至于为什么mysqli中的预处理查询和非预处理查询之间存在差异:mysqli预处理语句在与数据库通信时使用二进制协议(而不是文本协议)。这意味着从 MySQL 到达的数据已经是整数、浮点数或字符串。已决定默认情况下不会强制转换为字符串。毕竟,这有什么意义呢?但是为了使文本协议与二进制协议兼容,添加了一个选择加入设置,要求 PHP 自动将数字字符串转换为 PHP 原生整数和浮点数。您可以随时通过调用以下命令来启用该设置:

$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);

二进制协议(预准备语句)忽略此设置。

我不知道为什么设置是选择加入而不是选择退出。PHP 8.1 在 PDO 中改变了这一点,但在 mysqli 中没有。

评论

0赞 OZ1SEJ 9/30/2022
听起来很有道理。我确实在 PHP 7.4.32 上运行。谢谢。