【发布时间】:2012-01-20 02:39:43
【问题描述】:
是否可以通过在 Postgres 8.3 中将varchar 列强制转换为integer 对结果行进行排序?
【问题讨论】:
标签: postgresql types casting indexing integer
是否可以通过在 Postgres 8.3 中将varchar 列强制转换为integer 对结果行进行排序?
【问题讨论】:
标签: postgresql types casting indexing integer
绝对有可能。
ORDER BY varchar_column::int
确保每个条目的varchar 列中都有有效的整数文字,否则会出现异常invalid input syntax for integer: ...。 (前导和尾随空格是可以的 - 它将被自动修剪。)
如果是这样,那么为什么不将列转换为 integer 开始呢?更小、更快、更清洁、更简单。
在强制转换之前删除非数字字符,从而避免可能的异常:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
regexp_replace() 表达式有效地删除了所有非数字,因此只保留数字或空字符串。 (见下文。)
\D 是字符类[^[:digit:]] 的简写,表示所有非数字([^0-9])。
在具有过时设置standard_conforming_strings = off 的旧 Postgres 版本中,您必须使用 Posix 转义字符串语法 E'\\D' 来转义反斜杠 \。这是 Postgres 8.3 中的默认设置,因此您需要在过时的版本中使用它。
第 4 个参数 g 用于 "globally",指示替换 所有 次出现,而不仅仅是第一次。
您可能希望允许负数使用前导破折号 (-)。
如果字符串根本没有数字,则结果是一个空字符串,对于转换为integer 无效。使用NULLIF 将空字符串转换为NULL。 (您可以考虑使用0。)
结果保证有效。此过程适用于按问题正文中的要求强制转换为 integer,不适用于标题中提到的numeric。
一种方法是index on an expression。
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
然后在ORDER BY 子句中使用相同的表达式:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
用EXPLAIN ANALYZE测试函数索引是否真的被使用了。
【讨论】:
此外,如果您想按可转换为浮动的文本列进行排序,那么可以这样做:
select *
from your_table
order by cast(your_text_column as double precision) desc;
【讨论】: