如何绕过ORA-01722

时间:2012-08-25 08:05:41

标签: sql oracle

是否有解决方法/更好的方法来执行此操作:

我有一个字段(TEREMARKS),其中包含一个长字符串,在该字符串中我需要获取我可以在那里找到的时间和名称。当我遇到这种格式时,我会提取时间和名称: TE=<HH:MM>(<NAME>)

我的问题是有时格式化的编码器不会抛出ORA-01722。我本来希望我的程序跳过错误的记录并返回那些没问题的记录。这可能吗?以下是脚本:

创建表格

CREATE TABLE HPACC.TE_ENTRY
(
  TENUMBER    VARCHAR2(20 BYTE)                 NOT NULL,
  TEREMARKS   VARCHAR2(100 BYTE),
  TEUPDATEBY  VARCHAR2(15 BYTE),
  TETRXDT     DATE
);

插入数据:

Insert into HPACC.TE_ENTRY (TENUMBER, TEREMARKS, TEUPDATEBY, TETRXDT)
Values ('115118002', 'TE=10:03 CU ANTI SEIZZURE ', 'ME1', TO_DATE('08/24/2012 10:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into HPACC.TE_ENTRY (TENUMBER, TEREMARKS, TEUPDATEBY, TETRXDT)
Values ('1151180025 ', 'TE= 10:19 ON AND OFF FEVER', 'ME2', TO_DATE('08/24/2012 10:01:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into HPACC.TE_ENTRY (TENUMBER, TEREMARKS, TEUPDATEBY, TETRXDT)
Values ('1153053592', 'TE=10:40(DIANE)   PRE''EMP', 'ME1', TO_DATE('08/24/2012 10:05:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into HPACC.TE_ENTRY (TENUMBER, TEREMARKS, TEUPDATEBY, TETRXDT)
Values ('1157019820', 'TE=10:45(KRISTEN), CU,MONITORING,RASHE,FEVER LAST MONDAY  ', 'ME1', TO_DATE('08/24/2012 10:12:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into HPACC.TE_ENTRY (TENUMBER, TEREMARKS, TEUPDATEBY, TETRXDT)
Values ('1157019832', 'TE=11-:13 PRE EMP EXTRACTED BY:CAMILLA', 'ME3', TO_DATE('08/24/2012 10:15:00', 'MM/DD/YYYY HH24:MI:SS'));

我的查询:

SELECT TO_CHAR(DECODE(ORIGTIME, '1', '13','2', '14','3', '15','4', '16',ORIGTIME),'FM00') ATIME
      , DONEBY
      , COUNT(TENUMBER) AS CTOTAL 
FROM ( 
SELECT TENUMBER
        , (CASE WHEN (INSTR(UPPER(TEREMARKS),'TE=',1,1) <> 0) 
                  AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,1)+3,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,1)),':',1,1))-4)
   , ' +-.0123456789', ' '))) IS  NULL) 
     THEN TO_NUMBER(REPLACE(TO_CHAR(TO_NUMBER(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,1)+3,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,1)),':',1,1))-4)),'FM99'),'-')) 
   ELSE 0 END) AS ORIGTIME
 , (CASE WHEN (INSTR(UPPER(TEREMARKS),'(',1,1) <> 0) 
    AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,1)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,1)+1),')',1,1))-1), ' +-.0123456789', ' '))) IS NULL) 
   THEN SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,1)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,1)+1),')',1,1))-1) 
  ELSE TEUPDATEBY END) AS DONEBY 
FROM HPACC.TE_ENTRY 
  Where TETRXDT BETWEEN TO_DATE('08-24-2012 10:00:00','MM-DD-YYYY HH24:MI:SS') AND TO_DATE('08-24-2012 10:59:59','MM-DD-YYYY HH24:MI:SS') 
GROUP BY TENUMBER, TEREMARKS, TEUPDATEBY 
UNION
SELECT TENUMBER
    , (CASE WHEN (INSTR(UPPER(TEREMARKS),'TE=',1,2) <> 0) 
     AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,2)+3,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,2)),':',1,1))-4), ' +-.0123456789', ' '))) IS NULL) 
      THEN TO_NUMBER(REPLACE(TO_CHAR(TO_NUMBER(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,2)+3,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,2)),':',1,1))-4)),'FM99'),'-'))
   ELSE 0 END) AS ORIGTIME
 ,  (CASE WHEN (INSTR(UPPER(TEREMARKS),'(',1,2) <> 0) 
     AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,2)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,2)+1),')',1,1))-1), ' +-.0123456789', ' '))) IS NULL) 
 THEN SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,2)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,2)+1),')',1,1))-1) 
Else 'NONE' END) AS DONEBY 
FROM HPACC.TE_ENTRY 
Where TETRXDT BETWEEN TO_DATE('08-24-2012 10:00:00','MM-DD-YYYY HH24:MI:SS') AND TO_DATE('08-24-2012 10:59:59','MM-DD-YYYY HH24:MI:SS') 
GROUP BY TENUMBER, TEREMARKS 
UNION  
SELECT TENUMBER
     , (CASE WHEN (INSTR(UPPER(TEREMARKS),'TE=',1,3) <> 0)
 AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,3)+3, (INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,3)),':',1,1))-4), ' +-.0123456789', ' '))) IS NULL) 
THEN TO_NUMBER(REPLACE(TO_CHAR(TO_NUMBER(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,3)+3, (INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,3)),':',1,1))-4)),'FM99'),'-')) 
ELSE 0 END) AS ORIGTIME
, (CASE WHEN (INSTR(UPPER(TEREMARKS),'(',1,3) <> 0) 
  AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,3)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,3)+1),')',1,1))-1), ' +-.0123456789', ' '))) IS NULL) 
THEN SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,3)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,3)+1),')',1,1))-1) 
Else 'NONE' END) AS DONEBY 
FROM HPACC.TE_ENTRY 
Where TETRXDT BETWEEN TO_DATE('08-24-2012 10:00:00','MM-DD-YYYY HH24:MI:SS') AND TO_DATE('08-24-2012 10:59:59','MM-DD-YYYY HH24:MI:SS') GROUP BY TENUMBER, TEREMARKS 
UNION 
SELECT TENUMBER
 , (CASE WHEN (INSTR(UPPER(TEREMARKS),'TE=',1,4) <> 0) 
 AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,4)+3, (INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,4)),':',1,1))-4), ' +-.0123456789', ' '))) IS NULL) 
 THEN TO_NUMBER(REPLACE(TO_CHAR(TO_NUMBER(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,4)+3, (INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,4)),':',1,1))-4)),'FM99'),'-')) 
ELSE 0 END) AS ORIGTIME, 
(CASE WHEN (INSTR(UPPER(TEREMARKS),'(',1,4) <> 0)
 AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,4)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,4)+1),')',1,1))-1), ' +-.0123456789', ' '))) IS NULL) 
 THEN SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,4)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,4)+1),')',1,1))-1) 
Else 'NONE' END) AS DONEBY 
FROM HPACC.TE_ENTRY
Where TETRXDT BETWEEN TO_DATE('08-24-2012 10:00:00','MM-DD-YYYY HH24:MI:SS') AND TO_DATE('08-24-2012 10:59:59','MM-DD-YYYY HH24:MI:SS')
GROUP BY TENUMBER, TEREMARKS 
UNION 
SELECT TENUMBER
, (CASE WHEN (INSTR(UPPER(TEREMARKS),'TE=',1,5) <> 0) 
AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,5)+3,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,5)),':',1,1))-4), ' +-.0123456789', ' '))) IS NULL) 
 THEN TO_NUMBER(REPLACE(TO_CHAR(TO_NUMBER(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,5)+3,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'TE=',1,5)),':',1,1))-4)),'FM99'),'-'))
 ELSE 0 END) AS ORIGTIME
, (CASE WHEN (INSTR(UPPER(TEREMARKS),'(',1,5) <> 0) AND (LENGTH(TRIM(TRANSLATE(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,5)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,5)+1),')',1,1))-1), ' +-.0123456789', ' '))) IS NULL) 
THEN 
 SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,5)+1,(INSTR(SUBSTR(TEREMARKS,INSTR(UPPER(TEREMARKS),'(',1,5)+1),')',1,1))-1) 
   Else 'NONE' END) AS DONEBY
FROM HPACC.TE_ENTRY Where TETRXDT BETWEEN TO_DATE('08-24-2012 10:00:00','MM-DD-YYYY HH24:MI:SS') AND TO_DATE('08-24-2012 10:59:59','MM-DD-YYYY HH24:MI:SS') 
GROUP BY TENUMBER, TEREMARKS
) 
Where ORIGTIME <> 0 
Group By ORIGTIME, DONEBY 
Order By TO_CHAR(TO_NUMBER(ATIME),'FM00') , DONEBY;

最后一条记录(10:15)导致错误。如何绕过那一个? 我也觉得我的剧本太冗长了。非常感谢您的更正,建议和示例。谢谢!

1 个答案:

答案 0 :(得分:6)

正如Alex所说,这显然是正则表达式的任务。

以下是适用于当前数据的内容。

select regexp_substr( teremarks
                   , '^TE=[[:space:]]?[[:digit:]]{2}[[:print:]]?:[[:digit:]]{2}')
     , regexp_substr( teremarks
                   , '([(][[:alpha:]]+[)]|:[[:alpha:]]+$)')
from te_entry

这匹配从字符串的开头TE,后跟=,然后是可选空格,两个数字是可选字符:,然后是另外两个数字。< / p>

秒数匹配(后跟任意数量的字母,后跟),或:后跟任意数量的字母。

或者,为了获得时间和名称,删除所有额外的东西:

with matched as (
 select regexp_substr( teremarks
                    , '^TE=[[:space:]]?[[:digit:]]{2}[[:print:]]?:[[:digit:]]{2}'
                       ) as time
      , regexp_substr( teremarks
                    , '([(][[:alpha:]]+[)]|:[[:alpha:]]+$)'
                        ) as name
   from te_entry
        )
select regexp_replace( time
                    , '[^([:digit:]|:)]')
     , regexp_replace( name
                    , '[^[:alpha:]]')
from matched

这是a SQL Fiddle to demonstrate。另请注意,正则表达式仅适用于Oracle 10g或更高版本。

我只想强调,虽然这会对您的当前数据起作用,但这并不意味着它将永远有效。总会有更多你没想过的案例。如果此查询的结果很重要,则应更改表格以包含具有日期(不是时间)测量值的列以及具有接收测量值的人员姓名的另一列。 / p>

这是唯一的方式,您可以确定您的数据是正确的。