2015-08-17 5 views
0

Я пытаюсь выполнить хранимую процедуру, я застрял в 54-й строке «EXECUTE IMMEDIATE» в основном. Я передаю инструкцию SQL в цикл. Пожалуйста, дайте мне знать, что я что-то делаю неправильно?Я получаю эту ошибку, когда когда-либо выполняю свою хранимую процедуру «PLS-00103»

CREATE OR REPLACE Procedure DE_DUP_PROC (Dy_File_Name in USER_TABLES.table_name%type, 
             SUPPLIER_CD in varchar2, 
             EXT_PHARMA_ID in varchar2, 
             FLAG_VALUE in varchar2, 
             DE_REC_COUNT out NUMBER) --RETURN NUMBER 
AS 
    SEQ_NO_SHO Number(38);       --EEEE 
    WYYYYNNN VARCHAR2(250) := 'W2015021'; 
    YYYYNNN VARCHAR2(10); 
    CUR_DATE Date; 
    --De_Rec_Count Number(38) := 3456; 
    DE_DUB_OUTPUT_FILE VARCHAR2(100); 

    /*CURSOR De_DUB_CUR IS */ 
    DE_DUB_SQL_STATMNT VARCHAR2(3000) := 'SELECT S.TRANS_GUID AS OLD_TRANS_GUID, 
    H.TRANS_GUID AS NEW_TRANS_GUID, 
    CASE 
     WHEN H.TRANS_GUID IS NULL 
     THEN 0 
     ELSE 1 
    END as TRN_STAT,P.INTR_PHARMACY_ID as INT_PHARMACY_ID ,S.EXTRNL_PHARMACY_ID as EXT_PHARMACY_ID ,S.PHARMACY_NM as PHARMACY_NAME ,S.PHARMACY_ADDR as PHARMACY_ADDRESS, 
     S.SUPPLIERS_PSCR_DRUG_CD as SP_PSCR_DRUG_CD, S.PSCR_DRUG_IPU_CD as PS_DRUG_IPU_CD,''IPU'' as IPU_Value, S.PSCR_DRUG_DESC as PS_DRUG_DESC, 
     S.DSPNSD_DRUG_PACK_SIZE as DS_DRUG_PACK_SIZE, S.RX_ID as R_ID, S.RX_ITEM_SEQ as R_ITEM_SEQ, S.RX_REPEAT_STATUS as R_REPEAT_STATUS, S.RX_TYP as R_TYPE, 
     S.EXMT_STATUS as EX_STATUS,S.PSCR_QTY as PS_QTY, S.NRSG_HM_IND as NR_HM_IND,S.RX_DSPNSD_DT as R_DSPNSD_DT, S.RX_DSPNSD_TM as R_DSPNSD_TM, 
     S.SUPPLIERS_DSPNSD_DRUG_CD as SP_DSPNSD_DRUG_CD, S.DSPNSD_DRUG_IPU_CD as DS_DRUG_IPU_CD, ''IPU'' as IPU_Value2,S.DSPNSD_DRUG_DESC as DS_DRUG_DESC, 
     S.GENERIC_USE_MARKER as GC_USE_MARKER, S.DSPNSD_UNIT_OF_QTY as DS_UNIT_OF_QTY, S.DSPNSD_QTY as DS_QTY, ''EUR'' as EUR_Value1,S.COST_OF_DSPNSD_QTY as CT_OF_DSPNSD_QTY , 
     S.VERBOSE_DOSAGE as VER_DOSAGE FROM 
     (SELECT stg.*, row_number() over (partition BY key_clmns_hash ORDER BY 1) AS RN FROM '|| Dy_File_Name ||' stg) s 
     LEFT JOIN ps_pharmacy p 
     ON s.extrnl_pharmacy_id = p.extrnl_pharmacy_id 
     LEFT JOIN ps_rx_hist H 
     ON h.key_clmns_hash  = s.key_clmnS_hash 
     AND h.rx_dspnsd_dt   = s.rx_dspnsd_dt 
     AND s.supplier_pharmacy_cd = h.SUPPLIER_PHARMACY_CD 
     AND s.detl_clmns_hash <> h.detl_clmns_hash 
     WHERE s.RN     = 1'; 
BEGIN 
    EXECUTE IMMEDIATE 'SELECT count(*) into DE_REC_COUNT 
         FROM (SELECT stg.*, row_number() over (partition BY key_clmns_hash ORDER BY 1) AS RN FROM '|| Dy_File_Name ||' stg) s 
         LEFT JOIN ps_pharmacy p ON s.extrnl_pharmacy_id = p.extrnl_pharmacy_id LEFT JOIN ps_rx_hist H ON h.key_clmns_hash = s.key_clmnS_hash 
         AND h.rx_dspnsd_dt = s.rx_dspnsd_dt AND s.supplier_pharmacy_cd = h.SUPPLIER_PHARMACY_CD AND s.detl_clmns_hash <> h.detl_clmns_hash WHERE S.RN = 1'; 

    IF DE_REC_COUNT > 0 THEN 

    --select sysdate into CUR_DATE from dual; 
    --select PROC_PD_CD into WYYYYNNN from PS_ADMIN.PS_PROC_PD where PD_STRT_DT <= CURRENT_DATE and PD_END_DT >= CURRENT_DATE; 
    --select PROC_PD_CD into WYYYYNNN from PS_ADMIN.PS_PROC_PD where PD_STRT_DT <= CURRENT_DATE and PD_END_DT >= CURRENT_DATE; -- PD_STRT_DT<='16-AUG-15' and PD_STRT_DT >= '16-AUG-15'; 
    select replace(WYYYYNNN,'W','') into YYYYNNN from dual; 
    SELECT PS_GET_PROC_PD(SUPPLIER_CD,EXT_PHARMA_ID,YYYYNNN) into SEQ_NO_SHO FROM DUAL; 
    select 'LRXIE'||FLAG_VALUE||'10_'||SUPPLIER_CD||'_'||EXT_PHARMA_ID||'_'||WYYYYNNN||'_'||SEQ_NO_SHO||'_'||DE_REC_COUNT||'.TXT' into DE_DUB_OUTPUT_FILE from dual; 

    --DBMS_OUTPUT.PUT_LINE(De_Dub_Output_File); 

    FOR De_Dub_rec IN EXECUTE IMMEDIATE DE_DUB_SQL_STATMNT 
    LOOP 
     dbms_output.enable(100000); 

     DBMS_OUTPUT.PUT_LINE ('"' || De_Dub_rec.OLD_TRANS_GUID || '"|"' || De_Dub_rec.NEW_TRANS_GUID || '"|' || De_Dub_rec.TRN_STAT || '|' || De_Dub_rec.INT_PHARMACY_ID || '|' || De_Dub_rec.EXT_PHARMACY_ID || '|"' || 
     De_Dub_rec.PHARMACY_NAME|| '"|"' || De_Dub_rec.PHARMACY_ADDRESS || '"|' || De_Dub_rec.SP_PSCR_DRUG_CD || '|' || De_Dub_rec.PS_DRUG_IPU_CD || '|"' || De_Dub_rec.IPU_Value || '"|"' || 
     De_Dub_rec.PS_DRUG_DESC || '"|' || De_Dub_rec.DS_DRUG_PACK_SIZE || '|"' || De_Dub_rec.R_ID || '"|' || De_Dub_rec.R_ITEM_SEQ || '|' || De_Dub_rec.R_REPEAT_STATUS || '|"' || 
     De_Dub_rec.R_TYPE || '"|"' || De_Dub_rec.EX_STATUS || '"|' || De_Dub_rec.PS_QTY || '|' || De_Dub_rec.NR_HM_IND || '|"' || De_Dub_rec.R_DSPNSD_DT || '"|' || De_Dub_rec.R_DSPNSD_TM || '|' || 
     De_Dub_rec.SP_DSPNSD_DRUG_CD || '|' || De_Dub_rec.DS_DRUG_IPU_CD|| '|"' || De_Dub_rec.IPU_Value2 || '"|"' || De_Dub_rec.DS_DRUG_DESC|| '"|' || De_Dub_rec.GC_USE_MARKER|| '|"' || 
     De_Dub_rec.DS_UNIT_OF_QTY|| '"|' || De_Dub_rec.DS_QTY|| '|"' || De_Dub_rec.EUR_Value1|| '"|' || De_Dub_rec.CT_OF_DSPNSD_QTY || '|"' || De_Dub_rec.VER_DOSAGE || '"'); 
    END LOOP; 

    DE_REC_COUNT :=0; 
    ELSE 
    DE_REC_COUNT :=1; 
    END IF; 

END DE_DUP_PROC; 
/

Я получаю эту ошибку:

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
58/44 PLS-00103: Encountered the symbol "IMMEDIATE" when expecting one 
     of the following: 
     . (* @ % & - +/at loop mod remainder rem .. 
     <an exponent (**)> || multiset 
     The symbol ". was inserted before "IMMEDIATE" to continue. 

ответ

2

В коде есть две ошибки. Первая - это ошибка компилятора, которую вы получаете. Вы не можете использовать execute immediate в петле for (то есть clearly documented in the manual)

Вам нужно открыть курсор, а затем прокрутить курсор. Таким образом, вместо

FOR De_Dub_rec IN EXECUTE IMMEDIATE DE_DUB_SQL_STATMNT 

вам нужно использовать что-то вроде этого:

OPEN De_Dub_cursor FOR DE_DUB_SQL_STATMNT; 
LOOP 
    FETCH De_Dub_cursor INTO de_dub_cursor_record; 
    EXIT WHEN cv%NOTFOUND; 

    ... do your stuff here 

END LOOP; 

Конечно, вы должны объявить курсор De_Dub_cursor и переменную записи de_dub_cursor_record. Обратите внимание, что переменные записи должны быть определены со всеми столбцами, которые возвращают ваш результат (что по существу требует определения нового TYPE, если я не ошибаюсь)

Вторая ошибка, которую вы не увидите, пока не будет запущена код. У вас есть INTO variable статья внутри Ваша строка SQL для первого EXECUTE IMMEDIATE. Это не будет работать. Это предложение нельзя использовать. Вам нужно удалить часть into DE_REC_COUNT из строкового литерала и использовать предложение INTO в качестве опции для оператора execute immediate. Что-то вроде этого:

EXECUTE IMMEDIATE 'SELECT count(*) FROM ....' 
    INTO DE_REC_COUNT; 

Unrelated ваших проблем, но select ... from dual можно заменить простым заданием.

Таким образом, вместо

select replace(WYYYYNNN,'W','') into YYYYNNN from dual; 

использование

YYYYNNN := replace(WYYYYNNN,'W',''); 

или вместо:

SELECT PS_GET_PROC_PD(SUPPLIER_CD,EXT_PHARMA_ID,YYYYNNN) into SEQ_NO_SHO FROM DUAL; 
select 'LRXIE'||FLAG_VALUE||'10_'||SUPPLIER_CD||'_'||EXT_PHARMA_ID||'_'||WYYYYNNN||'_'||SEQ_NO_SHO||'_'||DE_REC_COUNT||'.TXT' into DE_DUB_OUTPUT_FILE from dual; 

использование

SEQ_NO_SHO := PS_GET_PROC_PD(SUPPLIER_CD,EXT_PHARMA_ID,YYYYNNN); 
DE_DUB_OUTPUT_FILE := 'LRXIE'||FLAG_VALUE||'10_'||SUPPLIER_CD||'_'||EXT_PHARMA_ID||'_'||WYYYYNNN||'_'||SEQ_NO_SHO||'_'||DE_REC_COUNT||'.TXT'; 
+0

более д ответ на мой запрос, а также лучшее решение с помощью курсора. –

0

Во-первых, должно быть execute immediate 'select count(*) from ...' into DE_REC_COUNT;

Вот что я вижу в первом сканировании, но потерпеть неудачу на втором выполнить немедленно.

Там вы должны создать коллекцию и выполнить немедленный запрос и сбор массы в эту коллекцию. Затем вы должны зациклиться на этой коллекции и выполнить работу, которую вы выполняете (материал dbms_output).