我有一个查询,比如说这个
SELECT to_char(regexp_substr(q'{select * from dual minus select * from dual; select * from dual minus select * from dual;}'
, '[^;]+', 1, LEVEL)) FROM dual
CONNECT BY to_char(regexp_substr(q'{select * from dual minus select * from dual; select * from dual minus select * from dual;}', '[^;]+', 1, LEVEL)) IS NOT NULL;
它运行正常 - 分割我的行
从双减去select * from double中选择*;从双重中选择* 减去select * from dual;
分为两个
从双减去select * from double选择* 从双重中选择* 减去select * from dual
一切都很好,直到我添加一些线刹,就像这样
SELECT to_char(regexp_substr(q'{select * from dual minus select * from dual;
select * from dual minus select * from dual;}'
, '[^;]+', 1, LEVEL)) FROM dual
CONNECT BY to_char(regexp_substr(q'{select * from dual minus select * from dual;
select * from dual minus select * from dual;}', '[^;]+', 1, LEVEL)) IS NOT NULL;
这里变成了地狱:sql在字符串中处理;
,就像查询的实际结束一样,ORA-01756和东西......
如果我在;
之后添加一个随机符号,那么一切都会好起来的
SELECT to_char(regexp_substr(q'{select * from dual minus select * from dual;%
select * from dual minus select * from dual;}'
, '[^;]+', 1, LEVEL)) FROM dual
CONNECT BY to_char(regexp_substr(q'{select * from dual minus select * from dual;%
select * from dual minus select * from dual;}', '[^;]+', 1, LEVEL)) IS NOT NULL;
请解释此行为并建议解决方法。
UPD :在不同的IDE(SQL开发人员而不是PL / SQL开发人员)中尝试过此操作。没有错误。也许这就是编码...
UPD2 :在这种情况下,SQLPlus的工作方式与PL / SQL开发人员的工作方式相同。 SQL开发人员似乎有点“聪明”。不过,不知道为什么。
答案 0 :(得分:1)
尝试:
SELECT to_char(regexp_substr(q'{select * from dual minus select * from dual;
select * from dual minus select * from dual;}'
, '[^;[:cntrl:]]+', 1, LEVEL)) FROM dual
CONNECT BY to_char(regexp_substr(q'{select * from dual minus select * from dual;
select * from dual minus select * from dual;}', '[^;[:cntrl:]]+', 1, LEVEL)) IS NOT NULL;
输出:
select * from dual minus select * from dual
select * from dual minus select * from dual
原因是regexp_substr查找您指定的下一个模式,在您的情况下最初是[^;] +,此模式将找到;而下一个字符将是换行符。如果你想分解这样的行,简单的解决方案是通过[:cntrl:]
排除正则表达式搜索中的控制字符答案 1 :(得分:1)
我创建了开源项目plsql_lexer来解决这些问题。
对于复杂的SQL语句,拆分可能会变得棘手。在语句拆分后,您可能想知道如何处理它们,以及如何报告它们。 STATEMENT_CLASSIFIER.CLASSIFY和STATEMENT_FEEDBACK.GET_FEEDBACK_MESSAGE程序可以帮助完成该任务。
示例代码
以下是一些示例,从您的示例开始并添加一些其他案例。每个样本将字符串拆分为两个语句。
declare
procedure print_split_strings(p_statements nclob) is
v_split_statements nclob_table;
begin
v_split_statements := statement_splitter.split(p_statements);
for i in 1 .. v_split_statements.count loop
dbms_output.put_line('Statement '||i||': '||v_split_statements(i));
end loop;
end;
begin
--This is a simple case.
print_split_strings('select * from dual minus select * from dual; select * from dual minus select * from dual;');
--Ignore semicolons in comments.
print_split_strings('select * from dual a;/* a comment ; */ select * from dual b;');
--Ignore semicolons in strings.
print_split_strings(q'{select '''' || q'!'!' from dual a;select * from dual b;}');
--Ignore semicolons in matching BEGIN/ENDs in PLSQL_DECLARATIONS:
print_split_strings('with function f return number is begin return 1; end; function g return number is begin return 2; end; select f from dual;select 1 from dual;');
end;
/
Statement 1: select * from dual minus select * from dual;
Statement 2: select * from dual minus select * from dual;
Statement 1: select * from dual a;
Statement 2: /* a comment ; */ select * from dual b;
Statement 1: select '''' || q'!'!' from dual a;
Statement 2: select * from dual b;
Statement 1: with function f return number is begin return 1; end; function g return number is begin return 2; end; select f from dual;
Statement 2: select 1 from dual;