Sql 将文本拆分为具有只读权限的表行
我是数据库的只读用户,存在以下问题: 情景: 一家公司的呼叫中心员工代表我们的客户通过我们的数据库向我提交票据。呼叫中心在信息中包含精确长度的字母数字批号,以便我进行故障排除。根据票证的更新次数,一张票证可能会有多条消息,每条消息中嵌入了零个或多个字母数字批号。我可以使用Oracle SQL和SQL工具访问所有这些消息 如何仅提取批号以生成包含所有给定批号的单列表 示例数据: 到目前为止: 我可以用下面的代码隔离常量字符串的批号,但它会被放入标准输出,而不是表格格式Sql 将文本拆分为具有只读权限的表行,sql,string,oracle,parsing,Sql,String,Oracle,Parsing,我是数据库的只读用户,存在以下问题: 情景: 一家公司的呼叫中心员工代表我们的客户通过我们的数据库向我提交票据。呼叫中心在信息中包含精确长度的字母数字批号,以便我进行故障排除。根据票证的更新次数,一张票证可能会有多条消息,每条消息中嵌入了零个或多个字母数字批号。我可以使用Oracle SQL和SQL工具访问所有这些消息 如何仅提取批号以生成包含所有给定批号的单列表 示例数据: 到目前为止: 我可以用下面的代码隔离常量字符串的批号,但它会被放入标准输出,而不是表格格式 DECLARE msg
DECLARE
msg VARCHAR2(200) := 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.';
cnt NUMBER := regexp_count(msg, '[[:alnum:]]{10}');
BEGIN
IF cnt > 0 THEN
FOR i IN 1..cnt LOOP
Dbms_Output.put_line(regexp_substr(msg, '[[:alnum:]]{10}', 1, i));
END LOOP;
END IF;
END;
/
目标:
将结果输出到一个表中,该表本身可以用作较大查询语句中的表。
以某种方式,您可以将其应用于与原始票证关联的所有消息。
更新:将示例批号从8个字符改为10个字符,以避免与消息中的真实文字混淆。现实世界中的场景有更长的代码和非常特定的格式,因此将使用更复杂的正则表达式
更新2:尝试使用表变量而不是标准输出。它没有出错,但没有填充我的查询选项卡。。。这可能只是用户错误
DECLARE
TYPE lot_type IS TABLE OF VARCHAR2(10);
lots lot_type := lot_type();
msg VARCHAR2(200) := 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.';
cnt NUMBER := regexp_count(msg, '[[:alnum:]]{10}');
BEGIN
IF cnt > 0 THEN
FOR i IN 1..cnt LOOP
lots.extend();
lots(i) := regexp_substr(msg, '[[:alnum:]]{10}', 1, i);
END LOOP;
END IF;
END;
/
这是一种正则表达式格式,与您提供的批掩码匹配:'[a-z]{3}[0-9]{5}'。使用这样的方法可以帮助你避免问题中提到的误报 现在为您提供一个只读的纯SQL解决方案
with cte as (
select 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.' msg
from dual)
select regexp_substr(msg, '[a-z]{3}[0-9]{5}', 1, level) as lotno
from cte
connect by level <= regexp_count(msg, '[a-z]{3}[0-9]{5}')
;
我使用WITH子句只是为了生成数据。重要的是使用CONNECT BY操作符,这是Oracle分层数据语法的一部分,但这里从一行生成一个表。伪列级别允许我们遍历字符串并选择不同的正则表达式模式
以下是输出:
SQL> r
1 with cte as ( select 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.' msg from dual)
2 select regexp_substr(msg, '[a-z]{3}[0-9]{5}', 1, level) as lotno
3 from cte
4 connect by level <= regexp_count(msg, '[a-z]{3}[0-9]{5}')
5*
LOTNO
----------
xyz23456
zyx12345
SQL>
您可以使用流水线表函数来实现这一点,但这是您需要在db中创建的对象,因此如果有人不允许您这样做,它将无法工作。仅供参考,示例中的计数返回3。能否将所需的结果集输出到表变量中?@OldProgrammer-huh,因此它确实返回3。。。现实世界中的情况是超过15个字符,而且更加具体,但我要补充一点。谢谢你抓住了@纳特安德森-可能,我现在正在调查。由于我无法插入任何内容,我一直在研究如何将搜索数据添加到表中。谢谢,这一点解释得很好!我将在星期一再次访问数据库时尝试它。需要稍微修改以删除奇怪的重复条目,但它可以工作!很高兴听到这个消息。我确实说过,您可能会对使用Oracle SQL可以做多少事情感到惊讶。
SQL> r
1 with cte as ( select 'Same customer found lots xyz23456 and zyx12345 in their storage as well and would like those checked.' msg from dual)
2 select regexp_substr(msg, '[a-z]{3}[0-9]{5}', 1, level) as lotno
3 from cte
4 connect by level <= regexp_count(msg, '[a-z]{3}[0-9]{5}')
5*
LOTNO
----------
xyz23456
zyx12345
SQL>