我需要将由'\ n'分隔的文本字段(描述)解析为三个单独的字段。我是通过利用substr
和instr
来做到这一点的,但这会导致难以阅读和重复的SQL。有没有办法创建和使用变量或表达式来保存instring函数返回的“position”值,所以我可以将该变量传递给substr
?我的代码发布在下面的函数并返回正确的结果,但感觉不对。有很多重复。
相关原始数据:
DBKEY DBTIME DBUSER DESCRIPTION
40846809 2013-11-18 11:04:11.0000000 abc$userid The following Message List entry has been logged:\nError Number:5011\nDescription:Planogram: 60E90001006.0SMA :: UPC: is not numeric\nSeverity:0
40846810 2013-11-18 11:04:11.0000000 abc$userid The following Message List entry has been logged:\nError Number:5000\nDescription:Planogram: 60E90001006.0SMA :: ID: NEW not 9 digits\nSeverity:0
40846811 2013-11-18 11:04:11.0000000 abc$userid The following Message List entry has been logged:\nError Number:5001\nDescription:Planogram: 60E90001006.0SMA :: ID: NEW not numeric\nSeverity:0
期望的结果:
DBKEY DBTIME USERID ERROR_NUM DESCRIPTION SEVERITY
40846809 2013-11-18 11:04:11.0000000 userid 5011 Planogram: 60E90001006.0SMA :: UPC: is not numeric 0
40846810 2013-11-18 11:04:11.0000000 userid 5000 Planogram: 60E90001006.0SMA :: ID: NEW not 9 digits 0
40846811 2013-11-18 11:04:11.0000000 userid 5001 Planogram: 60E90001006.0SMA :: ID: NEW not numeric 0
40846812 2013-11-18 11:04:11.0000000 userid 5003 Planogram: 60E90001006.0SMA :: ID: NEW ID must begin with 000,200,220,900,950,990,or 999 0
当前代码:
SELECT DBKEY,DBTIME,
SUBSTR(DBUSER,INSTR(DBUSER,'$',1,1)+1) AS USERID,
SUBSTR(ERROR_NUM,INSTR(ERROR_NUM,':')+1) AS ERROR_NUM,
SUBSTR(DESC1,INSTR(DESC1,':')+1) AS DESCRIPTION,
SUBSTR(SEVERITY,INSTR(SEVERITY,':')+1) AS SEVERITY
FROM(
SELECT l.DBKEY,DBTIME,DBUSER,
--substring(description,first+2,second-first-2)
SUBSTR(DESCRIPTION,INSTR(DESCRIPTION,'\n',1,1)+2,INSTR(DESCRIPTION,'\n',1,2)-INSTR(DESCRIPTION,'\n',1,1)-2) AS ERROR_NUM,
--substring(description,second+2,third-second-2)
SUBSTR(DESCRIPTION,INSTR(DESCRIPTION,'\n',1,2)+2,INSTR(DESCRIPTION,'\n',1,3)-INSTR(DESCRIPTION,'\n',1,2)-2) AS DESC1,
--substring(description,third+2)
SUBSTR(DESCRIPTION,INSTR(DESCRIPTION,'\n',1,3)+2) AS SEVERITY
/*,
INSTR(DESCRIPTION,''\n'',1,1) as first,
INSTR(DESCRIPTION,''\n'',1,2) as second,
INSTR(DESCRIPTION,''\n'',1,3) as third,
*/
FROM EVENT_LOG l
)derivedtbl
答案 0 :(得分:3)
regexp_replace会这样做:
select
dbkey,
dbtime,
REGEXP_REPLACE(dbuser,'^.*\$','',1,1) dbuser,
REGEXP_REPLACE(description, '.*Error Number:([0-9]+).*','\1',1,1) error_num,
REGEXP_REPLACE(description, '.*Description:(.+)\\n.*','\1',1,1) description,
REGEXP_REPLACE(description, '.*Severity:(.+)','\1',1,1) severity
from rawdata;
结果
DBKEY DBTIME DBUSER ERROR_NUM DESCRIPTION SEVERITY
40846809 2013-11-18 11:04:11.0000000 userid 5011 Planogram: 60E90001006.0SMA :: UPC: is not numeric 0
40846810 2013-11-18 11:04:11.0000000 userid 5000 Planogram: 60E90001006.0SMA :: ID: NEW not 9 digits 0
40846811 2013-11-18 11:04:11.0000000 userid 5001 Planogram: 60E90001006.0SMA :: ID: NEW not numeric 0
答案 1 :(得分:3)
我建议使用REGEXP_SUBSTR
,这是实现预期效果的绝佳功能:
SELECT
l.DBKEY,
l.DBTIME,
REGEXP_SUBSTR(l.DBUSER, '[^$]+$') AS USERID,
REGEXP_SUBSTR(l.DESCRIPTION, '[0-9]{4}') AS ERROR_NUM,
REPLACE(REGEXP_SUBSTR(l.DESCRIPTION, 'Planogram:[^\]+\\n'), '\n', '')
AS DESCRIPTION,
REGEXP_SUBSTR(l.DESCRIPTION, '\d+$') AS SEVERITY
FROM
EVENT_LOG l;
我创建并测试了SQLFiddle。有关REGEXP_SUBSTR
的详细信息,您可能需要阅读Oracle Docs。