You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何PDO在静态与动态值联合查询中返回整数为字符串?

PDO联合查询返回字段类型异常问题

环境与测试配置

PDO配置

$options = [
    \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
    \PDO::ATTR_EMULATE_PREPARES   => false,
];

user表结构

CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `admin` tinyint(1) unsigned NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

测试情况

  1. 普通查询:返回admin为整数,符合预期
$sql = "SELECT admin FROM user";
$pdo_statement = $pdo->query($sql);
$result = $pdo_statement->fetchAll();

var_dump($result);

// > array(1) { [0]=> array(1) { ["admin"]=> int(1) } } ...
  1. 静态值联合查询:返回admin为整数,符合预期
$sql = "SELECT 0 AS admin FROM user
    UNION
    SELECT 1 AS admin FROM user";
$pdo_statement = $pdo->query($sql);
$result = $pdo_statement->fetchAll();

var_dump($result);

// > array(1) { [0]=> array(1) { ["admin"]=> int(1) } } ...
  1. 静态与动态值混合联合查询:返回admin为字符串,不符合预期
$sql = "SELECT admin FROM user
    UNION
    SELECT 1 AS admin FROM user";
$pdo_statement = $pdo->query($sql);
$result = $pdo_statement->fetchAll();

var_dump($result);

// > array(1) { [0]=> array(1) { ["admin"]=> string(1) "1" } } ...

测试环境

Apache 2.4.51
PHP 5.6.40 | 7.4.26 | 8.0.13 | 8.1.0
MySQL 8.0.27
MariaDB 10.6.5

疑问

为何第三种混合联合查询中,PDO会将admin字段以字符串类型返回而非整数?这是否为PDO的Bug,还是存在我忽略的细节?


解答:这不是PDO的Bug,是MySQL类型规则与PDO驱动逻辑共同作用的结果

1. MySQL的UNION类型统一规则

当使用UNION合并多个查询结果时,MySQL会为结果集的每个字段确定一个兼容所有子查询的统一类型:

  • 第三种查询中,第一个子查询的admin是tinyint(1) unsigned(无符号小整数),第二个子查询的1是默认的int(11)(有符号整数)。
  • 由于两个类型分属不同符号属性的数值类型,MySQL会将结果集的字段类型转换为**DECIMAL类型**——这是一种高精度数值类型,能同时兼容无符号和有符号数值的范围。

2. PDO对DECIMAL类型的处理逻辑

PDO的MySQL驱动在处理DECIMAL类型字段时,默认返回字符串而非整数。原因是DECIMAL可以存储超出PHP整数范围的高精度数值,直接转换为整数可能导致精度丢失或溢出,因此驱动选择以字符串形式保留完整数值。

3. 前两种情况正常的原因

  • 第一种情况:直接查询表字段,返回的是tinyint类型,PDO驱动可安全转换为PHP整数。
  • 第二种情况:两个子查询都是字面量整数,MySQL会将结果集类型统一为int,PDO驱动直接转换为PHP整数。

解决方法

如果需要确保返回整数类型,可通过以下方式处理:

  • SQL层面显式转换:将字面量转换为与表字段一致的类型,比如SELECT CAST(1 AS UNSIGNED TINYINT) AS admin,这样UNION后的字段类型保持为tinyint unsigned,PDO会返回整数。
  • PHP层面手动转换:获取结果后,将字符串字段值强制转换为整数,例如$result[0]['admin'] = (int)$result[0]['admin'];。

内容的提问来源于stack exchange,提问作者Xintaur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 03:50:31