create table hwsets_v4 ( id number(38), qlist CLOB, primary key(id) );
insert into hwsets_v4 values (3129, '1@2386:1@2387:1@2388:1@2389:1@2391:1@2392:1@2393:1@2394/2395;2396/2877');
insert into hwsets_v4 values (3130, '1@2664:1@2672:1@2673:1@2674:1@2675:1@2677:1@2678:1@3425:1@3426:1@3706:1@6058');
create table responses_v5 ( user_id varchar2(20), hw_id number(38), pb_id number(38), tries number(38), grade number(3,2), response CLOB, primary key(user_id, hw_id, pb_id, tries) );
insert into responses_v5 values ( 'bob', 3129, 2386, 1, 1.0, 'response1' );
insert into responses_v5 values ( 'bob', 3129, 2390, 1, 1.0, 'response2' );
insert into responses_v5 values ( 'bob', 3129, 2394, 1, 1.0, 'response3' );
insert into responses_v5 values ( 'bob', 3129, 2395, 1, 1.0, 'response4' );
insert into responses_v5 values ( 'bob', 3129, 2877, 1, 1.0, 'response5' );
insert into responses_v5 values ( 'refoyl', 3129, 2386, 1, 1.0, 'response6' );
insert into responses_v5 values ( 'refoyl', 3129, 2390, 1, 0.0, 'response7' );
insert into responses_v5 values ( 'refoyl', 3129, 2390, 2, 1.0, 'response8' );
insert into responses_v5 values ( 'refoyl', 3129, 2391, 1, 0.0, 'response9' );
insert into responses_v5 values ( 'refoyl', 3129, 2391, 2, 1.0, 'response10' );
insert into responses_v5 values ( 'refoyl', 3130, 2391, 1, 1.0, 'response11' );
insert into responses_v5 values ( 'refoyl', 3130, 2673, 1, 1.0, 'response12' );
I want to delete all rows from responses_v5 in which responses_v5.pb_id no longer appears in hwsets_v4.qlist corresponding to hwsets_v4.hw_id = responses_v5.hw_id. In the example above, that means the rows with responses 2, 7, 8, and 11.
Seems simple enough, but the simplest query that seems reasonable is not valid:
SQL> delete from responses_v5 where responses_v5.hw_id = hwsets_v4.hw_id and REGEXP_INSTR(hwsets_v4.qlist, '[@/;]' || responses_v5.pb_id || '([/;:]|$)') <= 0;
*
ERROR at line 1:
ORA-00904: "HWSETS_V4"."QLIST": invalid identifier
This works:
delete from responses_v5 where hw_id || ' ' || pb_id in (select unique responses_v5.hw_id || ' ' || responses_v5.pb_id from responses_v5, hwsets_v4 where responses_v5.hw_id = hwsets_v4.hw_id and REGEXP_INSTR(hwsets_v4.qlist, '[@/;]' || responses_v5.pb_id || '([/;:]|$)') <= 0);
but I'm sure there's a way to do it that doesn't rely on concatenation.
It would be easy if there were only one primary key in responses_v5, but the fact that there are two keys that both need to be considered, plus necessary information in a second table, is what's throwing me for a loop.
Well, a couple of methods pop into mind.
First of all - you don't need concatenation at all - when using IN or NOT IN, you can do this:
where (a,b,c) in (select d,e,f from ....)
You can use multiple columns - so instead of "where hw_id||' '||pb_id in (select esponses_v5.hw_id || ' ' || responses_v5.pb_id" - you would just code
"where (hw_id,pb_id) in (select responses_v5.hw_id, responses_v5.pb_id ..."
Note that I did not use UNIQUE, you never need the unique in that set operation, IN takes care of that - the only thing the UNIQUE could be doing it impacting runtime query performance negatively.
ops$tkyte%ORA11GR2> delete from responses_v5
2 where (hw_id, pb_id) in (select responses_v5.hw_id, responses_v5.pb_id
3 from responses_v5, hwsets_v4
4 where responses_v5.hw_id = hwsets_v4.id
5 and REGEXP_INSTR(hwsets_v4.qlist,
6 '[@/;]' || responses_v5.pb_id || '([/;:]|$)') <= 0);
4 rows deleted.
Here is another approach:
ops$tkyte%ORA11GR2> delete from responses_v5
2 where not exists (select null
3 from hwsets_v4
4 where responses_v5.hw_id = hwsets_v4.id
5 and REGEXP_INSTR(hwsets_v4.qlist, '[@/;]' || responses_v5.pb_id || '([/;:]|$)') > 0);
4 rows deleted.
Here is yet another, based on your second query attempt:
ops$tkyte%ORA11GR2> delete from
2 (select null
3 from responses_v5, hwsets_v4
4 where responses_v5.hw_id = hwsets_v4.id
5 and REGEXP_INSTR(hwsets_v4.qlist,
6 '[@/;]' || responses_v5.pb_id || '([/;:]|$)') <= 0);
4 rows deleted.
I must say, I'm not entirely thrilled with your "data model". That table hwsets_v4 goes against just about every principle involved in relational database design... In other words - that table is just plain "broke".