Sql 如何减少子字符串和指令串造成的代码重复?

Sql 如何减少子字符串和指令串造成的代码重复?,sql,oracle,plsql,oracle11g,substr,Sql,Oracle,Plsql,Oracle11g,Substr,我需要将由“\n”分隔的文本字段(描述)解析为三个单独的字段。我是通过使用substr和instr来实现这一点的,但这会导致难以读取和重复的sql。有没有办法创建并使用一个变量或表达式来保存instring函数返回的“position”值,这样我就可以将该变量传递给substr?我的代码在下面发布了函数并返回了正确的结果,但感觉不对劲。有很多重复 相关原始数据: DBKEY DBTIME DBUSER DESCRIPTION 4084

我需要将由“\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

regexp\u 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

regexp\u 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

我建议使用
REGEXP\u 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;

我已经创建并测试了一个。有关
REGEXP\u SUBSTR
的更多信息,您可能需要阅读。

我建议使用
REGEXP\u 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;

我已经创建并测试了一个。有关
REGEXP\u SUBSTR
的详细信息,您可能需要阅读。

某些RDBMS具有本机
SPLIT()
函数。您正在使用哪些RDBMS?某些RDBMS具有本机的
SPLIT()
函数。你用的是哪种RDBMS?你用oracle文档的链接把他排除在外。谢谢@timo.rieber。这正是我所需要的。我承认,但请注意,此方法假定错误代码始终为四位数,所有描述均以“平面图:”开头。谢谢@Joe。注意到了。我会考虑的。事实上,它当然可能是3、4或5位数字。对于3到5位数字,只需编写
{3、5}
,有关正则表达式的更多详细信息可以在此处找到:@timo.rieber true,但您仍有获取错误值的风险。如果指定{3,5}并显示一个两位数的错误代码,则最终可能会提取描述中的前两位数。您使用指向oracle文档的链接将其删除。谢谢@timo.rieber。这正是我所需要的。我承认,但请注意,此方法假定错误代码始终为四位数,所有描述均以“平面图:”开头。谢谢@Joe。注意到了。我会考虑的。事实上,它当然可能是3、4或5位数字。对于3到5位数字,只需编写
{3、5}
,有关正则表达式的更多详细信息可以在此处找到:@timo.rieber true,但您仍有获取错误值的风险。如果指定{3,5}并显示一个两位数的错误代码,则最终可能会提取描述中的前两位数。