Sie möchten nicht dual
sehen überhaupt hier; sicherlich nicht versuchen, einzufügen. Sie müssen die höchsten und niedrigsten Werte verfolgen, die Sie beim Durchlaufen der Schleife gesehen haben. basierend auf einigen Elementen von ename
Datumsangaben darstellen Ich bin mir ziemlich sicher, dass alle Ihre Übereinstimmungen 0-9
sein sollen , nicht 1-9
. Sie beziehen sich auch auf den Cursornamen, wenn Sie auf seine Felder zugreifen, anstatt auf den Namen der Datensatzvariablen:
FOR List_ENAME_rec IN List_ENAME_cur loop
if REGEXP_LIKE(List_ENAME_rec.ENAME,'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]') then
V_seq := substr(List_ENAME_rec.ename,5,4);
V_Year := substr(List_ENAME_rec.ename,10,2);
V_Month := substr(List_ENAME_rec.ename,13,2);
V_day := substr(List_ENAME_rec.ename,16,2);
if min_seq is null or V_seq < min_seq then
min_seq := v_seq;
end if;
if max_seq is null or V_seq > max_seq then
max_seq := v_seq;
end if;
end if;
end loop;
Mit Werten in der Tabelle von emp-1111_14_01_01_1111_G1
und emp-1115_14_02_02_1111_G1
, das max_seq 1115 min_seq 1111
meldet .
Wenn Sie dual verwenden möchten, können Sie dies innerhalb der Schleife anstelle des if/then/assign-Musters tun, aber es ist nicht notwendig:
select least(min_seq, v_seq), greatest(max_seq, v_seq)
into min_seq, max_seq
from dual;
Ich habe keine Ahnung, was das Verfahren bewirken wird; Es scheint keine Beziehung zwischen dem zu geben, was Sie in test1
haben und die Werte, die Sie finden.
Sie benötigen dafür jedoch kein PL/SQL. Sie können die Min/Max-Werte aus einer einfachen Abfrage erhalten:
select min(to_number(substr(ename, 5, 4))) as min_seq,
max(to_number(substr(ename, 5, 4))) as max_seq
from table1
where status = 2
and regexp_like(ename,
'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')
MIN_SEQ MAX_SEQ
---------- ----------
1111 1115
Und Sie können diese verwenden, um eine Liste aller Werte in diesem Bereich zu erstellen:
with t as (
select min(to_number(substr(ename, 5, 4))) as min_seq,
max(to_number(substr(ename, 5, 4))) as max_seq
from table1
where status = 2
and regexp_like(ename,
'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')
)
select min_seq + level - 1 as seq
from t
connect by level <= (max_seq - min_seq) + 1;
SEQ
----------
1111
1112
1113
1114
1115
Und ein etwas anderer allgemeiner Tabellenausdruck, um zu sehen, welche davon nicht in Ihrer Tabelle vorhanden sind, was meiner Meinung nach das ist, wonach Sie suchen:
with t as (
select to_number(substr(ename, 5, 4)) as seq
from table1
where status = 2
and regexp_like(ename,
'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')
),
u as (
select min(seq) as min_seq,
max(seq) as max_seq
from t
),
v as (
select min_seq + level - 1 as seq
from u
connect by level <= (max_seq - min_seq) + 1
)
select v.seq as missing_seq
from v
left join t on t.seq = v.seq
where t.seq is null
order by v.seq;
MISSING_SEQ
-----------
1112
1113
1114
oder wenn Sie es vorziehen:
...
select v.seq as missing_seq
from v
where not exists (select 1 from t where t.seq = v.seq)
order by v.seq;
Basierend auf Kommentaren denke ich, dass Sie die fehlenden Werte für die Sequenz für jede Kombination der anderen Elemente der ID (YY_MM_DD) wünschen. Dadurch erhalten Sie diese Aufschlüsselung:
with t as (
select to_number(substr(ename, 5, 4)) as seq,
substr(ename, 10, 2) as yy,
substr(ename, 13, 2) as mm,
substr(ename, 16, 2) as dd
from table1
where status = 2
and regexp_like(ename,
'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')
),
r (yy, mm, dd, seq, max_seq) as (
select yy, mm, dd, min(seq), max(seq)
from t
group by yy, mm, dd
union all
select yy, mm, dd, seq + 1, max_seq
from r
where seq + 1 <= max_seq
)
select yy, mm, dd, seq as missing_seq
from r
where not exists (
select 1 from t
where t.yy = r.yy
and t.mm = r.mm
and t.dd = r.dd
and t.seq = r.seq
)
order by yy, mm, dd, seq;
Mit Ausgabe wie:
YY MM DD MISSING_SEQ
---- ---- ---- -------------
14 01 01 1112
14 01 01 1113
14 01 01 1114
14 02 02 1118
14 02 02 1120
14 02 03 1127
14 02 03 1128
Wenn Sie nach einem bestimmten Datum suchen möchten, können Sie dieses kalt filtern (entweder in t
, oder die erste Verzweigung in r
), aber Sie könnten das Regex-Muster auch so ändern, dass es die festen Werte enthält; Suchen Sie also nach 14 06
das Muster wäre 'emp[-][0-9]{4}_14_06_[0-9]{2}[_][0-9]{4}[_][G][1]'
, zum Beispiel. Das ist jedoch schwieriger zu verallgemeinern, also ein Filter (where t.yy = '14' and t.mm = '06'
könnte flexibler sein.
Wenn Sie darauf bestehen, dies in einer Prozedur zu haben, können Sie die Datumselemente optional machen und das Regex-Muster ändern:
create or replace procedure show_missing_seqs(yy in varchar2 default '[0-9]{2}',
mm in varchar2 default '[0-9]{2}', dd in varchar2 default '[0-9]{2}') as
pattern varchar2(80);
cursor cur (pattern varchar2) is
with t as (
select to_number(substr(ename, 5, 4)) as seq,
substr(ename, 10, 2) as yy,
substr(ename, 13, 2) as mm,
substr(ename, 16, 2) as dd
from table1
where status = 2
and regexp_like(ename, pattern)
),
r (yy, mm, dd, seq, max_seq) as (
select yy, mm, dd, min(seq), max(seq)
from t
group by yy, mm, dd
union all
select yy, mm, dd, seq + 1, max_seq
from r
where seq + 1 <= max_seq
)
select yy, mm, dd, seq as missing_seq
from r
where not exists (
select 1 from t
where t.yy = r.yy
and t.mm = r.mm
and t.dd = r.dd
and t.seq = r.seq
)
order by yy, mm, dd, seq;
begin
pattern := 'emp[-][0-9]{4}[_]'
|| yy || '[_]' || mm || '[_]' || dd
|| '[_][0-9]{4}[_][G][1]';
for rec in cur(pattern) loop
dbms_output.put_line(to_char(rec.missing_seq, 'FM0000'));
end loop;
end show_missing_seqs;
/
Ich weiß nicht, warum Sie darauf bestehen, dass es so gemacht werden muss oder warum Sie dbms_output
verwenden möchten da Sie sich darauf verlassen, dass der Client / Anrufer dies anzeigt; Was wird Ihr Job mit dem Output machen? Sie könnten dafür sorgen, dass dies einen sys_refcursor
zurückgibt was flexibler wäre. aber wie auch immer, Sie können es von SQL*Plus/SQL Developer so aufrufen:
set serveroutput on
exec show_missing_seqs(yy => '14', mm => '01');
anonymous block completed
1112
1113
1114