以原生数据类型获取MySQL查询结果?

19

我曾经尝试使用mysql_fetch_row()mysql_result()来获取MySQL查询结果,但是数字值以字符串的形式返回。

有没有办法按照表中存储的数据类型获取数据?

该应用程序将查询许多不同的查询,因此我无法逐个将值转换为预期的数据类型。

5个回答

19

我认为在PHP 5.2中无法以原生数据类型获取数据(即除了字符串以外的任何内容)...

在PHP 5.3中,如果我没记错的话,当您使用新的mysqlnd(MySQL Native Driver)驱动程序时,这就成为可能。

在查找我的书签时,我找到了关于mysqlnd的这篇文章:PDO_MYSQLND: PHP 5.3中PDO_MYSQL的新功能

它说(引用):

使用mysqlnd for PDO的优势

使用服务器端准备语句时,mysqlnd会返回本机数据类型, 例如,INT列将作为整数变量返回而不是字符串。 这意味着内部进行的数据转换更少。

但这仅适用于PHP 5.3(前提是您的PHP 5.3版本已编译mysqlnd(而不是旧的libmysql)),似乎只适用于准备好的语句 :-(

在您的情况下,这并没有太大帮助,我猜...


这里还有一篇关于mysqlnd新特性的文章,不仅涉及到预处理语句: PHP:使用mysqlnd实现网络流量、CPU和内存的节省

不确定这是否已经合并到官方的mysqlnd驱动程序中,最好的方法是尝试;但无论如何,它仍然只适用于PHP >= 5.3...


另一种解决方案是,在PHP端使用一种映射系统(如ORM),将从数据库返回的结果转换为PHP数据类型...

如果您想使用像 === !==这样的运算符,那么这是不好的,因为它们是类型敏感的...


谢谢Pascal MARTIN!我已经谷歌了几个小时,但没有找到任何我可以使用的东西。我对PHP相对较新,但听起来如果我想要本地支持,我需要使用PDO。不幸的是,我的主机正在运行5.2.something...另一个困难是,我正在尝试创建一个包含不同查询信息的xml报告文件输入。 PHP脚本读取请求的xml文件并将查询发送到数据库,因此我真的不知道正在查询什么数据以及应该如何返回它。时间开始创造性思维了 :) - user292089
1
无论使用PDO还是不使用PDO,在这种情况下都不应该改变任何东西:重要的是底层使用的驱动程序(即libmysql与mysqlnd)-而且我甚至不确定PHP 5.3.2中的mysqlnd是否会为标准查询返回本机类型;在您的情况下,无论如何,使用PHP 5.2,您唯一的解决方案将是一些映射层,在需要时进行类型转换... - Pascal MARTIN
请注意,如果使用PDO,则需要关闭预处理语句模拟。具体操作请参考此链接:https://dev59.com/sHM_5IYBdhLWcg3w2XLw#15592818 - Alexander Garden

11

如果使用 mysqli 而不是 PDO,请尝试这个

$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1);

3
我已经手动实现了这个功能,实际上并不难,只需要几行代码。
建议使用mysqli_fetch_fields()函数来获取查询结果的资源。
然后根据PHP字段类型编号与MySQL数据类型的映射(请参考此处的辛勤工作:http://www.php.net/manual/en/mysqli-result.fetch-field-direct.php),将MySQLi返回的各种数据库类型的字符串值转换为PHP中适当的类型。
但我不确定这会导致多大的减速。

1
除了Pascal MARTIN的回答之外,如果您使用MySQLi预处理语句,您将使用本机类型获取数据。 尝试这样做:
<?php
$mysqli = new mysqli("example.com", "user", "password", "database");

$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT, label CHAR(1))");
$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')");

$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = 1");
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();

printf("id = %s (%s)\n", $row['id'], gettype($row['id']));
printf("label = %s (%s)\n", $row['label'], gettype($row['label']));
?>

以上示例将输出:
id = 1 (integer)
label = a (string)

你可以在这里获取更多信息: https://dev.mysql.com/doc/apis-php/zh/apis-php-mysqli.quickstart.prepared-statements.html

0
我写了一个函数来规避这个问题(针对PDO):
/**
 * Converts columns from strings to types according to 
 * PDOStatement::columnMeta
 * 
 * @param PDOStatement $st
 * @param array $assoc returned by PDOStatement::fetch with PDO::FETCH_ASSOC
 * @return copy of $assoc with matching type fields
 */
function convertTypes(PDOStatement $statement, $assoc)
{
    for ($i = 0; $columnMeta = $statement->getColumnMeta($i); $i++)
    {
        $type = $columnMeta['native_type'];

        switch($type)
        {
            case 'DECIMAL':
            case 'TINY':
            case 'SHORT':
            case 'LONG':
            case 'LONGLONG':
            case 'INT24':
                $assoc[$columnMeta['name']] = (int) $assoc[$columnMeta['name']];
                break;
            case 'DATETIME':
            case 'DATE':
            case 'TIMESTAMP':
                $assoc[$columnMeta['name']] = strtotime($assoc[$columnMeta['name']]);
                break;
            // default: keep as string
        }
    }

    return $assoc;
}

当然,类型列表并不完整,转换也过于简化,但对于入门可能会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接