I have a table foo
:
CREATE TABLE foo (
bar NUMBER NOT NULL,
value VARCHAR2(10) NOT NULL
)
Now, in a PL/SQL procedure, I want to change the list of values for a specific value for bar
so that it contains exactly those returned from a rather complicated select query:
SELECT * FROM (
SELECT
x bar,
regexp_substr(y,'[^ ]+', 1, level) value
FROM dual
CONNECT BY regexp_substr(y, '[^ ]+', 1, level) IS NOT NULL
) WHERE TRIM(value) IS NOT NULL;
This means I have to (1) delete all rows not returned by that query, and (2) insert all rows from that query that are not already in foo
. So for instance if foo
contains this,
1 A
2 A
2 B
2 C
the variable x
is 2
and the query above returns this (as y
is C D
)
2 C
2 D
I would like to end up with a table foo
like this:
1 A
2 C
2 D
Currently I do this by first deleting all rows where bar = x
and then inserting all the rows from the query:
DELETE FROM foo WHERE bar = x;
INSERT INTO foo
SELECT * FROM /* the full query edited out for compactness */;
The problem is that this messes up my revision control system since I often delete rows and then directly afterwards insert the exact same row again. Is there any way to do this without deleting the rows that will be inserted again? I would prefer to only type the query once, since it is rather long.
答案 0 :(得分:1)
插入/删除foo和foo的新值之间的区别怎么样?
delete foo ff
where exists(with c_query as (
-- result of your complex query
select 2 as bar, 'C' as value
from dual
union all
select 2 as bar, 'D' as value from dual)
-- delete foo not in c_query
(select f.bar, f.value
from foo f
where f.bar = (select distinct bar from c_query)
and ff.bar = f.bar
and ff.value = f.value
minus
select d.bar, d.value from c_query d));
insert into foo
with c_query as
( -- result of your complex query
select 2 as bar, 'C' as value
from dual
union all
select 2 as bar, 'D' as value from dual)
-- insert c_query data not in foo
(select d.bar, d.value
from c_query d
minus
select f.bar, f.value from foo f);