CAST 与 CONVERT 是什么
显式类型转换把一种类型的值转成另一种。MySQL 用 CAST(x AS SIGNED) 这类写法,目标类型名带自己的命名习惯;PostgreSQL 用 CAST(x AS integer) 或简写 x::integer,类型名遵循 SQL 标准。两者语法相近,但可用的目标类型与遇到非法输入时的处理策略差别很大。
基本信息
| MySQL 语法 | CAST(expr AS type),另有等价形式 CONVERT(expr, type) |
|---|---|
| MySQL 目标类型 | SIGNED、UNSIGNED、CHAR、DATE、DATETIME、DECIMAL(M,D)、JSON、BINARY |
| PostgreSQL 语法 | CAST(expr AS type) 或简写 expr::type |
| PostgreSQL 目标类型 | integer、bigint、numeric(M,D)、text、date、timestamptz |
| 非法输入 | MySQL 截取可用前缀并产生告警;PostgreSQL 直接抛错 |
| 无符号陷阱 | MySQL 无符号列运算出负数会报越界 |
MySQL 写法
MySQL 写法
SELECT CAST('123' AS SIGNED); -- 123
SELECT CAST(12.34 AS SIGNED); -- 12(小数转整数会舍入,别当截断用)
SELECT CAST(123 AS CHAR); -- '123':数字转字符串
SELECT CAST('2024-06-01' AS DATE); -- 2024-06-01
SELECT CAST('123abc' AS SIGNED); -- 123 并产生 warning
SELECT CAST(-1 AS UNSIGNED); -- 绕回成一个很大的整数,负数转无符号要避免PostgreSQL 写法
PostgreSQL 写法
SELECT CAST('123' AS integer), '123'::int; -- 两种写法等价
SELECT CAST(12.34 AS numeric(6,2)); -- 保留两位小数
SELECT CAST('2024-06-01' AS date); -- 转成日期
SELECT CAST('123abc' AS integer); -- 直接报错 invalid input syntax
SELECT '123'::int + 1; -- 转换后参与数值运算两库对照
| 需求 | MySQL 8 | PostgreSQL |
|---|---|---|
| 数字转字符串 | CAST(n AS CHAR) | n::text |
| 字符串转整数 | CAST(s AS SIGNED) | s::integer 或 ::bigint |
| 转小数 | CAST(x AS DECIMAL(10,2)) | CAST(x AS numeric(10,2)) |
| 转日期 | CAST(s AS DATE) | s::date |
| 转 JSON | CAST(s AS JSON) | s::json 或 ::jsonb |
| 非法输入 | 截取前缀并产生告警 | 抛 invalid input syntax 错误 |
典型使用场景
- 导入外部数据:把文本列转成数字列或日期列
- 两侧类型不同的列做比较前先显式转换成同一类型
- 迁移脚本改造:把 MySQL 的无符号写法换成标准类型写法
- 拼接前把数字转成字符串,避免隐式转换带来意外格式
- 把 JSON 文本落成 JSON 类型,才能用 JSON 函数与索引
- 排查隐式转换导致的慢查询,先看比较两侧的类型
给列本身加 CAST 会破坏索引可用性:WHERE CAST(num_col AS CHAR) = '10' 会全表扫描。更高效的做法是把常量转成列的类型,让列保持“裸用”,这样才能走索引。
MySQL 的 CAST 对脏数据是尽力而为:'123abc' 会得到 123 并只产生告警;PostgreSQL 遇到同样输入直接报错中断整条查询。迁移前先清洗数据,并统计转换结果里的 NULL 与告警数量。