【问题标题】:Trim leading zeroes if it is numeric and not trim zeroes if it is alphanumeric如果是数字则修剪前导零,如果是字母数字则不修剪零
【发布时间】:2018-07-08 10:19:31
【问题描述】:

在一列中,有以“0”开头的数字和字母数字值。 如果它是数字,如何修剪前导零,如果它是 Oracle 中的字母数字,则不应修剪零。

我需要在WHERE Con​​dition中使用它。

例如

000012345 应该是 12345012321 应该是 1232100012JY12 应该是 00012JY12

这是我尝试过的:

    SELECT COUNT(*)
    FROM <TABLE 1> ONN, <TABLE 2> SV
   WHERE SV.CSA_SHP_VISIT_STG_SEQ_ID=ONN.CSA_SHOP_VIST_SEQ_ID
    AND EXISTS (SELECT '1' FROM  <TABLE 3> TMP 
    WHERE TRIM(SV.WORK_ORDER_NUM) = TRIM(TMP.WORK_ORDER_NUM)
    AND PLANT IN ('EMA')
    AND regexp_replace(TRIM(ONN.INSTLD_PART), '^0+([[:digit:]]+)$', 
   '\1')=TRIM(TMP.INSTLD_PART)  AND
  TRIM(ONN.INSTLD_PART_SERIAL_NUM)=TRIM(TMP.INSTLD_PART_SERIAL_NUM) AND      
    nvl(to_number(TRIM(ONN.INSTLD_PART_CSN)),0)=
    nvl(to_number(TRIM(TMP.INSTLD_PART_CSN)),0)
    and REGEXP_LIKE(tmp.INSTLD_PART_CSN, '^-?\d+(\.\d+)?$'))

【问题讨论】:

  • 不确切知道您在做什么,但如果可能的话,这将是在演示级别(无论您使用什么应用程序或报告)更好地处理数据。

标签: sql oracle oracle11g leading-zero character-trimming


【解决方案1】:

尽可能(在本例中)使用标准字符串函数,例如 SUBSTR、INSTR、TRANSLATE 等,而不是正则表达式函数。正则表达式功能更强大,但也更耗时(正是因为这个原因),所以它们应该只在真正需要时使用。

如果列名是str,那么:

case when translate(str, 'z0123456789', 'z') is null
     then ltrim(str, '0')
     else str                      end

TRANSLATE 会将 z 转换为自身,将所有数字转换为 NULL,并将所有其他字符转换为自身。 (唉,需要 z 或一些非数字字符。)

当且仅当 TRANSLATE 的结果为 NULL 时,输入为全数字。

演示:

select str, case when translate(str, 'z0123456789', 'z') is null
                 then ltrim(str, '0')
                 else str
            end  as new_str
from
(
  select '000012345' as str from dual union all
  select '012321'    as str from dual union all
  select '00012JY12' as str from dual
);

STR       NEW_STR 
--------- ---------
000012345 12345    
012321    12321    
00012JY12 00012JY12

【讨论】:

  • 你是对的;我想到了TRANSLATE,但后来决定选择REGEXP_REPLACE,但在我的数据库中有一个大表时,后者确实需要1.5倍的时间。遗憾的是,Oracle 没有将 TRANSLATE 中的 '' 视为简单的空。虽然我开始欣赏 Oracle 的 VARCHAR2 '' is null 方法,但他们在 TRANSLATE 方面做得不好。
  • 我需要在 where 条件下使用它,例如 ** SELECT COUNT(*) FROM ONN, SV WHERE SV.CSA_SHP_VISIT_STG_SEQ_ID=ONN.CSA_SHOP_VIST_SEQ_ID AND EXISTS (SELECT '1' FROM TMP WHERE TRIM(SV.WORK_ORDER_NUM) = TRIM(TMP.WORK_ORDER_NUM) AND PLANT IN ('EWL') AND (当 translate(TRIM(ONN.INSTLD_PART), 'z0123456789', 'z') 为空时的情况ltrim(TRIM(ONN.INSTLD_PART), '0') 否则 TRIM(ONN.INSTLD_PART) end)=TRIM(TMP.INSTLD_PART) ); **。我试过了,但它需要更多时间。
  • @SelvathalapathyS - 和... ??
【解决方案2】:

使用regexp_replace(col, '^0+([[:digit:]]+)$', '\1')

这会将仅包含前导零和尾随数字的字符串替换为仅尾随数字,从而删除零。

示例查询:

select col, regexp_replace(col, '^0+([[:digit:]]+)$', '\1') as newvalue
from
(
  select '000012345' as col from dual
  union all
  select '012321' as col from dual
  union all
  select '00012JY12' as col from dual
);

结果:

色彩 |新价值 ----------+---------- 000012345 | 12345 012321 | 12321 00012JY12 | 00012JY12

【讨论】:

    【解决方案3】:

    如果您使用的是 Oracle 12.2,则可以使用 CAST 表达式的错误处理。

    https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/CAST.html#GUID-5A70235E-1209-4281-8521-B94497AAEF75

    沿着这条路:

    CASE WHEN CAST(<expression> AS NUMERIC DEFAULT NULL ON CONVERSION ERROR) IS NULL
         THEN <expression>
         ELSE TRIM(LEADING '0' FROM <expression>)
     END
    

    &lt;expression&gt; 替换为您的列名(或其他名称)。我在default null on conversion error 子句中使用null 作为魔法值,但这并没有什么害处,因为null 输入将匹配THEN 子句并通过null

    【讨论】:

    • 我使用的是 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0
    【解决方案4】:

    您可以创建一个函数来检查它是否为数字,请参阅此链接以获取函数示例,

    check if "it's a number" function in Oracle

    你可以通过给数值加0来TRIM数值的零,

    示例代码:

    --get  the IS_NUMERIC function from the link 
    
    SELECT DECODE(IS_NUMERIC(col1), 'Y', col1+0, 'N', col1) 
      FROM your_table;
    

    【讨论】:

      猜你喜欢
      • 2017-07-10
      • 2021-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-13
      • 1970-01-01
      相关资源
      最近更新 更多