在从旧的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' Id
和TestDecimal
字段。
如果我使用旧的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
字段无关...
有没有办法让这项工作,或者我将不得不重新审视我的代码库,并找出有什么打破这种变化(我已经确定了一些不再工作的东西......)?
答案 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;
}
注意:其他答案也一样好,选择一个你最熟悉的答案。