【问题标题】:Regular expression metacharacter in SQL yields different results in Oracle vs. PostgresSQL 中的正则表达式元字符在 Oracle 和 Postgres 中产生不同的结果
【发布时间】:2018-05-03 21:06:33
【问题描述】:

我正在尝试将一些查询从 Oracle 环境转换为 Postgres。这是其中一个查询的简化版本:

SELECT * FROM TABLE
  WHERE REGEXP_LIKE(TO_CHAR(LINK_ID),'\D')

我相信等效的 postgreSQL 应该是这样的:

SELECT * FROM TABLE
    WHERE CAST(LINK_ID AS TEXT) ~ '\D'

但是当我在它们各自的环境中对完全相同的数据集运行这些查询时,第一个查询不输出任何记录(这是正确的),第二个查询输出表中的所有记录。我没有编写原始代码,但据我了解,它正在寻找数字字段 LINK_ID 中非数字字符的任何值。 \D 元字符在 Oracle 和 postgres 中的行为是否应该不同?我在文档中没有看到任何应该说的内容。

【问题讨论】:

  • 能否提供几行数据示例?
  • 每个DBMS中link_id的数据类型是什么?
  • 尾随空格的处理方式不同?输入rtrim
  • @GregoryArenius 这里有一些值... 22290704.00000000 40006661.00000000 22291131.00000000 0.00000000 0.00000000 所有值都是数字。
  • “作品”是什么意思?如果您不知道它要做什么,您怎么知道它在 postgres 上“不起作用”而在 oracle 上“不起作用”? :-)

标签: sql oracle postgresql regexp-like


【解决方案1】:

Oracle 的TO_CHAR(number) 状态的文档

如果省略 fmt,则 n 将转换为 VARCHAR2 值,其长度正好足以容纳其有效数字。

这意味着唯一可能产生的非数字字符是负号或小数点。如果数字为正数且没有小数部分,则不会匹配正则表达式\D

另一方面,在 PostgreSQL 上,CAST(numeric(38,8)as TEXT) 返回一个具有类型规范指定的小数位数的值,在本例中为 8。 例如:

cast( cast(12341234 as numeric(38,8)) as TEXT)

生成12341234.00000000 此类转换的结果将始终包含小数点,因此将始终匹配正则表达式\D

您可能会发现用这个替换它可以解决您的问题:

(LINK_ID % 1) <> 0.0

或者,如果您需要使用正则表达式(例如,为了简化迁移工作),请考虑将其更改为 '\.0*[1-9]',即查找其后有任何非零数字的小数点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    相关资源
    最近更新 更多