如何从 MySQL 返回整数和数字列作为 PHP 中的整数和数字?

Posted

技术标签:

【中文标题】如何从 MySQL 返回整数和数字列作为 PHP 中的整数和数字?【英文标题】:How do I return integer and numeric columns from MySQL as integers and numerics in PHP? 【发布时间】:2013-12-03 11:09:00 【问题描述】:

问题是数据库查询应该在 php 中为整数列返回整数数据类型。相反,查询将每一列都作为字符串类型返回。

我已确保 "PDO::ATTR_STRINGIFY_FETCHES" if false 只是为了确保不会将结果转换为字符串。

我看到的答案:

无法完成 不,它可以在安装了 PHP/mysql 的 Mac OS X 上运行 在代码中输入所有值 不,我不会这样做 别担心,PHP 是松散类型的 我的数据以 JSON 格式输出并被许多其他服务使用,有些需要正确格式的数据

根据我的研究,我了解到这是一个驱动程序实现问题。

许多消息来源声称 MySQL 本机驱动程序不支持返回数字类型。这似乎不正确,因为它适用于 Mac OS X。除非他们的意思是说“Linux 上的 MySQL 本机驱动程序不支持该功能”。

这意味着我在 Mac OS X 上安装的驱动程序/环境有一些特殊之处。我一直在尝试找出差异以便应用修复,但我对如何检查的知识有限这些东西。

区别:

OS X 上的 PHP 是通过 Home Brew 编译和安装的 Ubuntu 上的 PHP 是通过“apt-get install php5-dev”安装的 OS X 上的 PHP 正在连接到也在 OS X 上运行的 MySQL 服务器 服务器版本:5.1.71-log 源码分发 Ubuntu 上的 PHP 正在连接到 Rackspace 云数据库 服务器版本:5.1.66-0+squeeze1 (Debian)

Ubuntu 环境

版本:10.04.1

PHP 5.4.21-1+debphp.org~lucid+1 (cli)(构建时间:2013 年 10 月 21 日 08:14:37)

php -i

pdo_mysql

用于 MySQL 的 PDO 驱动程序 => 已启用 客户端 API 版本 => 5.1.72

Mac OS X 环境

10.7.5

PHP 5.4.16 (cli)(构建时间:2013 年 8 月 22 日 09:05:58)

php -i

pdo_mysql

用于 MySQL 的 PDO 驱动程序 => 已启用 客户端 API 版本 => mysqlnd 5.0.10 - 20111026 - $Id: e707c415db32080b3752b232487a435ee0372157 $

使用的 PDO 标志

PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES => false,

【问题讨论】:

这是mysqlnd的责任。我相信 我有完全相同的问题,但对于 MS SQL Server。是否有一个强类型库,类似于 mysqlnd?我能找到的latest drivers 返回所有字符串。 【参考方案1】:

解决方案是确保您使用的是 mysqlnd php 驱动程序。

你怎么知道你没有使用mysqlnd?

查看php -i 时,将没有提及“mysqlnd”。 pdo_mysql 部分会有这样的内容:

pdo_mysql

PDO Driver for MySQL => enabled Client API version => 5.1.72

如何安装?

L/A/M/P 的大多数安装指南建议使用apt-get install php5-mysql,但 MySQL 的本机驱动程序由不同的包安装:php5-mysqlnd。我发现这可以通过 ppa:ondrej/php5-oldstable 获得。

要切换到新的驱动程序(在 Ubuntu 上):

删除旧驱动:apt-get remove php5-mysql 安装新驱动:apt-get install php5-mysqlnd 重启apache2:service apache2 restart

如何检查驱动程序是否正在使用?

现在php -i 将在pdo_mysql 部分明确提及“mysqlnd”:

pdo_mysql

PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.10 - 20111026 - $Id:      e707c415db32080b3752b232487a435ee0372157 $

PDO 设置

确保PDO::ATTR_EMULATE_PREPARESfalse(检查您的默认值或设置它):$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

确保PDO::ATTR_STRINGIFY_FETCHESfalse(检查您的默认值或设置它):$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

返回值

浮点类型(FLOAT、DOUBLE)作为 PHP 浮点数返回。 整数类型(INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、BIGINT †)以 PHP 整数形式返回。 定点类型(DECIMAL、NUMERIC)作为字符串返回。

† 值大于 64 位有符号整数 (9223372036854775807) 的 BIGINT 将作为字符串返回(或 32 位系统上的 32 位)

    object(stdClass)[915]
      public 'integer_col' => int 1
      public 'double_col' => float 1.55
      public 'float_col' => float 1.5
      public 'decimal_col' => string '1.20' (length=4)
      public 'bigint_col' => string '18446744073709551615' (length=20)

【讨论】:

请注意,即使启用了此版本的 mysqlnd,DECIMALS 仍将作为字符串发送...(尽管 FLOATS 将作为浮点数返回!):/ 来源:我测试过。 还要注意 PDO::ATTR_STRINGIFY_FETCHES 与它无关——我试过了,它对结果没有影响,this post 用户 @Josh Davis 说它与 MySQL 无关。跨度> 谢谢,我已经进一步调查并更新了关于 DECIMAL 类型的注释。 @pere 这是正确的行为。 DECIMAL 不是数字类型。这是数字的字符串格式。所以你可以返回:0.30 作为"0.30" 而不是0.3。十进制用于此...所以这是正确的行为 为什么这是一个该死的妥协?我需要PDO::ATTR_EMULATE_PREPARES 多次使用命名参数【参考方案2】:

这个被接受的答案有效,并且似乎是谷歌上这个问题最流行的答案。我的问题是我需要将应用程序部署到多个环境,而且我并不总是能够安装正确的驱动程序,而且我需要小数点是数字,而不是字符串。所以我创建了一个例程在 JSON 编码之前输入大小写,很容易修改以适应。这有点像从轨道上对其进行核弹。

首先,使用“show columns from”从表中获取列。 mysql query "SHOW COLUMNS FROM table like 'colmunname'":questions

$query = 'SHOW COLUMNS FROM ' . $table; //run with mysqli or PDO 

然后将类型放入由列名索引的数组中,以便于迭代。假设来自显示列的结果集位于名为 $columns_from_table 的变量中。 http://php.net/manual/en/function.array-column.php

$column_types = array_column( $columns_from_table, 'Type', 'Field');

接下来我们要从类型中删除括号,这将是 varchar(32) 或 decimal(14,6) 之类的东西

foreach( $column_types as $col=>$type )

    $len = strpos( $type, '(' );
    if( $len !== false )
    
        $column_types[ $col ] = substr( $type, 0, $len );
    

现在我们有一个关联数组,以列名作为索引,格式化类型作为值,例如:

Array
(
    [id] => int
    [name] => varchar
    [balance] => decimal
    ...
)

现在,当您从表中进行选择时,您可以遍历结果并将值转换为适当的类型:

foreach( $results as $index=>$row )

    foreach( $row as $col=>$value )
    
        switch( $column_types[$col] )
        
            case 'decimal':
            case 'numeric':
            case 'float':
            case 'double':

                $row[ $col ] = (float)$value;
                break;

            case 'integer':
            case 'int':
            case 'bigint':
            case 'mediumint':
            case 'tinyint':
            case 'smallint':

                $row[ $col ] = (int)$value;
                break;
        

    
    $results[ $index ] = $row;

switch 语句可以很容易地修改以适应,并且可以包括日期函数等。例如,在我的例子中,第 3 方将货币值作为小数推送到数据库中,但是当我获取该数据并需要以 JSON 格式返回,我需要的是数字,而不是字符串。

使用 PHP 7、7.2 和 JQuery 2、3 测试。

【讨论】:

【参考方案3】:

在 php-8.1.0RC1/ 中,即使是 EMULATE_PREPARES 也是本机类型, https://github.com/php/php-src/tree/c18b1aea289e8ed6edb3f6e6a135018976a034c6 所以将来应该可以省略PDO::ATTR_EMULATE_PREPARES => false,选项。

【讨论】:

以上是关于如何从 MySQL 返回整数和数字列作为 PHP 中的整数和数字?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 MySQL 的 JSON 数组中删除一个数字?

mysqli将位和整数作为字符串返回

如何将 mysql 数字类型数据从 php 传递到 Javascript 以作为字符串类型到达? [关闭]

MySQL/PHP:如何获取列和关联数据

MySQL PDO fetchAll 作为具有整数索引的数组

用php判断两个数字的大小和差值 两个数字均为整数