You Asked
Hi,
I am facing a weird problem in which a merge statement using dynamic sql is failing with the below error while the static merge statement is suceeding.
Error:
ORA-00904: : invalid identifier
ORA-06512: at line 60
Below is the logic I am trying to accomplish. The inner query in the USING clause is much more complex than shown here. I have provided this simplified example to convey my point.
Code Snippet:
create table src_tab (seq_id number, delim_col varchar2(200));
create table dest_tab (seq_id number, date_col date, num_col1 number, num_col2 number, num_col3 number);
insert into src_tab values (1, '10-OCT-16~247071961109~247071936109~10024707193122');
insert into dest_tab values (2, '10-OCT-16', 247071961109, 247071936109, 10024707193122);
This is working:
merge into dest_tab dest
using
(select seq_id,
REGEXP_SUBSTR(a.delim_col, '[^~]+',1,1) AS date_col,
REGEXP_SUBSTR(a.delim_col, '[^~]+',1,2) AS num_col1,
REGEXP_SUBSTR(a.delim_col, '[^~]+',1,3) AS num_col2,
REGEXP_SUBSTR(a.delim_col, '[^~]+',1,4) AS num_col3
from src_tab a where seq_id = 1
) src_tab
on (dest.date_col = src.date_col
and dest.num_col1 = src.num_col1
and dest.num_col2 = src.num_col2
and dest.num_col3 = src.num_col3)
when matched then update set dest.seq_id = src.seq_id
where dest.date_col = src.date_col
and dest.num_col1 = src.num_col1
and dest.num_col2 = src.num_col2
and dest.num_col3 = src.num_col3;
This is not working:
declare
l_seq_id number := 1;
l_sql clob;
begin
l_sql := ' merge into dest_tab dest
using
(select seq_id,
REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,1) AS date_col,
REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,2) AS num_col1,
REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,3) AS num_col2,
REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,4) AS num_col3
from src_tab a where seq_id = :1
) src_tab
on (dest.date_col = src.date_col
and dest.num_col1 = src.num_col1
and dest.num_col2 = src.num_col2
and dest.num_col3 = src.num_col3)
when matched then update set dest.seq_id = src.seq_id
where dest.date_col = src.date_col
and dest.num_col1 = src.num_col1
and dest.num_col2 = src.num_col2
and dest.num_col3 = src.num_col3';
execute immediate l_sql using l_seq_id;
for x in (select plan_table_output from table (dbms_xplan.display_cursor))
loop
dbms_output.put_line ( x.PLAN_TABLE_OUTPUT );
end loop;
end;
Few important points
In the explain plan I see few things.
"DEST"."DATE_COL"=INTERNAL_FUNCTION("from$subquery$_018"."DATE_COL") AND
"DEST"."NUM_COL1"=TO_NUMBER("from$subquery$_018"."NUM_COL1") AND
"DEST"."NUM_COL2"=TO_NUMBER("from$subquery$_018"."NUM_COL2") AND
"DEST"."NUM_COL3"=TO_NUMBER("from$subquery$_018"."NUM_COL3") AND
and Connor said...
I beg to differ with your assessment :-)
SQL> drop table src_tab purge;
Table dropped.
SQL> drop table dest_tab purge;
Table dropped.
SQL> create table src_tab (seq_id number, delim_col varchar2(200));
Table created.
SQL> create table dest_tab (seq_id number, date_col date, num_col1 number, num_col2 number, num_col3 number);
Table created.
SQL> insert into src_tab values (1, '10-OCT-16~247071961109~247071936109~10024707193122');
1 row created.
SQL> insert into dest_tab values (2, '10-OCT-16', 247071961109, 247071936109, 10024707193122);
1 row created.
SQL>
SQL>
SQL> merge into dest_tab dest
2 using
3 (select seq_id,
4 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,1) AS date_col,
5 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,2) AS num_col1,
6 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,3) AS num_col2,
7 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,4) AS num_col3
8 from src_tab a where seq_id = 1
9 ) src_tab
10 on (dest.date_col = src.date_col
11 and dest.num_col1 = src.num_col1
12 and dest.num_col2 = src.num_col2
13 and dest.num_col3 = src.num_col3)
14 when matched then update set dest.seq_id = src.seq_id
15 where dest.date_col = src.date_col
16 and dest.num_col1 = src.num_col1
17 and dest.num_col2 = src.num_col2
18 and dest.num_col3 = src.num_col3;
and dest.num_col3 = src.num_col3)
*
ERROR at line 13:
ORA-00904: "SRC"."NUM_COL3": invalid identifier
SQL>
SQL>
SQL> declare
2 l_seq_id number := 1;
3 l_sql clob;
4 begin
5 l_sql := ' merge into dest_tab dest
6 using
7 (select seq_id,
8 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,1) AS date_col,
9 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,2) AS num_col1,
10 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,3) AS num_col2,
11 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,4) AS num_col3
12 from src_tab a where seq_id = :1
13 ) src_tab
14 on (dest.date_col = src.date_col
15 and dest.num_col1 = src.num_col1
16 and dest.num_col2 = src.num_col2
17 and dest.num_col3 = src.num_col3)
18 when matched then update set dest.seq_id = src.seq_id
19 where dest.date_col = src.date_col
20 and dest.num_col1 = src.num_col1
21 and dest.num_col2 = src.num_col2
22 and dest.num_col3 = src.num_col3';
23
24 execute immediate l_sql using l_seq_id;
25
26 end;
27 /
declare
*
ERROR at line 1:
ORA-00904: "SRC"."NUM_COL3": invalid identifier
ORA-06512: at line 24
Both dont work because of a syntax error. If I alter the merge (ie, correct the alias), then now they both work
SQL>
SQL>
SQL> merge into dest_tab dest
2 using
3 (select seq_id,
4 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,1) AS date_col,
5 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,2) AS num_col1,
6 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,3) AS num_col2,
7 REGEXP_SUBSTR(a.delim_col, '[^~]+',1,4) AS num_col3
8 from src_tab a where seq_id = 1
9 ) src
10 on (dest.date_col = src.date_col
11 and dest.num_col1 = src.num_col1
12 and dest.num_col2 = src.num_col2
13 and dest.num_col3 = src.num_col3)
14 when matched then update set dest.seq_id = src.seq_id
15 where dest.date_col = src.date_col
16 and dest.num_col1 = src.num_col1
17 and dest.num_col2 = src.num_col2
18 and dest.num_col3 = src.num_col3;
1 row merged.
SQL>
SQL>
SQL> declare
2 l_seq_id number := 1;
3 l_sql clob;
4 begin
5 l_sql := ' merge into dest_tab dest
6 using
7 (select seq_id,
8 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,1) AS date_col,
9 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,2) AS num_col1,
10 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,3) AS num_col2,
11 REGEXP_SUBSTR(a.delim_col, ''[^~]+'',1,4) AS num_col3
12 from src_tab a where seq_id = :1
13 ) src
14 on (dest.date_col = src.date_col
15 and dest.num_col1 = src.num_col1
16 and dest.num_col2 = src.num_col2
17 and dest.num_col3 = src.num_col3)
18 when matched then update set dest.seq_id = src.seq_id
19 where dest.date_col = src.date_col
20 and dest.num_col1 = src.num_col1
21 and dest.num_col2 = src.num_col2
22 and dest.num_col3 = src.num_col3';
23
24 execute immediate l_sql using l_seq_id;
25
26 end;
27 /
PL/SQL procedure successfully completed.
SQL>
SQL>
Rating
(1 rating)
Is this answer out of date? If it is, please let us know via a Comment