I am trying to create a dynamic merge script and pass the variables dynamically, but the variable are not getting substituted in the code. Can someone help on this?
create or replace PROCEDURE MERGE_APPMODULE(institutionKey varchar2,applname varchar2,modulename varchar2,DESCRIPTION varchar2 )
as
--set serveroutput on;
--SET FEEDBACK OFF;
DATA long;
BEGIN
select
CONCAT ('declare
institutionkey varchar2(100) := '|| '''institutionkey''' ||' ;
actiondate DATE := SYSDATE;
actionuser VARCHAR2(100) := sys_context(''USERENV'', ''AUTHENTICATED_IDENTITY'');
supportedLanguages varchar2(100) := ''en'';
BEGIN',
'
MERGE INTO APPMODULE TARGET
USING (
SELECT 0 DISALLOW, NULL IMAGE, NULL IsMaintainence, moduleclass,1 ModuleIndex, ''modulename'' ModuleName , ApplId FROM APPLICATION WHERE ApplName = ''applname'' and FinInstKey = ''institutionKey'')
) source
ON (
target.ApplId=source.ApplId and target.ModuleName=source.ModuleName
)
WHEN NOT MATCHED THEN
insert (createddate, creatorusr, Disallow, Image, IsDefault, IsMaintainence, moduleClass, ModuleIndex, ModuleName, updatordate, updatorusr, ApplId)
values (actionDate, actionUser, source.Disallow, source.Image, 1, source.IsMaintainence, source.moduleClass, source.ModuleIndex, source.ModuleName, actionDate, actionUser, source.ApplId);
MERGE INTO APPMODULETXT target
USING (
SELECT ''DESCRIPTION'' DESCRIPTION, ModuleId FROM AppModule m JOIN Application a ON m.ApplId = a.ApplId WHERE m.ModuleName = ''ACCOUNTS_SERVICES_MODULE'' AND a.ApplName = applicationName AND a.finInstKey = ''institutionKey''
) source
ON (
target.ModuleId = source.ModuleId
)
WHEN NOT MATCHED THEN
insert (Description, TxtLanguage, ModuleId)
values (source.Description, ''en'', source.ModuleId);') INTO DATA from dual;
dbms_output.put_line(DATA);
END;
You are not doing concatanation properly.
Strings can be concated using || operaror or concat method.
In your code you used both and mess happened. Here, I tried using || operator as following:
create or replace PROCEDURE MERGE_APPMODULE(institutionKey varchar2,applname varchar2,modulename varchar2,DESCRIPTION varchar2 )
as
--set serveroutput on;
--SET FEEDBACK OFF;
DATA VARCHAR2(32767); -- using varchar2 data type variable
BEGIN
DATA := 'declare
institutionkey varchar2(100) := '''|| institutionkey ||''' ;
actiondate DATE := SYSDATE;
actionuser VARCHAR2(100) := sys_context(''USERENV'', ''AUTHENTICATED_IDENTITY'');
supportedLanguages varchar2(100) := ''en'';
BEGIN' || chr(10) ||
' MERGE INTO APPMODULE TARGET
USING (
SELECT 0 DISALLOW, NULL IMAGE, NULL IsMaintainence, moduleclass,1 ModuleIndex, '''|| modulename ||''' ModuleName , ApplId FROM APPLICATION WHERE ApplName = ''' || applname || ''' and FinInstKey = ''' || institutionKey || '''
) source
ON (
target.ApplId=source.ApplId and target.ModuleName=source.ModuleName
)
WHEN NOT MATCHED THEN
insert (createddate, creatorusr, Disallow, Image, IsDefault, IsMaintainence, moduleClass, ModuleIndex, ModuleName, updatordate, updatorusr, ApplId)
values (actionDate, actionUser, source.Disallow, source.Image, 1, source.IsMaintainence, source.moduleClass, source.ModuleIndex, source.ModuleName, actionDate, actionUser, source.ApplId);
MERGE INTO APPMODULETXT target
USING (
SELECT ''' || DESCRIPTION || ''' DESCRIPTION, ModuleId FROM AppModule m JOIN Application a ON m.ApplId = a.ApplId WHERE m.ModuleName = ''ACCOUNTS_SERVICES_MODULE'' AND a.ApplName = applicationName AND a.finInstKey = ''' || institutionKey || '''
) source
ON (
target.ModuleId = source.ModuleId
)
WHEN NOT MATCHED THEN
insert (Description, TxtLanguage, ModuleId)
values (source.Description, ''en'', source.ModuleId);';
dbms_output.put_line(DATA);
END;
Check if it is working for you.
Cheers!!
Why are you using type LONG in this century?
It has been sort of deprecated since Oracle 8.0 came out in 1997.
Using CLOB will generally make your life a lot easier, but in this case even a VARCHAR2 is probably large enough to fit your query.
Related
Hello i m having this error :
Invalid host/bind variable name ORA-01745 at line 47
The error , from the second insert (insert into TPILVALEUR )
when i m using the procedure below , i know that it happen when we use a Oracle variable in the request but im not using it (i think in my queries) , i dont know where he found the Oracle key word in my Insert request ...
create or replace
procedure computePilotageLFIICHN (pCampagne in number)
as
cSep constant varchar2(1) := ':';
cCodeGeoTableauDep constant varchar2(3) := 'DEP';
cCodeGeoTableauReg constant varchar2(3) := 'REG';
cCodeGeoTableauNat constant varchar2(3) := 'NAT';
cCodeTypeTableauCourant constant varchar2(12) := 'LFI_ICHN';
cCodeColTheorie constant varchar2(30) := 'LFI_ICHN_THEORIE';
cCodeColDosAvecLet constant varchar2(30) := 'LFI_ICHN_DOS_AVEC_LFI';
cCodeColAEditer constant varchar2(30) := 'LFI_ICHN_A_EDITER';
cCodeColAReediter constant varchar2(30) := 'LFI_ICHN_A_REEDITER';
cCodeColEditees constant varchar2(30) := 'LFI_ICHN_EDITEES';
idTypeDemd constant varchar2(12) := '20.2010';
lDateDebut timestamp;
lTempsExec varchar2(29);
cNbEtapes constant number := 5;
lEtapeCur number := 0;
begin
PCKISISLOGGER.logavancement('Début Calcul Pilotage LFI ICHN');
pilSupprimerTdB(cCodeTypeTableauCourant,pCampagne);
pilInitialiserTdB(cCodeTypeTableauCourant,pCampagne);
EXECUTE IMMEDIATE 'create global temporary table TPILTMPLFIICHN'||pCampagne||' As SELECT * from TPILTMPLFIICHN';
EXECUTE IMMEDIATE 'insert into TPILTMPLFIICHN'||pCampagne||'(CODEDDAF,NUMEROPACAGE,CAMPAGNE) (select CODEDDAF,NUMEROPACAGE,CAMPAGNE from TPILTMPLFIICHN)';
EXECUTE IMMEDIATE 'TRUNCATE TABLE TPILTMPLFIICHN'||pCampagne;
EXECUTE IMMEDIATE 'INSERT INTO TPILTMPLFIICHN'||pCampagne||'(codeDdaf, numeroPacage, campagne)
SELECT distinct sousReq.codeDdaf, sousReq.numeroPacage, '||pCampagne||'
FROM (
SELECT dos.CODEDDAF codeDdaf, dos.numeropacage numeroPacage
FROM TSRFDOSSIERSURFACE dos,TSRFDEMANDEAIDE dem, TVSFDOSSIERVALORISATION2P dvn
WHERE dem.IDTYPEDEMANDEAIDE = '||idTypeDemd||'
AND dem.IDDOSSIERSURFACE = dos.IDDOSSIERSURFACE
AND dos.campagne = '||pCampagne||' AND dos.DATEDERNIEREEVALUATION > dos.DATEDERNIEREMODIF and dos.DOSSIERMODIFIEAREEVALUER = 0
AND dem.DATEDERNIEREEVALUATION > dem.DATEDERNIEREMODIFICATION and dem.DOSSIERMODIFIEAREEVALUER = 0
AND dvn.ELIGIBLELFI = 1) sousReq';
-- Nombre de destinataires theoriques distincts
lEtapeCur := lEtapeCur + 1;
PCKISISLOGGER.logavancement('Etape ' || lEtapeCur || '/' || cNbEtapes || ' : Calcul du Nombre de destinataires théoriques distincts');
EXECUTE IMMEDIATE 'insert into TPILVALEUR (idValeur, idTableauDeBord, codeLigne, codeColonne, valeur)
SELECT
tab.idTableauDeBord || '||cSep||' || tmpLfi.codeDdaf || '||cSep||' || '||cCodeColTheorie||',
tab.idTableauDeBord,
tmpLfi.codeDdaf,
'||cCodeColTheorie||',
count(distinct tmpLfi.numeroPacage)
FROM
TPILTABLEAUDEBORD tab,
TPILTMPLFIICHN'||pCampagne||' tmpLfi
WHERE
tab.campagne = '||pCampagne||'
AND tmpLfi.campagne = '||pCampagne||'
AND tab.codeTypeTableauDeBord = '||cCodeTypeTableauCourant||'
AND tmpLfi.codeDdaf =
case
when tab.codeTypeGeoTableauDeBord = '||cCodeGeoTableauDep||' then tab.codeDepartement
when tab.codetypegeotableaudebord = '||cCodeGeoTableauReg||' and EXISTS(SELECT 1 FROM trefdepartement dept WHERE dept.code = tmpLfi.codeDdaf AND dept.codeRegion = tab.codeRegion) then tmpLfi.codeDdaf
when tab.codetypegeotableaudebord = '||cCodeGeoTableauNat||' then tmpLfi.codeDdaf
end
GROUP BY
tab.idTableauDeBord,
tmpLfi.codeDdaf';
EXECUTE IMMEDIATE 'drop table TPILTMPLFIICHN'||pCampagne;
PCKISISLOGGER.logavancement('Fin Calcul Pilotage LFI ICHN');
end computePilotageLFIICHN;
/
Thank you
Since you need more quotes to get literals for most of the local variables within the INSERT Statement such as
EXECUTE IMMEDIATE
'INSERT INTO TPILVALEUR (idValeur, idTableauDeBord, codeLigne, codeColonne, valeur)
SELECT
tab.idTableauDeBord || '''||cSep||''' || tmpLfi.codeDdaf || '''||cSep||''' || '''||cCodeColTheorie||''',
tab.idTableauDeBord,
tmpLfi.codeDdaf,
'''||cCodeColTheorie||''',
COUNT(DISTINCT tmpLfi.numeroPacage)
FROM
TPILTABLEAUDEBORD tab
JOIN
TPILTMPLFIICHN'||pCampagne||' tmpLfi
ON tmpLfi.codeDdaf =
CASE
WHEN tab.codeTypeGeoTableauDeBord = '''||cCodeGeoTableauDep||''' THEN tab.codeDepartement
WHEN tab.codetypegeotableaudebord = '''||cCodeGeoTableauReg||''' AND EXISTS(SELECT 1 FROM trefdepartement dept WHERE dept.code = tmpLfi.codeDdaf AND dept.codeRegion = tab.codeRegion) THEN tmpLfi.codeDdaf
WHEN tab.codetypegeotableaudebord = '''||cCodeGeoTableauNat||''' THEN tmpLfi.codeDdaf
END
WHERE tab.campagne = '''||pCampagne||'''
AND tmpLfi.campagne = '''||pCampagne||'''
AND tab.codeTypeTableauDeBord = '''||cCodeTypeTableauCourant||'''
GROUP BY tab.idTableauDeBord, tmpLfi.codeDdaf';
Here is one of oracle functions. There is a cursor called c_adv_course_credit which receives 2 parameters. These 2 parameters are using the where statement:
WHERE
-- year
cc.year = p_year AND
-- rela_pk
cc.sequence_number = p_sequence_number AND
cc.closed_ind = 'N';
When I run it in oracle sql developer:
SET SERVEROUTPUT ON
variable res varchar2(200);
EXECUTE :res := advp_test_cursor(2018, 92919);
select :res from dual;
The result text is always "not working"
Here is the full function (not working):
CREATE OR REPLACE Function SISD_OWNER.advp_test_cursor (
p_sequence_number IN NUMBER, -- rela_pk
p_year IN NUMBER -- year
)
RETURN VARCHAR2
IS
v_return_var VARCHAR2(300) := 'not working';
CURSOR c_adv_course_credit (
p_sequence_number IN NUMBER,
p_year IN NUMBER
)
IS
SELECT
cc.EXTERNAL_COURSE_CD
FROM
adv_course_credit cc
WHERE
cc.year = p_year AND
-- rela_pk
cc.sequence_number = p_sequence_number AND
cc.closed_ind = 'N';
BEGIN
FOR v_at_rec IN c_adv_course_credit(p_sequence_number, p_year) LOOP
v_return_var := v_at_rec.EXTERNAL_COURSE_CD;
DBMS_OUTPUT.PUT_LINE('?output = ' || v_return_var);
EXIT;
END LOOP;
RETURN v_return_var;
END;
If I change the cursor to use hard-coded numbers the function works and returns actual result.
WHERE
-- year
cc.year = 2018 AND
-- rela_pk
cc.sequence_number = 92919 AND
cc.closed_ind = 'N';
Your function is defined as (ignoring the data types):
advp_test_cursor(p_sequence_number, p_year)
but you're calling it as
advp_test_cursor(2018, 92919);
which has the arguments the wrong way round. You either need to flip them:
advp_test_cursor(92919, 2018);
or use named parameter notation:
advp_test_cursor(p_year=>2018, p_sequence_number=>92919)
or indeed combine both:
advp_test_cursor(p_sequence_number=>92919, p_year=>2018)
You do not need to use cursors:
CREATE OR REPLACE Function SISD_OWNER.advp_test_cursor (
p_sequence_number IN adv_course_credit.sequence_number%TYPE,
p_year IN adv_course_credit.year%TYPE
) RETURN adv_course_credit.EXTERNAL_COURSE_CD%TYPE
IS
v_return_var adv_course_credit.EXTERNAL_COURSE_CD%TYPE;
BEGIN
SELECT EXTERNAL_COURSE_CD
INTO v_return_var
FROM adv_course_credit
WHERE year = p_year
AND sequence_number = p_sequence_number
AND closed_ind = 'N';
DBMS_OUTPUT.PUT_LINE('?output = ' || v_return_var);
RETURN v_return_var;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'Not working';
END;
I have created a stored procedure where the user can inset 1 or multiple values in the parameter
create or replace procedure MyProcerdure
(
title Film.Title%Type,
country Film.country%Type,
language Film.language%Type,
category Film.category%Type,
refCursor OUT SYS_REFCURSOR )
AS
begin
OPEN refCursor FOR
select Film.Title as FilmTitle,
Film.language as language
Film.category
FROM Film
Where Film.language=language
AND Film.category=category
AND Film.Country=country
//etc...
But I want to allow the fact that the user doesn't have to fill them all and pass them in parameter , which means if the user only enter the language without anything else , return the proper language , and let's say he entered country and language so the result should get WHERE language and country is equal to what he inserted
Is it possible to make such a mechanism in a stored procedure using oracle ?
Thank you
You can simply add some logic in your query to handle the fact that parameters can be null:
CREATE OR REPLACE PROCEDURE MyProcerdure(
p_title Film.Title%TYPE,
p_country Film.country%TYPE,
p_language Film.language%TYPE,
p_category Film.category%TYPE,
po_refCursor OUT SYS_REFCURSOR
) AS
BEGIN
OPEN po_refCursor FOR
SELECT Film.Title AS FilmTitle, Film.language AS language, Film.category
FROM Film
Where ( p_title is null or Film.title = p_title )
AND ( p_country is null or Film.country = p_country )
AND ( p_language is null or Film.language = p_language )
AND ( p_category is null or Film.category = p_category );
END;
The best way to accomplish this is to use dynamic SQL. You can conditionally concatenate the correct filters. You will also want to concatenate an alternate version for when no value was provided.
For example, the following allows you to either filter, or put in a statement that the compiler will ignore but still has the correct number of bind variables in the dynamic SQL.
CREATE OR REPLACE PROCEDURE MyProcerdure
(
title file.title%TYPE,
country file.country%TYPE,
language file.language%TYPE,
category file.category%TYPE,
refCursor OUT SYS_REFCURSOR
) IS
l_stmt VARCHAR2(4000);
BEGIN
l_stmt := 'SELECT f.title AS filetitle,'||
' f.language AS language,'||
' f.category'||
' FROM file f'||
' WHERE 1 = 1';
IF title IS NOT NULL THEN
l_stmt := l_stmt || ' AND f.title = :title';
ELSE
l_stmt := l_stmt || ' AND (1=1 OR :title IS NULL)';
END IF;
-- The others would be done similarly
OPEN refCursor FOR l_stmt USING title, -- The others would go the same order as above
END;
/
Whenever the length of string l_long_string is above 4000 characters, the following code is throwing an error:
ORA-01460: unimplemented or unreasonable conversion requested
Instead of the nested regexp_substr query, when I try to use
SELECT column_value
FROM TABLE(l_string_coll)
it throws:
ORA-22905: cannot access rows from a non-nested table item
How can I modify the dynamic query?
Notes:
- l_string_coll is of type DBMS_SQL.VARCHAR2S, and comes as input to my procedure (here, i have just shown as an anonymous block)
- I'll have to manage without creating a User-defined Type in DB schema, so I am using the in-built DBMS_SQL.VARCHAR2S.
- This is not the actual business procedure, but is close to this. (Can't post the original)
- Dynamic query has to be there since I am using it for building the actual query with session, current application schema name etc.
/*
CREATE TABLE some_other_table
(word_id NUMBER(10), word_code VARCHAR2(30), word VARCHAR2(255));
INSERT INTO some_other_table VALUES (1, 'A', 'AB');
INSERT INTO some_other_table VALUES (2, 'B', 'BC');
INSERT INTO some_other_table VALUES (3, 'C', 'CD');
INSERT INTO some_other_table VALUES (4, 'D', 'DE');
COMMIT;
*/
DECLARE
l_word_count NUMBER(10) := 0;
l_counter NUMBER(10) := 0;
l_long_string VARCHAR2(30000) := NULL;
l_dyn_query VARCHAR2(30000) := NULL;
l_string_coll DBMS_SQL.VARCHAR2S;
BEGIN
-- l_string_coll of type DBMS_SQL.VARCHAR2S comes as Input to the procedure
FOR i IN 1 .. 4100
LOOP
l_counter := l_counter + 1;
l_string_coll(l_counter) := 'AB';
END LOOP;
-- Above input collection is concatenated into CSV string
FOR i IN l_string_coll.FIRST .. l_string_coll.LAST
LOOP
l_long_string := l_long_string || l_string_coll(i) || ', ';
END LOOP;
l_long_string := TRIM(',' FROM TRIM(l_long_string));
dbms_output.put_line('Length of l_long_string = ' || LENGTH(l_long_string));
/*
Some other tasks in PLSQL done successfully using the concatenated string l_long_string
*/
l_dyn_query := ' SELECT COUNT(*)
FROM some_other_table
WHERE word IN ( SELECT TRIM(REGEXP_SUBSTR(str, ''[^,]+'', 1, LEVEL)) word
FROM ( SELECT :string str FROM SYS.DUAL )
CONNECT BY TRIM(REGEXP_SUBSTR(str, ''[^,]+'', 1, LEVEL)) IS NOT NULL )';
--WHERE word IN ( SELECT column_value FROM TABLE(l_string_coll) )';
EXECUTE IMMEDIATE l_dyn_query INTO l_word_count USING l_long_string;
dbms_output.put_line('Word Count = ' || l_word_count);
EXCEPTION
WHEN OTHERS
THEN
dbms_output.put_line('SQLERRM = ' || SQLERRM);
dbms_output.put_line('FORMAT_ERROR_BAKCTRACE = ' || dbms_utility.format_error_backtrace);
END;
/
How can I modify the dynamic query?
First of all. Based on the code you've provided, there is absolutely no need to use dynamic, native or DBMS_SQL dynamic SQL at all.
Secondly, SQL cannot operate on "strings" that are greater than 4K bytes in length(Oracle versions prior to 12c), or 32K bytes(Oracle version 12cR1 and up, if MAX_STRING_SIZE initialization parameter is set to EXTENDED).
PL/SQL, on the other hand, allows you to work with varchar2() character strings that are greater than 4K bytes (up to 32Kb) in length. If you just need to count words in a comma separated sting, you can simply use regexp_count() regular expression function(Oracle 11gr1 and up) as follows:
set serveroutput on;
set feedback off;
clear screen;
declare
l_str varchar2(100) := 'aaa,bb,ccc,yyy';
l_numOfWords number;
begin
l_numOfWords := regexp_count(l_str, '[^,]+');
dbms_output.put('Number of words: ');
dbms_output.put_line(to_char(l_numOfWords));
end;
Result:
Number of words: 4
In the below oracle sql package body, I receive a "SQL Statement ignored" error and cannot determine the cause. Please see the SELECT statement of the dborLoans_cursor in the PROCEDURE updateLoansInLdcTab in the statement below:
create or replace
PACKAGE body PK_DBORUFT_SYNC AS
PROCEDURE mainProg(v_beginDate DATE, v_endDate DATE) IS
BEGIN
updateLoansInLdcTab(v_beginDate,v_endDate);
END mainProg;
FUNCTION searchForLdcToUpdate(v_beginDate DATE, v_endDate DATE) RETURN type_ref_cursor IS
v_ldcLoan type_ref_cursor;
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
OPEN v_ldcLoan FOR
SELECT loan_id
FROM ldc.ldc_rel_tab
WHERE loan_id NOT IN
(SELECT loan_id
FROM dbor.vw_ldc_data dbor
WHERE dbor.closing_agent IS NOT NULL
AND dbor.closing_agent_phone IS NOT NULL
AND dbor.lock_expiration_date > sysdate)
AND TO_CHAR(request_date, 'MM/DD/YYYY') >= v_beginDate
AND TO_CHAR(request_date, 'MM/DD/YYYY') <= v_endDate;
RETURN v_ldcLoan;
END searchForLdcToUpdate;
PROCEDURE updateLoansInLdcTab(v_beginDate DATE, v_endDate DATE) is
TYPE dborLdcData IS TABLE OF dbor.vw_ldc_data%ROWTYPE;
v_ldcLoan_type_rec type_ref_cursor;
v_ldcLoanCursor_type ldcLoanCursor_type;
dborReference dborLdcData;
v_LDC_LOANID VARCHAR2(10);
v_LOAN_ID VARCHAR2(10);
v_BANKLINE VARCHAR2(20);
v_CHANNEL VARCHAR2(20);
v_PROPERTY_TYPE VARCHAR2(10);
v_STATE VARCHAR2(2);
v_STREET_NAME VARCHAR2(64);
v_FIRST_NAME VARCHAR2(64);
v_LAST_NAME VARCHAR2(64);
v_CLOSING_AGENT VARCHAR2(50);
v_CLOSING_AGENT_PHONE VARCHAR2(15);
v_REGION_CODE VARCHAR2(20);
v_CLPP_FLAG VARCHAR2(1);
v_INSTRUMENT_NAME VARCHAR2(30);
v_BROKER_OFFICER VARCHAR2(30);
v_COST_CENTER VARCHAR2(10);
v_PREPARED_BY VARCHAR2(30);
v_BUYPRICE NUMBER(9,4);
v_SRP NUMBER(8,3);
v_TOTAL_BUYPRICE NUMBER(9,4);
v_TOTAL_SRP NUMBER(8,3);
v_BRANCH_NAME VARCHAR2(30);
v_LOCK_EFFECTIVEDATE DATE;
dbor_count NUMBER;
CURSOR dborLoans_cursor IS
SELECT P.loan_id,
P.property_type,
P.state,
P.street_name,
P.close_date,
P.loan_purpose,
P.borrower_last_name,
P.borrower_first_name,
P.closing_agent,
P.closing_agent_phone,
P.region_code,
P.clpp,
P.instrument_name,
P.broker_officer,
P.lock_effective_date,
P.channel,
NVL(P.buyprice, 0) buyPrice
FROM dbor.vw_ldc_data P
LEFT JOIN dbor.wlnprogram W
ON upper(P.instrument_name) = W.ln_pgm
LEFT JOIN
(SELECT A.loan_id FROM ldc.ldc_rel_tab A WHERE A.ldc_status='LDC_PENDING'
) pend ON pend.loan_id = p.loan_id
LEFT JOIN
(SELECT DISTINCT A.loan_id
FROM ldc.ldc_rel_tab A, ldc.ldc_request_rel_tab B
WHERE A.ldc_status IN ('LDC_PENDING', 'DISBURSED','COMPLETE','RECON_PENDING','SUBMITTED','DISBURSEPAYOFF','VOIDREQUEST','FUNDS_REQUESTED')
AND A.ldc_id = B.ldc_id
AND (B.funding_reason = 'DL Payoff' OR B.funding_reason ='Original Disbursement')
) disbursed ON disbursed.loan_Id = p.loan_id
LEFT JOIN
(SELECT name, phone, agent_id, street1, city, zip, state FROM dbor.WCLOS_AGNT) wagnt
ON wagnt.agent_id=p.loan_id
LEFT JOIN
(SELECT loan,
company_name,
phone_phn,
street,
city,
zip_code,
state
FROM DBOR.WLOAN_PARTY
WHERE type='4'
) wloan ON wloan.loan =p.loan_id
WHERE P.closing_agent IS NOT NULL
AND p.loan_id not in (SELECT loan_id FROM ldc.ldc_rel_tab)
AND P.closing_agent_phone IS NOT NULL
AND P.lock_expiration_date > sysdate ;
v_dborLdcData dbor.vw_ldc_data%ROWTYPE;
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
dborReference := dborLdcData();
v_ldcLoanCursor_type := searchForLdcToUpdate(v_beginDate, v_endDate);
dbor_count := 0;
WHILE dborLoans_cursor%FOUND LOOP
FETCH dborLoans_cursor INTO v_dborLdcData;
dbor_count := dbor_count + 1;
v_LOAN_ID := v_dborLdcData.LOAN_ID;
v_PROPERTY_TYPE := v_dborLdcData.property_type;
v_STATE := v_dborLdcData.state;
v_STREET_NAME := v_dborLdcData.street_name;
v_LAST_NAME := v_dborLdcData.borrower_last_name;
v_FIRST_NAME := v_dborLdcData.borrower_first_name;
v_CLOSING_AGENT := v_dborLdcData.closing_agent;
v_CLOSING_AGENT_PHONE := v_dborLdcData.closing_agent_phone;
v_CLPP_FLAG := v_dborLdcData.clpp;
v_INSTRUMENT_NAME := v_dborLdcData.INSTRUMENT_NAME;
v_BROKER_OFFICER := v_dborLdcData.BROKER_OFFICER;
v_CHANNEL := v_dborLdcData.CHANNEL;
EXECUTE IMMEDIATE 'SELECT region_code FROM dbor.Branch WHERE branch_name = '||v_dborLdcData.CHANNEL INTO v_REGION_CODE;
EXECUTE IMMEDIATE 'SELECT cost_center FROM ldc.REF_BANKLINE_REL WHERE channel = '||v_dborLdcData.CHANNEL INTO v_COST_CENTER;
EXECUTE IMMEDIATE 'SELECT bankline FROM ldc.REF_BANKLINE_REL WHERE channel = '||v_dborLdcData.CHANNEL INTO v_BANKLINE;
v_LOCK_EFFECTIVEDATE := v_dborLdcData.lock_effective_date;
v_BUYPRICE := v_dborLdcData.buyPrice;
LOOP
FETCH v_ldcLoan_type_rec INTO v_LDC_LOANID;
EXECUTE IMMEDIATE
'update ldc.ldc_rel_tabtest
set loan_id = ' ||''''|| v_LOAN_ID||''''||
',bankline = ' ||''''|| v_BANKLINE||''''||
',channel = ' ||''''||v_CHANNEL||''''||
',PROPERTY_TYPE= ' ||''''||v_PROPERTY_TYPE||''''||
',STATE = ' ||''''||v_STATE||''''||
',STREET_NAME = ' ||''''||v_STREET_NAME||''''||
',BORROWER_NAME = ' ||''''||v_LAST_NAME||','||''''||v_FIRST_NAME||''''||
',CLOSING_AGENT = ' ||''''||v_CLOSING_AGENT||''''||
',CLOSING_AGENT_PHONE = ' ||''''||v_CLOSING_AGENT_PHONE||''''||
',REGION_CODE = ' ||''''||v_REGION_CODE||''''||
',CLPP_FLAG = ' ||''''||v_CLPP_FLAG||''''||
',INSTRUMENT_NAME = ' ||''''||v_INSTRUMENT_NAME||''''||
',BROKER_OFFICER = ' ||''''||v_BROKER_OFFICER||''''||
',COST_CENTER = ' ||''''||v_COST_CENTER||''''||
',BUYPRICE = ' ||v_BUYPRICE ||
' where loan_id = ' ||v_LDC_LOANID;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END updateLoansInLdcTab;
END PK_DBORUFT_SYNC;
After quick glance at this (without running it), I would have though there are errors on the lines below as you have not put quotes around the value which is being concatenated in:
EXECUTE IMMEDIATE 'SELECT region_code FROM dbor.Branch WHERE branch_name = '||v_dborLdcData.CHANNEL INTO v_REGION_CODE;
EXECUTE IMMEDIATE 'SELECT cost_center FROM ldc.REF_BANKLINE_REL WHERE channel = '||v_dborLdcData.CHANNEL INTO v_COST_CENTER;
EXECUTE IMMEDIATE 'SELECT bankline FROM ldc.REF_BANKLINE_REL WHERE channel = '||v_dborLdcData.CHANNEL INTO v_BANKLINE;
However, from the comments above you seem to have gotten it working.
The bigger problem in this code is why are you using execute immediate at all? You don't need to, and worse you have created non scalable code as the three execute immediate statements above and the big update are not using bind variables. In PLSQL if you avoid using execute_immediate, you don't need to worry about binds at all, PLSQL does it all for you automagically.
Try converting the execute immediate select into something like:
select region_code
into v_region_code
from dbor.branch
where branch_name = v_dborLdcData.CHANNEL;
That will work find and fix the bind variable problem. Then do the same to the update:
update ldc.ldc_rel_tabtest
set loan_id = v_LOAN_ID
bankline = v_bank_line
...
...
where loan_id = v_LDC_LOANID;
The code will be simpler, easier to find errors in the SQL and more scalable.
Problem was due to missing grant on DBOR.WLOAN_PARTY.