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;
注意填零的Id
和TestDecimal
字段。
如果我使用旧的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.ini
和my.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+mysql 请问:用pdo如何获取某个表中记录的数目?