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

时间:2014-07-29 07:24:23

标签: php mysql pdo

在从旧的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;

请注意zerofill' IdTestDecimal字段。

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

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

我得到以下输出,正确的zerofilled 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),它仍然没有&#39 ; t返回前导零:

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

3 个答案:

答案 0 :(得分:7)

您可以使用LPAD吗?

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

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

<强>更新

我不认为将int改为小数是好的做法,为什么我不会深入研究这个问题,你可以搜索那个主题。

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

  

将mysqlnd用于PDO的优点

     

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

来源: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);

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

答案 1 :(得分:2)

如果要在不更改应用程序代码的情况下解决此问题,可以将数据库中的列定义修改为DECIMAL(9,0)

虽然我同意其他人评论说ZEROFILL在数据库中是一个奇怪的功能。无论如何,它应该是应用程序代码的一部分,用于格式化表示值。

答案 2 :(得分:1)

我将小例程写入 patch 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;
}

注意:其他答案也一样好,选择一个你最熟悉的答案。