PHP MySQL PDO:如何保留 zerofill int 列的前导零

Posted

技术标签:

【中文标题】PHP MySQL PDO:如何保留 zerofill int 列的前导零【英文标题】:PHP MySQL PDO: how to preserve leading zeros of zerofill int columns 【发布时间】:2014-09-20 12:29:07 【问题描述】:

在从旧的 mysql_*() 函数迁移到新的 PDO 类的过程中,我又遇到了一个障碍: 我有一个下表:

CREATE TABLE `test` (
  `Id` tinyint(4) unsigned zerofill NOT NULL,
  `UserName` varchar(4) NOT NULL,
  `TestDecimal` decimal(6,0) unsigned zerofill DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

注意填零的IdTestDecimal 字段。

如果我使用旧的mysql_*() 函数运行以下代码:

$SqlQuery = "SELECT * FROM test";
$Sql_Result = mysql_query($SqlQuery);
var_dump(mysql_fetch_array($Sql_Result));

我得到以下输出,正确填零 Id

array (size=6)
  0 => string '0001' (length=4)
  'Id' => string '0001' (length=4)
  1 => string 'alex' (length=4)
  'UserName' => string 'alex' (length=4)
  2 => string '000002' (length=6)
  'TestDecimal' => string '000002' (length=6)

但是,如果我使用 PDO 做同样的事情,就像这样:

$SqlQuery = "SELECT * FROM test";
$SqlResult = $MysqlPDO->prepare($SqlQuery);
$SqlResult->execute();
var_dump($SqlResult->fetch(PDO::FETCH_BOTH));

我得到了这个输出,不正确的非零填充Id

array (size=6)
  'Id' => int 1
  0 => int 1
  'UserName' => string 'alex' (length=4)
  1 => string 'alex' (length=4)
  'TestDecimal' => string '000002' (length=6)
  2 => string '000002' (length=6)

似乎 PDO 类正在查看列类型并在 php 中返回匹配的变量类型(在本例中为整数)。 经过一番搜索,我发现了 PDO::ATTR_STRINGIFY_FETCHES 属性,该属性可以设置为强制所有 MYSQL 结果作为字符串返回,虽然这似乎有效(我得到一个字符串而不是 int),但它仍然不返回前导零:

array (size=6)
  'Id' => string '1' (length=1)
  0 => string '1' (length=1)
  'UserName' => string 'alex' (length=4)
  1 => string 'alex' (length=4)
  'TestDecimal' => string '000002' (length=6)
  2 => string '000002' (length=6)

decimal(6,0) zerofill 字段似乎可以正常工作,但tinyint(4) zerofill 字段不能... 有什么办法可以使这项工作,还是我必须检查我的代码库并找出与此更改有关的问题(我已经确定了一些不再起作用的事情......)?

Demo code.

【问题讨论】:

这家伙解决了它改成十进制***.com/questions/6825106/… 可能不相关,但让我很头疼:$ResultType 的值是多少(在fetch($ResultType) 中)? @Alex ,mysql 版本?客户端 API 版本? create table 查询? @sectus: 好的,那为什么我的输出和你不一样呢?也许是 PHP 或 MySQL 配置?你能发布你的php.inimy.cnf 文件吗?谢谢! 【参考方案1】:

你可以使用LPAD

试试这个:SELECT *, LPAD( Id, 3, '0') AS zero_Fill_Id FROM test

应该根据 int 大小更改3:对于这种情况可能是 4?

更新:

我不认为将 int 更改为 decimal 是一种好习惯,为什么我不会深入探讨,您可以搜索该主题。

我认为你使用mysqlnd 驱动程序,我发现它(检查是否启用How to know if MySQLnd is the active driver?):

使用 mysqlnd 进行 PDO 的优势

mysqlnd 在以下情况下返回本机数据类型 使用服务器端准备好的语句, 例如返回一个 INT 列 作为整数变量而不是作为 细绳。这意味着更少的数据 内部转换。

来源:How to get numeric types from MySQL using PDO?

在这种情况下有PDO::ATTR_STRINGIFY_FETCHES,在你的情况下应该设置为true,你也可以尝试PDO::ATTR_EMULATE_PREPARES属性进一步看:PDO MySQL: Use PDO::ATTR_EMULATE_PREPARES or not?

...
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);

希望这对任何情况或任何人都有帮助:))

【讨论】:

虽然这修复了我的问题中的具体示例,但它需要我检查所有代码并修复各处的查询。如果我必须这样做,我宁愿修改代码以使用从 MySQL 返回的实际整数值。感谢您的回答! 就个人而言,我认为 LPAD 是要走的路——但我不太明白 zerofill 的意义 @Alex 您只需要修改数据库句柄,而不是每个查询,因此我希望 stringify fetches 选项是最简单的选项,因为您只需在创建 $MysqlPDO 数据库时设置属性处理程序。您可能还想更改错误处理,这是 setAttribute 的常见用例。 php.net/manual/en/pdo.setattribute.php @edmondscommerce:很抱歉花了这么长时间才回复,但是在我的问题中我已经指出,即使将PDO::ATTR_STRINGIFY_FETCHES 设置为TRUE,它也会返回字符串(而不是整数),但是这些字符串仍然没有填零,所以我的问题仍然存在。 OK 看起来您可能只是遇到了一个需要解决的 PDO 问题。【参考方案2】:

我会编写小例程来修补 PDO 输出以满足要求,并尽量减少对编码的更改。

$results = pdoFix($SqlResult->fetchAll(PDO::FETCH_BOTH))

function pdoFix($results) 
    foreach ($results as &$row)  // note the "&"
      $row[0] = sprintf("%'04s",$row[0]); // zerofill '0'
      $row['id'] = sprintf("%'04s",$row['id']); // zerofill 'id'
    
    unset($row); // break the reference with the last element
    return $results;

注意:其他答案也一样好,请选择您最满意的一个。

【讨论】:

以上是关于PHP MySQL PDO:如何保留 zerofill int 列的前导零的主要内容,如果未能解决你的问题,请参考以下文章

如何在PHP下开启PDO MySQL的扩展

如何在PHP下开启PDO MySQL的扩展

php+mysql 请问:用pdo如何获取某个表中记录的数目?

php+mysql 请问:用pdo如何获取某个表中记录的数目?

如何在 PHP PDO 中使用异步 Mysql 查询

PHP PDO MySQL 以及它如何真正处理 MySQL 事务?