Execute Immediate in oracle - oracle

I have below query which gives an error as encounter an symbol ( in the line where loop is used. I am trying to develop a function which takes dynamic paramater as table_name,column_name,table_id and used for other tables as well.
FUNCTION get_encryp_pass( table_name IN varchar2,column_name IN varchar2,table_id IN varchar2) RETURN VARCHAR2
IS
BEGIN
EXECUTE IMMEDIATE 'for c1 in (select * from' || table_name ||) loop
EXECUTE IMMEDIATE 'update ' || table_name || ' set ' || column_name = encrypt_val(c1.column_name) || ' where ' || table_id || ' = ' || c1.table_id and column_name is not null;
end loop;
END get_encrypt_pass;

this should work:
CREATE PROCEDURE get_encryp_pass(table_name IN varchar2,
column_name IN varchar2,
table_id IN varchar2) IS
BEGIN
EXECUTE IMMEDIATE 'begin for c1 in (select * from ' || table_name ||
') loop update ' || table_name || ' set ' ||
column_name || ' = encrypt_val(c1.' || column_name ||
') where ' || table_id || ' = c1.'||table_id||' and ' || column_name ||
' is not null; end loop; end;'
;
END;
But why not simply call update FTP_SFTP_SERVER set PASSWORD=encrypt_val(PASSWORD) where PASSWORD is not null ?

keep care of what is a variable and what is a string-literal and must be single-quoted therefore ... and string-variables mus be double-quoted:
EXECUTE IMMEDIATE 'update ' || table_name || ' set ' || column_name || ' = ''' || encrypt_val(c1.column_name) || ''' where ' || table_id || ' = ' || c1.table_id || ' and column_name is not null';
Best practice is to concatenate the statement in a varchar2-variable first and inspect this. If the content of the variable is syntactical correct and executable, the EXECUTE IMMEDIATE should work as well
declare
stmt varchar2(4000);
begin
stmt := 'update ' || table_name || ' set ' || column_name || ' = ''' || encrypt_val(c1.column_name) || ''' where ' || table_id || ' = ' || c1.table_id || ' and column_name is not null';
EXECUTE IMMEDIATE stmt;
end;

I think i have one alternative for your question. MERGE can be used in this case. Please try it i dont have workspaceso dint test it but it should work Let me know if it helps.
FUNCTION get_encryp_pass(
table_name IN VARCHAR2,
column_name IN VARCHAR2,
table_id IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
EXECUTE IMMEDIATE 'MERGE INTO '||table_name||' t1 USING
(
SELECT * FROM '||table_name|| ')t2
ON
(
t1.table_id = t2.table_id
)
WHEN MATCHED THEN
UPDATE SET t1.'||column_name||' = encrypt_val(t2.'||column_name||')'
||' WHERE and t1.'||column_name||' IS NOT NULL';
END;

Related

ORA-00904 - Invalid Identifier in Dynamic SQL

I'm trying to get to the bottom of ORA-00904 - Invalid Identifier error that I'm getting in my stored procedure.
Here is the code:
CREATE OR REPLACE PROCEDURE CDG4_HIER_GET_SUBTREE(pDimensionId IN VARCHAR2, pPeriodId IN NUMBER, pNodeId IN NUMBER, pMode IN CHAR, rCursor OUT SYS_REFCURSOR) IS
v_table_name VARCHAR2(30);
v_function_name VARCHAR2(30) := 'CDG4_HIER_MGR_HAS_CHILDREN'; -- some function defined in the same package
InvalidMode EXCEPTION;
---
v_sql VARCHAR2(2000);
BEGIN
-- Get dynamic table name
v_sql := 'SELECT UPPER(TABLE_ID)'
||'FROM CDG4_CFG_MAP_GER '
||'WHERE UPPER(DIMENSION_ID) = UPPER(''' || pDimensionId || ''') ';
EXECUTE IMMEDIATE v_sql INTO v_table_name;
IF pMode = 'F' THEN
-- Do something
ELSIF pMode = 'S' THEN
v_sql := 'SELECT A.PERIODO_K, '
||' A.FIGLIO_K, '
||' A.PADRE_K, '
||' A.F_LAYOUT, '
||' A.F_VISUALIZZA, '
||' DECODE(A.PADRE_K, NULL, NULL, B2.CODICE) AS CODICE_PADRE, '
||' A.F_ORDINE, '
||' DECODE(A.GEN1, ''2'', ''I'', A.GEN1) AS GEN1, '
||' A.GEN2, '
||' A.GEN3, '
||' ''[''|| B1.CODICE || ''] - '' || B1.DESCR AS DESCR, '
||' ''[''|| B1.CODICE || ''] - '' || B1.DESCR AS DESCRIZIONE, '
||' ' || v_function_name || '(''' || pDimensionId || ''', ' || pPeriodId || ', A.FIGLIO_K) AS HAS_CHILDREN '
||'FROM DM_GERARCHIE A, DIM_BO_CANALE_PRIMARIA B1, DIM_BO_CANALE_PRIMARIA B2 '
||'WHERE A.FIGLIO_K = B1.CODICE_K '
||'AND A.PADRE_K = B2.CODICE_K '
||'AND UPPER(A.DIMENSION_ID) = UPPER(''' || pDimensionId || ''') '
||'AND UPPER(B1.DIMENSION_ID) = UPPER(''' || pDimensionId || ''') '
||'AND UPPER(B2.DIMENSION_ID) = UPPER(''' || pDimensionId || ''') '
||'AND A.PERIODO_K = ' || pPeriodId
||' AND A.FIGLIO_K = ' || pNodeId;
ELSE
RAISE InvalidMode;
END IF;
OPEN rCursor FOR v_sql;
EXCEPTION
WHEN InvalidMode THEN
RAISE_APPLICATION_ERROR(-20005, 'Invalid selection mode.');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20004, 'Generic error - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
Oracle seems not to be able to identify the function v_function_name (it is in the same package) as it keeps returning ORA-00904 while opening the cursor rCursor.
Any hint to a plausible clause of this behaviour?
Thanks in advance.
Oracle seems not to be able to identify the function v_function_name (it is in the same package
Dynamic SQL is executed as SQL but outside of the scope of the package. That means we need to build a valid SQL statement. If you were running a similar static SELECT statement you would have written package_name.v_function_name because your SQL would execute outside the package. And that's what you need to do here.
Although now I've looked more closely at your code and I don't understand why you are using Dynamic SQL at all. You could execute your statements as static SQL with bind variables and parameters.
OPEN rCursor FOR
SELECT A.PERIODO_K,
A.FIGLIO_K,
A.PADRE_K,
A.F_LAYOUT,
A.F_VISUALIZZA,
DECODE(A.PADRE_K, NULL, NULL, B2.CODICE) AS CODICE_PADRE,
A.F_ORDINE,
DECODE(A.GEN1, ''2'', ''I'', A.GEN1) AS GEN1,
A.GEN2,
A.GEN3,
'[' || B1.CODICE || '] - ' || B1.DESCR AS DESCR,
'[' || B1.CODICE || '] - ' || B1.DESCR AS DESCRIZIONE,
package_name.v_function_name (pDimensionId ,pPeriodId , A.FIGLIO_K) AS HAS_CHILDREN
FROM DM_GERARCHIE A, DIM_BO_CANALE_PRIMARIA B1, DIM_BO_CANALE_PRIMARIA B2
WHERE A.FIGLIO_K = B1.CODICE_K
AND A.PADRE_K = B2.CODICE_K
AND UPPER(A.DIMENSION_ID) = UPPER( pDimensionId )
AND UPPER(B1.DIMENSION_ID) = UPPER( pDimensionId )
AND UPPER(B2.DIMENSION_ID) = UPPER( pDimensionId )
AND A.PERIODO_K = pPeriodId
AND A.FIGLIO_K = pNodeId;

Insert into by chunks

I am trying to use insert into statement, but getting the error:
ORA-01628: max # extents (32765) reached for rollback segment _SYSSMU134_1882489978$
Increasing the UNDO tablespace is not an option, so I would like a way to insert those data by chunks (for example with 1 million rows at a time). Can someone help to rewrite this procedure in that way?
CREATE OR REPLACE PROCEDURE create_chunks (
p_source_table IN VARCHAR2,
p_table_name_chunk IN VARCHAR2,
p_chunks IN VARCHAR2
) AS
v_insert_sql CLOB;
BEGIN
v_insert_sql := 'INSERT INTO ' || p_table_name_chunk ||
' (rid, chunk_number) ' ||
'SELECT /*+ parallel(64) */ rowid rid,' ||
'mod( ora_hash(rowid), :p_chunks ) as chunk_number '
'FROM ' || p_source_table;
EXECUTE IMMEDIATE v_insert_sql USING p_chunks;
COMMIT;
END;
This v_insert_sql is failing with above mentioned error. I have working solution using the cursor fetching like that:
DECLARE
CURSOR v_cur IS SELECT /*+ parallel(64) */
rowid rid, mod( ora_hash(rowid), 20000 ) AS chunk_number
-- I need this table to be parametric name
FROM some_table;
TYPE t_sample IS TABLE OF v_cur%ROWTYPE;
v_sample t_sample;
v_row_limit CONSTANT NUMBER := 1000000;
BEGIN
OPEN v_cur;
LOOP
FETCH v_cur BULK COLLECT INTO v_sample LIMIT v_row_limit;
FORALL i IN v_sample.first .. v_sample.last
INSERT INTO chunk_table VALUES v_sample(i);
COMMIT;
EXIT WHEN v_cur%NOTFOUND;
END LOOP;
CLOSE v_cur;
END;
I can't move this cursor straight into the procedure as the table name is varying and I need it to be parametric as with cursor approach I have to repeat the same code for different tables. So the question is how to deal with this?
Basically, I was able to just past the whole chunks approach inside procedure as dynamic query, like that:
CREATE OR REPLACE PROCEDURE create_chunks (
p_source_table IN VARCHAR2,
p_table_name_chunk IN VARCHAR2,
p_chunks IN VARCHAR2
) AS
v_insert_sql CLOB;
BEGIN
v_insert_sql := '' ||
' DECLARE ' || CHR(10) ||
' CURSOR cur1 IS SELECT ' || CHR(10) ||
' /*+ parallel(64) full(tbn)*/ rowid rid,' || CHR(10) ||
' mod( ora_hash(rowid), :p_chunks ) AS chunk_number' || CHR(10) ||
' FROM ' || p_source_table || ' tbn;' || CHR(10) ||
' TYPE t_sample IS TABLE OF cur1%ROWTYPE;' || CHR(10) ||
' v_sample t_sample;' || CHR(10) ||
' v_row_limit CONSTANT NUMBER := 1000000;' || CHR(10) ||
' BEGIN' || CHR(10) ||
' OPEN cur1;' || CHR(10) ||
' LOOP' || CHR(10) ||
' FETCH cur1 BULK COLLECT INTO v_sample LIMIT v_row_limit;' || CHR(10) ||
' FORALL i IN v_sample.first .. v_sample.last' || CHR(10) ||
' INSERT INTO ' || p_table_name_chunk || ' VALUES v_sample(i);' || CHR(10) ||
' COMMIT;' || CHR(10) ||
' EXIT WHEN cur1%NOTFOUND;' || CHR(10) ||
' END LOOP;' || CHR(10) ||
' CLOSE cur1;' || CHR(10) ||
' END;';
EXECUTE IMMEDIATE v_insert_sql USING p_chunks;
COMMIT;
END;

Efficient query to find invalid number's in varchar column

I have already asked almost the same question before:
Finding non-numeric values in varchar column
And I received some great answer's and idea's to make not only fix the issue in my query but also make it much more efficient.
Old Query:
Select * From Table_Name
Where
(NOT REGEXP_LIKE(COLUMN_NAME, '^-?[0-9.]+$')
OR
LENGTH(Function_To_Fetch_Left_Component(COLUMN_NAME)) > (Precision-Scale)
OR
LENGTH(Column_Name) - LENGTH(REPLACE(Column_Name,'.','')) > 1)
New Query:
Select * From Table_Name
WHERE (Translate(column_name,'x0123456789-.','x') is not null
OR column_name = '.'
OR column_name = '-'
OR column_name = '-.'
OR Instr(column_name,'-') > 1
OR column_name like '%-%-%'
OR column_name like '%.%.%'
OR Instr(column_name||'.','.')-1 > (precision-scale) ) ;
Known limitations which are okay:
1.) Doesn't handle scientific notation. Its by design as I want to reject those.
2.) Doesn't check total precision (decimal component) however as while inserting oracle itself round's it off I am fine with it.
3.) Doesn't check for leading zero's.
Please help to see if the above query cover's everything and I haven't missing anything.
Another great solution by one Stackoverflow member however increased execution time by 2.5 times:
Function:
CREATE OR REPLACE function temp_is_number(p_test_value varchar2,
p_scale NUMBER,
p_precision NUMBER) return varchar2 is
l_result varchar2(1);
begin
execute immediate 'DECLARE l_number NUMBER; ' ||
'l_test_number NUMBER(' || p_precision || ',' || p_scale || '); ' ||
'BEGIN ' ||
' l_number := cast(:b1 as number); ' ||
' l_test_number := cast(:b1 as number); ' ||
' IF (l_number = l_test_number) THEN ' ||
' :b2 := ''Y''; ' ||
' ELSE ' ||
' :b2 := ''N''; ' ||
' END IF; ' ||
'EXCEPTION ' ||
' WHEN OTHERS THEN ' ||
' :b2 := ''N''; ' ||
'END;'
using in p_test_value, out l_result;
return l_result;
end;
/
Select Count(1) from Table_Name Where temp_is_number (Column_Name,scale,precision) = 'N';

Gettig error PLS-00364

I'm trying to create a stored procedure where I'm passing select statement to for loop and i'm using dynamic table which is passing at runtime and getting below error:
LINE 23 PLS-00364: loop index variable 'I' use is invalid
LINE 19 PL/SQL: ORA-00942: table or view does not exist
CREATE OR REPLACE PROCEDURE CREATE_TEST(TBL_NM IN VARCHAR2)
IS
SRC_ID NUMBER(38);
SQL_Q VARCHAR2(250);
DEL_F VARCHAR2(250);
BEGIN
FOR I in (SELECT DEL_IND FROM TBL_NM)
LOOP
SRC_ID := SRC_FILE_ID_SEQ.NEXTVAL;
IF I.DEL_IND = 0
THEN
execute immediate 'INSERT INTO TEST_HIST ' || ' (a,b,c,d,e,DEL_IND) ' ||
' SELECT a,b,c,d,e, '|| 0 || ' || ' FROM ' || TBL_NM;
ELSIF I.DEL_IND = 1
THEN
execute immediate 'INSERT INTO JESTX_IGNR ' || ' (a,b,c,d,e,DEL_IND,SRC_ID_NO) ' ||
' SELECT a,b,c,d,e, '|| 2 ||' , '|| SRC_ID || ' FROM ' || TBL_NM;
END IF ;
END LOOP;
COMMIT;
END;
I call the procedure using:
EXEC CREATE_TEST('abc');
What you want is a REF CURSOR as you cannot use cursor for loop with dynamic sql.
I dont know the exact datatype for your column DEL_IND. Please declare accordingly.
Here is some more information on Oracle REF CURSORS.
Try below
CREATE OR REPLACE PROCEDURE CREATE_TEST(TBL_NM IN VARCHAR2)
IS
TYPE c1ref is REF CURSOR;
SRC_ID NUMBER(38);
SQL_Q VARCHAR2(250);
DEL_F VARCHAR2(250);
DEL_IND NUMBER(5);
BEGIN
vsql_text := 'select DEL_IND from ' || TBL_NM;
open c1ref for vsql_text;
LOOP
SRC_ID := SRC_FILE_ID_SEQ.NEXTVAL;
fetch c1ref into DEL_IND;
exit when c1ref%NOTFOUND;
IF (DEL_IND = 0)
THEN
execute immediate 'INSERT INTO TEST_HIST ' || ' (a,b,c,d,e,DEL_IND) ' ||
' SELECT a,b,c,d,e, '|| 0 || ' || FROM ' || TBL_NM;
ELSIF (DEL_IND = 1)
THEN
execute immediate 'INSERT INTO JESTX_IGNR ' || ' (a,b,c,d,e,DEL_IND) ' ||
' SELECT a,b,c,d,e, '|| 2 ||' , '|| SRC_ID || ' FROM ' || TBL_NM;
END IF ;
END LOOP;
CLOSE c1ref;
COMMIT;
END;

Getting ORA-01747: invalid user.table.column, table.column, or column specification in Oracle when inserting data using a dynamic insert

Here is the code.
p_id number,
p_mc varchar2
Both of the above parameters will be passed in during a procedure call.
EXECUTE IMMEDIATE 'INSERT INTO COUNT_MASTER_TEMP ' || 'SELECT COUNT (ar.'|| p_mc || ')' ||
'
FROM app_recipient ar
WHERE EXISTS (SELECT r.' || p_mc ||
' FROM app_recipient r
WHERE r.ID =' || p_id || ' AND ar.'|| p_mc || '= r.'|| p_mc ||')';
My stored procedure is as follows:
input parameters are p_id (which is a numeric value), p_mc is a actually a column name. sample data is p_id = 6372325 and p_mc can be MC1, MC2 till MC14.
CREATE OR REPLACE PROCEDURE HCP_360.sp_get_all_records
(p_id NUMBER,
p_mc varchar2,
p_detail OUT SYS_REFCURSOR)
IS
v_count NUMBER;
v_master_id NUMBER;
v_sql VARCHAR2(2000);
--v_sql2 VARCHAR2(2000);
v_mc VARCHAR2(255):=p_mc;
cur_detail SYS_REFCURSOR;
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DELETE FROM COUNT_MASTER_TEMP';
execute immediate 'INSERT INTO COUNT_MASTER_TEMP ' ||
'SELECT COUNT (ar.'|| v_mc|| ')' || '
FROM app_recipient ar
WHERE EXISTS (SELECT r.' || v_mc || ' FROM app_recipient r
WHERE r.ID =' || p_id || ' AND ar.'|| v_mc || '= r.'|| v_mc||')';
END;
BEGIN
select c_count
into v_count
from COUNT_MASTER_TEMP;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
v_count := 0;
END;
BEGIN
IF v_count > 0
THEN
v_sql := 'SELECT master_id
FROM app_recipient
WHERE ' || v_mc || ' IN (SELECT r.'||v_mc ||
' FROM app_recipient r
WHERE r.ID = ' || p_id || ')
AND ROWNUM <= 1
AND master_id IS NOT NULL
ORDER BY master_id DESC';
EXECUTE IMMEDIATE 'DELETE FROM COUNT_MASTER_TEMP';
EXECUTE IMMEDIATE 'INSERT INTO COUNT_MASTER_TEMP ' || v_sql;
END IF;
select c_count
into v_master_id
from COUNT_MASTER_TEMP;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
v_master_id := 0;
END;
BEGIN
v_sql :=
'
SELECT r.ID,
r.master_id,
v.RECIPIENT_STATUS,
v.PARENT_OR_CHILD,
nvl(v.CHILD_COUNT, 0) CHILD_COUNT,
r.IS_PICKABLE,
r.IS_GOLDEN,
r.request_wf_state,
r.record_type,
r.first_name,
r.last_name,
r.'||v_mc ||
',r.middle,
r.title,
r.name_of_organization,
r.name_of_business,
r.address,
r.city,
r.state,
r.country,
v.HCP_TYPE,
v.HCP_SUBTYPE,
v.is_edit_locked,
v.record_type as rec_type,
v.DATA_SOURCE_NAME,
v.DEA_DATA,
v.NPI_DATA,
v.STATE_DATA,
RPPS,
v.finess,
v.siren_number
FROM app_recipient r
left join V_MASTER_RECIP_W_TRXN_OP v
on r.id = v.id
or r.master_id =' || v_master_id||
'WHERE' ||'r.'||v_mc || '= ANY
(SELECT ar.'||v_mc || 'FROM app_recipient ar WHERE r.ID =' || p_id || ')
UNION ALL
SELECT r.ID,
r.master_id,
v.RECIPIENT_STATUS,
v.PARENT_OR_CHILD,
nvl(v.CHILD_COUNT, 0) CHILD_COUNT,
r.IS_PICKABLE,
r.IS_GOLDEN,
r.request_wf_state,
r.record_type,
r.first_name,
r.last_name,
r.'||v_mc ||
',r.middle,
r.title,
r.name_of_organization,
r.name_of_business,
r.address,
r.city,
r.state,
r.country,
v.HCP_TYPE,
v.HCP_SUBTYPE,
v.is_edit_locked,
v.record_type as rec_type,
v.DATA_SOURCE_NAME,
v.DEA_DATA,
v.NPI_DATA,
v.STATE_DATA,
RPPS,
v.finess,
v.siren_number
FROM app_recipient r
left join V_MASTER_RECIP_W_TRXN_OP2 v
on r.id = v.id
or r.master_id =' || v_master_id ||'
WHERE r.'||v_mc ||'= ANY (SELECT ar.'||v_mc ||'FROM app_recipient ar WHERE r.ID =' ||v_master_id || ')';
open cur_detail for v_sql;
p_detail := cur_detail;
end;
END;
/
if you use pid as a VARCHAR with non-numeric data.. and you have embed it in single quotes, during query formation, or define it as a bind variable.
Always use bind variables where-ever possible.
EXECUTE IMMEDIATE
'INSERT INTO COUNT_MASTER_TEMP ' ||
'SELECT COUNT (ar.'|| p_mc || ')' ||
' FROM app_recipient ar ' ||
' WHERE EXISTS (SELECT r.' || p_mc ||
' FROM app_recipient r ' ||
' WHERE r.ID = :pid AND ar.'|| p_mc || '= r.'|| p_mc||')'
using pid;
You could test the string formation using DBMS_OUTPUT.
For example,
SQL> set serveroutput on
SQL> DECLARE
2 p_mc VARCHAR2(20);
3 p_id NUMBER;
4 BEGIN
5 p_mc := 'mc';
6 p_id := 1;
7 dbms_output.put_line( 'INSERT INTO COUNT_MASTER_TEMP ' ||
8 'SELECT COUNT (ar.'|| p_mc || ')' || '
9 FROM app_recipient ar
10 WHERE EXISTS (SELECT r.' || p_mc || ' FROM app_recipient r
11 WHERE r.ID =' || p_id || ' AND ar.'|| p_mc || '= r.'|| p_mc||')');
12 END;
13 /
INSERT INTO COUNT_MASTER_TEMP SELECT COUNT (ar.mc)
FROM app_recipient ar
WHERE
EXISTS (SELECT r.mc FROM app_recipient r
WHERE r.ID =1 AND ar.mc= r.mc)
PL/SQL procedure successfully completed.
SQL>
Always remember to first test the dynamic string using DBMS_OUTPUT. Once you are confirm that the string is correctly formed, remove/comment the dbms_output and use EXECUTE IMMEDIATE.
Update Thanks to Alex Poole. The actual issue is here:
'WHERE' ||'r.'||v_mc || '= ANY
After WHERE, there is no space, thus the query fails. You need to add a space after WHERE.
'WHERE ' ||'r.'||v_mc || '= ANY
The only way I can immediately see to get that error from insert is if you're passing the column name enclosed in single-quotes; you haven't shown the call and it's unlikely you'd do this from a SQL client (more likely you added quotes incorrectly in a JDBC/PHP/etc. parameter), but calling like this:
exec sp_get_all_records(6372325, '''MC1''', :detail);
would try to execute generated SQL that looks like this:
INSERT INTO COUNT_MASTER_TEMP SELECT COUNT (ar.'MC1')
FROM app_recipient ar
WHERE EXISTS (SELECT r.'MC1' FROM app_recipient r
WHERE r.ID =6372325 AND ar.'MC1'= r.'MC1')
with the column name starting with the illegal single-quote character, and that would indeed throw:
ORA-01747: invalid user.table.column, table.column, or column specification
ORA-06512: at "SCHEMA.SP_GET_ALL_RECORDS", line 17
ORA-06512: at line 1
and line 17 is the execute immediate 'INSERT....
You are also missing some whitespace in your final v_sql construct, which will case the open cur_detail to get an "ORA-00933: SQL command not properly ended" with what you've shown. You need to change
'WHERE' ||'r.'||v_mc || '= ANY
(SELECT ar.'||v_mc || 'FROM app_recipient ar WHERE r.ID =' || p_id || ')
to
' WHERE ' ||'r.'||v_mc || '= ANY
(SELECT ar.'||v_mc || ' FROM app_recipient ar WHERE r.ID =' || p_id || ')
with spaces ether side of the first WHERE, and before the FROM; and also in the second half of the union change
WHERE r.'||v_mc ||'= ANY (SELECT ar.'||v_mc ||'FROM app_recipient ar WHERE r.ID =' ||v_master_id || ')';
to
WHERE r.'||v_mc ||'= ANY (SELECT ar.'||v_mc ||' FROM app_recipient ar WHERE r.ID =' ||v_master_id || ')';
again adding a space before FROM.
Those won't get the ORA-01747 error you reported, but neither will the insert you showed, which seems to be valid with the arguments you are passing - unless you are incorrectly quoting the column name argument as shown above.
I was testing my procedure using PL/SQL developer. I still do not know why ORA-01747 was occurring. But I modified my procedure and wrote a PL/SQL code for testing the output.
Procedure is as follows:
CREATE OR REPLACE PROCEDURE HCP_360.sp_get_all_records
(p_id NUMBER,
p_mc in varchar2,
p_detail OUT SYS_REFCURSOR,
p_count OUT NUMBER,
p_error OUT NVARCHAR2)
IS
v_count NUMBER;
v_master_id NUMBER;
v_sql LONG;
--v_sql2 VARCHAR2(2000);
v_mc VARCHAR2(255):=p_mc;
cur_detail SYS_REFCURSOR;
BEGIN
BEGIN
-- v_sql := '(SELECT COUNT ( ' ||v_mc || ')' ||
-- '
-- FROM app_recipient
-- WHERE ' ||v_mc || ' IN (SELECT ' || v_mc ||
-- ' FROM app_recipient r
-- WHERE r.ID =' || p_id || ' AND '|| v_mc || '=' || v_mc ||'))';
v_sql :='(SELECT ar.'||v_mc || ' as v_count' ||
'
FROM app_recipient ar
WHERE EXISTS (SELECT r.'||v_mc ||
' FROM app_recipient r
WHERE r.ID =' || p_id || ' AND ar.'||v_mc || '= r.'||v_mc ||'))';
--EXECUTE IMMEDIATE 'DELETE FROM COUNT_MASTER_TEMP';
EXECUTE IMMEDIATE ' select nvl(count(*),0) as count from (' || v_SQL || ') '
INTO v_count;
END;
BEGIN
IF v_count > 0
THEN
v_sql := 'SELECT master_id
FROM app_recipient
WHERE ' || v_mc || ' IN (SELECT r.'||v_mc ||
' FROM app_recipient r
WHERE r.ID = ' || p_id || ')
AND ROWNUM <= 1
AND master_id IS NOT NULL
ORDER BY master_id DESC';
EXECUTE IMMEDIATE ' select nvl(master_id, 0) from (' || v_SQL || ') '
INTO v_master_id;
END IF;
END;
BEGIN
EXECUTE IMMEDIATE ' delete from GTT_RECIPEINTS_FOR_MC';
execute immediate 'insert into GTT_RECIPEINTS_FOR_MC
( MATCH_CODE_VALUE ,master_id ,id)
(SELECT r.'||v_mc ||', r.master_id, r.id
FROM app_recipient r
WHERE r.'||v_mc || '= ANY (SELECT r.'||v_mc || '
FROM app_recipient r
WHERE r.ID =' || p_id||')
UNION ALL
SELECT r.'||v_mc ||', r.master_id, r.id
FROM app_recipient r
WHERE r.ID =' ||v_master_id ||')';
end;
BEGIN
v_sql :=
'
select ( r.id) M_ID, r.RECIPIENT_STATUS, PARENT_OR_CHILD, nvl(CHILD_COUNT,0), r.IS_PICKABLE, r.IS_GOLDEN, r.ID, nvl(r.MASTER_ID,r.id) as MASTER_ID , r.request_wf_state,
r.TITLE, r.FIRST_NAME, r.MIDDLE, r.LAST_NAME,r.FULL_NAME_LNF, r.FULL_NAME_FNF, r.NAME_OF_ORGANIZATION,r.ADDRESS,
r.CITY, r.STATE, r.COUNTRY, r.HCP_TYPE, r.HCP_SUBTYPE, r.is_edit_locked, r.record_type as rec_type,
DATA_SOURCE_NAME,DEA_DATA,NPI_DATA,STATE_DATA,RPPS ,finess,siren_number from v_master_recip_w_trxn_op r join GTT_RECIPEINTS_FOR_MC p on r.id=p.id or r.id= p.master_id
order by id';
open cur_detail for v_sql;
p_detail := cur_detail;
p_count :=SQL%ROWCOUNT;
EXCEPTION
WHEN OTHERS
THEN
p_count := 0;
ROLLBACK;
end;
END;
/
And the PL/SQL code for testing is as follows:
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
l_cursor SYS_REFCURSOR;
p_count number;
p_error NVARCHAR2 (255);
M_ID app_recipient.id%type ;
l_ID app_recipient.id%type ;
l_master_id app_recipient.master_id%type ;
l_RECIPIENT_STATUS V_MASTER_RECIP_W_TRXN_OP2.recipient_status%type;
l_PARENT_OR_CHILD V_MASTER_RECIP_W_TRXN_OP2.parent_or_child%type;
l_CHILD_COUNT V_MASTER_RECIP_W_TRXN_OP2.child_count%type;
l_IS_PICKABLE app_recipient.is_pickable%type;
l_IS_GOLDEN app_recipient.is_golden%type;
l_request_wf_state app_recipient.request_wf_state%type;
l_record_type app_recipient.record_type%type;
l_first_name app_recipient.first_name%type;
l_last_name app_recipient.last_name%type;
l_p_mc app_recipient.MC14%type;
l_middle app_recipient.middle%type;
l_title app_recipient.title%type;
l_name_of_organization app_recipient.name_of_organization%type;
l_name_of_business app_recipient.name_of_business%type;
l_address app_recipient.address%type;
l_city app_recipient.city%type;
l_state app_recipient.state%type;
l_country app_recipient.country%type;
l_HCP_TYPE v_master_recip_w_trxn_op.HCP_TYPE%type;
l_HCP_SUBTYPE V_MASTER_RECIP_W_TRXN_OP.HCP_SUBTYPE%type;
l_is_edit_locked V_MASTER_RECIP_W_TRXN_OP.is_edit_locked%type;
l_rec_type V_MASTER_RECIP_W_TRXN_OP.record_type%type;
l_DATA_SOURCE_NAME V_MASTER_RECIP_W_TRXN_OP.data_source_name%type;
l_DEA_DATA V_MASTER_RECIP_W_TRXN_OP.dea_data%type;
l_NPI_DATA V_MASTER_RECIP_W_TRXN_OP.npi_data%type;
l_STATE_DATA V_MASTER_RECIP_W_TRXN_OP.state_data%type;
l_RPPS V_MASTER_RECIP_W_TRXN_OP.rpps%type;
l_finess V_MASTER_RECIP_W_TRXN_OP.finess%type;
l_siren_number V_MASTER_RECIP_W_TRXN_OP.siren_number%type;
l_FULL_NAME_LNF V_MASTER_RECIP_W_TRXN_OP.siren_number%type;
l_FULL_NAME_FNF V_MASTER_RECIP_W_TRXN_OP.siren_number%type;
BEGIN
hcp_360.hcp360_application.get_recipients_for_mc(p_id => &&var,
p_mc => &&p_mc,
p_detail => l_cursor,
p_count => p_count,
p_error => p_error);
LOOP
FETCH l_cursor
INTO M_ID ,
l_RECIPIENT_STATUS ,
l_PARENT_OR_CHILD ,
l_CHILD_COUNT ,
l_IS_PICKABLE,
l_IS_GOLDEN,
l_ID,
L_MASTER_ID,
l_request_wf_state,
l_title,
l_first_name,
l_middle,
l_last_name,
l_FULL_NAME_LNF,
l_FULL_NAME_FNF,
l_name_of_organization,
l_address,
l_city,
l_state,
l_country,
l_HCP_TYPE,
l_HCP_SUBTYPE,
l_is_edit_locked,
l_rec_type,
l_DATA_SOURCE_NAME,
l_DEA_DATA,
l_NPI_DATA,
l_STATE_DATA,
l_RPPS,
l_finess,
l_siren_number;
EXIT WHEN l_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(M_ID || ' | ' ||
l_RECIPIENT_STATUS || ' | ' ||
l_PARENT_OR_CHILD || ' | ' ||
l_CHILD_COUNT || ' | ' ||
l_IS_PICKABLE || ' | ' ||
l_IS_GOLDEN || ' | ' ||
l_ID || ' | ' ||
L_MASTER_ID || ' | ' ||
l_request_wf_state || ' | ' ||
l_title || ' | ' ||
l_first_name || ' | ' ||
l_middle || ' | ' ||
l_last_name || ' | ' ||
l_FULL_NAME_LNF || ' | ' ||
l_FULL_NAME_FNF || ' | ' ||
l_name_of_organization || ' | ' ||
l_address || ' | ' ||
l_city || ' | ' ||
l_state || ' | ' ||
l_country || ' | ' ||
l_HCP_TYPE || ' | ' ||
l_HCP_SUBTYPE || ' | ' ||
l_is_edit_locked || ' | ' ||
l_rec_type || ' | ' ||
l_DATA_SOURCE_NAME || ' | ' ||
l_DEA_DATA || ' | ' ||
l_NPI_DATA || ' | ' ||
l_STATE_DATA || ' | ' ||
l_RPPS || ' | ' ||
l_finess || ' | ' ||
l_siren_number
);
END LOOP;
CLOSE l_cursor;
END;

Resources