【问题标题】:PL SQL replace conditionally suggestionPL SQL 有条件替换建议
【发布时间】:2018-02-09 21:32:09
【问题描述】:

如果单词有任何非数字字符,我需要将整个单词替换为 0。例如,如果 digital_word='22B4' 则替换为 0,否则如果 digital_word='224' 则不替换。

SELECT replace_funtion(digital_word,'has non numeric character pattern',0,digital_word)
FROM dual;

我尝试了 decode、regexp_instr、regexp_replace,但找不到正确的解决方案。 请指教。

谢谢。

【问题讨论】:

  • 为什么你需要一个函数(PL/SQL)来做这个?你没有!

标签: sql oracle


【解决方案1】:

最快的方法是用 null 替换所有数字(简单地删除它们)并查看是否有任何剩余。你不需要正则表达式(slow!),你只需要标准的字符串函数TRANSLATE()

不幸的是,Oracle 不得不解决他们自己对NULL 的不一致处理——有时是空字符串,有时不是。在TRANSLATE() 函数的情况下,您不能简单地将每个数字转换为空;您还必须将非数字字符转换为自身,以便第三个参数不是空字符串(在关系理论中,视为真正的NULL)。有关 TRANSLATE() 函数的信息,请参阅 Oracle 文档。 https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions216.htm#SQLRF06145

那么,可以用CASE表达式(或者各种形式的NULL处理函数;我更喜欢CASE,这是SQL标准)得到结果:

with 
     nums ( num ) as (
       select '123' from dual union all
       select '-56' from dual union all
       select '7A9' from dual union all
       select '0.9' from dual 
     )
-- End of simulated inputs (for testing only, not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your own table and column names.
select num,
       case when translate(num, 'z0123456789', 'z') is null 
            then num
            else '0'
       end as result
from   nums
;

NUM  RESULT
---  ------
123  123
-56  0
7A9  0
0.9  0

注意:这里的所有内容都是varchar2 数据类型(或其他某种字符串数据类型)。如果应该将结果转换为数字,请将整个 case 表达式包含在 TO_NUMBER() 中。另请注意,字符串'-56''0.9' 不是全数字(它们包含非数字),因此两者的结果都是'0'。如果这不是您所需要的,您必须更正原帖中的问题陈述。

【讨论】:

    【解决方案2】:

    您可以尝试以下方法:

    SELECT CASE WHEN REGEXP_LIKE(digital_word, '\D') THEN '0' ELSE digital_word END
      FROM dual;
    

    正则表达式类\D 匹配任何非数字字符。你也可以使用[^0-9] 达到同样的效果:

    SELECT CASE WHEN REGEXP_LIKE(digital_word, '\D') THEN '0' ELSE digital_word END
      FROM dual;
    

    或者,您可以查看digital_word 的值是否仅由数字组成:

    SELECT CASE WHEN REGEXP_LIKE(digital_word, '^\d+$') THEN digital_word ELSE '0' END
      FROM dual;
    

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      类似以下更新查询的内容会帮助您:

      update [table] set [col] = '0'
      where REGEXP_LIKE([col], '.*\D.*', 'i')
      

      【讨论】:

      • 谁说过update?为什么在正则表达式中需要.*?为什么需要不区分大小写的比较?
      【解决方案4】:

      这个想法很简单——你需要检查值是否是数字

      脚本:

      with nums as
      (
      select '123' as num from dual union all
      select '456' as num from dual union all
      select '7A9' as num from dual union all
      select '098' as num from dual 
      )
      select n.* 
       ,nvl2(LENGTH(TRIM(TRANSLATE(num, ' +-.0123456789', ' '))),'0',num)
      from nums n
      

      结果

      1   123 123
      2   456 456
      3   7A9 0
      4   098 098
      

      查看下面的更多文章,看看哪种方式更适合您

      How can I determine if a string is numeric in SQL?

      https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:15321803936685

      How to tell if a value is not numeric in Oracle?

      【讨论】:

      • OP 谈论“非数字” - 所以如果输入有字符 + 或 .那么它就是“非数字”,不管它们如何用来表示“数字”。
      猜你喜欢
      • 2016-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-05
      • 2014-11-26
      相关资源
      最近更新 更多