#oracle #plsql #dynamic-sql
Вопрос:
Я создал пакет и вызываю его процедуру в другом анонимном блоке. Когда я вызываю процедуру, возникает ошибка отсутствия правильных скобок. Я продолжаю получать эту ошибку, но не нашел ни одной отсутствующей скобки.
Пакет
CREATE OR REPLACE PACKAGE BODY downloadInterface
AS
PROCEDURE getList (
pitxt_cc IN stand_value.val01%TYPE,
pitxt_language IN stand_value.language%TYPE,
piint_pn IN prt_req.pol_n%TYPE DEFAULT NULL,
piint_cn IN prt_req.cal_no%TYPE DEFAULT NULL,
piint_ctn IN prt_req.nm_id_no%TYPE DEFAULT NULL,
potab_doc_list OUT custDocTab,
potxt_message_id OUT error_det.ERROR_CODE%TYPE,
potxt_message_text OUT error_det.ERROR_TEXT%TYPE,
potxt_error_text OUT error_det.ERROR_TEXT%TYPE)
AS
ltxt_SQL_TYPE_stmt VARCHAR2 (32000 CHAR);
ltxt_SQL_stmt_f VARCHAR2 (32000 CHAR);
ltxt_SQL_stmt_s VARCHAR2 (32000 CHAR);
ltxt_SQL_stmt_t VARCHAR2 (32000 CHAR);
lint_error_log_id error_det.error_id%TYPE;
lint_agnt_id gnw_cla_user_reg.agnt_id%TYPE;
ltxt_group_id gnw_cla_user_reg.GROUP_ID%TYPE;
BEGIN
potab_doc_list := NEW custDocTab ();
ltxt_SQL_stmt_f :=
'SELECT ci.pol_n,
p.c01 agr_no,
ci.cal_no,
ci.nm_id_no,
NULL emailId,
''TIT'' doc_det,
ci.reqt_Id,
pr.reqt_emode reque_status,
ci.event_type eventType,
ci.wrt_date docprtDate,
pr.reqt_date docreqtDate,
pr.prt_job prtJob,
(pr.tter_salut || '' '' || pr.addressee || '', '' || pr.area_code)
addressee,
pr.language language,
ci.prgm_id tterId,
ci.file_name prtFile,
pp.description file_name,
lc.val08 description,
lc.val07 document_type,
fn.val02 orig_filename,
fn.val03 TYPE,
fn.val06 friendly_filename,
fn.val07 friendly_type,
fn.val08 scope,
NVL (fn.val06, ''Generic Title'') title,
pp.business_area,
(SELECT description
FROM stand_value_cb
WHERE table_name =''BUSINESS_AREA''
AND language = :pitxt_language
AND code = pp.business_area)
ba_description,
pp.activity,
(SELECT description
FROM stand_value_cb
WHERE table_name = ''ACTIVITY''
AND language = :pitxt_language
AND code = pp.activity)
act_description
FROM event_item ci,
prt_prgm pp,
polcy p,
prt_req pr,
(SELECT *
FROM stand_value
WHERE table_name = ''DOC_NAMES''
AND language = :pitxt_language) fn,
(SELECT DISTINCT table_name,
val03,
val07,
val08
FROM stand_value
WHERE table_name = ''tter_CONFIGURATION'') lc, ';
ltxt_SQL_stmt_s := ' WHERE ci.tter_location = ''DISK''
AND ci.prgm_id = pp.prgm_id
AND ci.event_type = ''LTOT''
AND ci.pol_n = p.pol_n
AND p.pre_seq_no IS NULL
AND ci.reqt_id = pr.reqt_id
AND pp.prgm_id = lc.val03
AND pp.prgm_id = fn.val04( )
AND fn.val08 IS NOT NULL';
ltxt_SQL_TYPE_stmt :=
' SELECT custDocTab
( polcyNumber
, alan
, clmNumber
, cstmNumber
, emailId
, docSource
, reqtId
, reqtStatus
, eventType
, docprtDate
, docreqtDate
, prtJob
, addressee
, language
, tterId
, prtFile
, file_name
, description
, document_type
, orig_filename
, type
, friendly_filename
, friendly_type
, scope
)
FROM (';
IF piint_cust_no IS NOT NULL
THEN
SELECT agnt_id, GROUP_ID
INTO lint_agnt_id, ltxt_group_id
FROM gnw_cla_user_reg
WHERE id_no = piint_cust_no;
IF (generic_cl.iseIvalpl (pitxt_cc => pitxt_cc,
piint_agnt_Id => lint_agnt_id,
pitxt_group_id => ltxt_group_id))
THEN
cript_idt.set_cript_idt (
pitxt_cc => pitxt_cc,
pinum_id_no_orig => piint_cust_no,
piint_agnt_id => lint_agnt_id,
pitxt_group_id => ltxt_group_id,
potxt_message_id => potxt_message_id,
potxt_message_text => potxt_message_text,
potxt_error_text => potxt_error_text);
IF ( (potxt_message_id || potxt_message_text || potxt_error_text)
IS NOT NULL)
THEN
-- Abort.
RETURN;
END IF;
ltxt_SQL_stmt_t :=
' AND ci.nm_id_no = nt.id_no( )
AND nt.id_no = :piint_cust_no
AND pp.business_area =
event
WHEN fn.val07 = ''Claims'' THEN ''CL''
WHEN fn.val07 = ''polcy'' THEN ''PO''
END)';
EXECUTE IMMEDIATE
ltxt_SQL_TYPE_stmt
|| ltxt_SQL_stmt_f
|| 'name_idt nt'
|| ltxt_SQL_stmt_s
|| ltxt_SQL_stmt_t
BULK COLLECT INTO potab_doc_list
USING IN pitxt_language,
pitxt_language,
pitxt_language,
piint_cust_no;
ELSE
EXECUTE IMMEDIATE
ltxt_SQL_TYPE_stmt
|| ltxt_SQL_stmt_f
|| 'name_dup nt'
|| ltxt_SQL_stmt_s
|| ltxt_SQL_stmt_t
BULK COLLECT INTO potab_doc_list
USING IN pitxt_language,
pitxt_language,
pitxt_language,
piint_cust_no;
END IF;
ELSIF piint_pol_n IS NOT NULL AND piint_cal_no IS NULL
THEN
EXECUTE IMMEDIATE
ltxt_SQL_TYPE_stmt
|| ltxt_SQL_stmt_f
|| 'name_dup nt'
|| ltxt_SQL_stmt_s
|| 'and ci.pol_n = :piint_pol_n
and pp.business_area = ''PO''
AND ci.cal_no is null)'
BULK COLLECT INTO potab_doc_list
USING IN pitxt_language,
pitxt_language,
pitxt_language,
piint_pol_n;
ELSIF piint_cal_no IS NOT NULL
THEN
EXECUTE IMMEDIATE
ltxt_SQL_TYPE_stmt
|| ltxt_SQL_stmt_f
|| 'name_dup'
|| ltxt_SQL_stmt_s
|| 'and ci.pol_n = :piint_cal_no)'
BULK COLLECT INTO potab_doc_list
USING IN pitxt_language,
pitxt_language,
pitxt_language,
piint_cal_no;
END IF;
EXCEPTION
WHEN OTHERS
THEN
z_error ('Error while fetching documents =' || SQLERRM);
potxt_message_id := 'GCDDIGDL009';
lint_error_log_id :=
utl_gss.save_error (ptxt_cc => pitxt_cc,
ptxt_error_code => potxt_message_id,
ptxt_error_text => potxt_message_text);
potxt_error_text :=
utl_gss.format_fatal_error (
pint_error_log_id => lint_error_log_id);
END getList;
END downloadInterface;
/
Блок для вызова процедуры, в которой возникает ошибка с отсутствующими скобками
DECLARE
potab_doc_listt custDocTab;
potxt_message_idt error_det.ERROR_CODE%TYPE;
potxt_message_textt error_det.ERROR_TEXT%TYPE;
potxt_error_textt error_det.ERROR_TEXT%TYPE;
BEGIN
downloadInterface.getList ('KL',
'AIA',
NULL,
NULL,
521749999,
potab_doc_listt,
potxt_message_idt,
potxt_message_textt,
potxt_error_textt);
END;
Ошибка
ORA-20210: generic_cl.iseIvalpl Error while fetching documents =ORA-00907: missing right parenthesis
ORA-06512: at "Z_ERROR", line 60
ORA-06512: at "downloadInterface", line 226
ORA-06512: at line 9
После размещения журналов в нескольких местах я обнаружил, что ошибка возникает при первом EXECUTE IMMEDIATE
утверждении, которое приведено ниже
EXECUTE IMMEDIATE
ltxt_SQL_TYPE_stmt
|| ltxt_SQL_stmt_f
|| 'name_idt nt'
|| ltxt_SQL_stmt_s
|| ltxt_SQL_stmt_t
BULK COLLECT INTO potab_doc_list
USING IN pitxt_language,
pitxt_language,
pitxt_language,
piint_cust_no;
Комментарии:
1. Вы пытались свести это к минимальному воспроизводимому примеру?
2. Вам лучше использовать современный синтаксис соединения ANSI вместо старого синтаксиса соединения Oracle. Используйте
DBMS_OUTPUT.PUT_LINE(...)
в командной строке перед выполнением команды. Ошибка кажется совершенно очевидной.
Ответ №1:
Динамический SQL сложен, потому что он превращает ошибки компиляции в ошибки времени выполнения. Вот что здесь происходит. Ваши куски SQL после сборки генерируют недопустимый SQL.
Отладка динамического SQL-это боль в шее. У вас должна быть переменная для всего оператора, затем используйте DBMS_OUTPUT.PUT_LINE, чтобы вывести все на экран. Это облегчает определение синтаксического цветка(ов).
Или же напишите инструкции в виде статического SQL, убедитесь, что они выполняются, а затем преобразуйте их в фрагменты.
Наконец, вы можете получить это бесплатно. Строка, назначенная ltxt_SQL_stmt_t
, содержит событие word, когда компилятор, вероятно, ожидает СЛУЧАЙ.