2016-01-07 36 views
0

我有下面的存儲過程,因此我得到一個錯誤,因爲缺少關鍵字。我試圖通過將它們放入變量來運行sql語句,因爲我在sql查詢中動態使用了數據庫鏈接。在合併查詢中使用case statement時出現錯誤。當我使用dbms輸出行打印合並查詢時,它打印完整的case語句而不是唯一的ID。Oracle在where子句中缺少關鍵字使用大小寫聲明

PROCEDURE     "EXT_SOAP_MONITORING"(IN_DB_LINK IN varchar2) AS 

    LAST_SM_ID Number := 0; 
    LAST_CAPT_DATE DATE; 
    LAST_SM_ID_MB Number := 0; 
    LAST_CAPT_DATE_MB DATE; 
    l_sql VARCHAR2(5000); 
    l_sql1 VARCHAR2(5000); 
    DB_CONNECTION_NAME VARCHAR2(100); 

    BEGIN 

    Select DB_LINK INTO DB_CONNECTION_NAME FROM RATOR_MONITORING_CONFIGURATION.DB_CONNECTION WHERE DB_LINK = IN_DB_LINK; 
    --DELETE FROM TEMP_SOAP_MONITORING table before inserting new data into this table 
    EXECUTE IMMEDIATE 'TRUNCATE TABLE TEMP_SOAP_MONITORING'; 

    -- first retrieve the last id (of the newest record) which has been imported at last extraction 
    --FONIC 
    SELECT LAST_TASK_ID INTO LAST_SM_ID FROM CAPTURING where DB_TABLE='TEMP_SOAP_MONITORING' and DB ='FONIC_RETAIL'; 
    SELECT CAPTURING_DATE INTO LAST_CAPT_DATE from CAPTURING WHERE DB_TABLE='TEMP_SOAP_MONITORING' and DB ='FONIC_RETAIL'; 

    --MB 
    SELECT LAST_TASK_ID INTO LAST_SM_ID_MB FROM CAPTURING where DB_TABLE='TEMP_SOAP_MONITORING' and DB ='MB_RETAIL'; 
    SELECT CAPTURING_DATE INTO LAST_CAPT_DATE_MB from CAPTURING WHERE DB_TABLE='TEMP_SOAP_MONITORING' and DB ='MB_RETAIL'; 

    l_sql:= 
'merge into TEMP_SOAP_MONITORING TSM 
using (
    select * from 
(select ID,REQUEST_XML,RESPONSE_XML,WEB_SERVICE_NAME,WEB_METHOD_NAME,CREATE_DATE,ERROR_CODE,ERROR_MESSAGE from 
[email protected]'||DB_CONNECTION_NAME||' WHERE 
ID > (CASE WHEN '||IN_DB_LINK||' = ''FONIC_RETAIL'' THEN ' || LAST_SM_ID || ' ELSE ' || LAST_SM_ID_MB ||' END) AND 
WEB_SERVICE_NAME =''RatorWebShopService'' and WEB_METHOD_NAME = ''placeShopOrder'') where rownum <=1000 
) data 
ON (TSM.ID = data.ID) 
when not matched then 
insert(ID,REQUEST_XML,RESPONSE_XML,WEB_SERVICE_NAME,WEB_METHOD_NAME,CREATE_DATE,ERROR_CODE,ERROR_MESSAGE,DB_LINK) 
values(data.ID,data.REQUEST_XML,data.RESPONSE_XML,data.WEB_SERVICE_NAME,data.WEB_METHOD_NAME,data.CREATE_DATE,data.ERROR_CODE,data.ERROR_MESSAGE,'||DB_CONNECTION_NAME ||')'; 

DBMS_OUTPUT.PUT_LINE('lsql' || l_sql); 

    DBMS_OUTPUT.PUT_LINE('lsql' || l_sql); 

    execute immediate l_sql; 

    END EXT_SOAP_MONITORING; 

下面是我的DBMS結果:

 merge into TEMP_SOAP_MONITORING TSM 
using (
    select * from 
(select ID,REQUEST_XML,RESPONSE_XML,WEB_SERVICE_NAME,WEB_METHOD_NAME,CREATE_DATE,ERROR_CODE,ERROR_MESSAGE from 
[email protected]_RETAIL WHERE 
ID > (CASE WHEN FONIC_RETAIL = 'FONIC_RETAIL' THEN 201601071130573261 ELSE 201601071130573261 END) AND 
WEB_SERVICE_NAME ='RatorWebShopService' and WEB_METHOD_NAME = 'placeShopOrder') where rownum <=1000 
) data 
ON (TSM.ID = data.ID) 
when not matched then 
insert(ID,REQUEST_XML,RESPONSE_XML,WEB_SERVICE_NAME,WEB_METHOD_NAME,CREATE_DATE,ERROR_CODE,ERROR_MESSAGE,DB_LINK) 
values(data.ID,data.REQUEST_XML,data.RESPONSE_XML,data.WEB_SERVICE_NAME,data.WEB_METHOD_NAME,data.CREATE_DATE,data.ERROR_CODE,data.ERROR_MESSAGE,FONIC_RETAIL) 
+0

案例表達式,而不是案例陳述... – jarlh

+0

我想你錯過了'THEN''後面的空白 – SomeJavaGuy

+0

我已經糾正了現在它顯示的ID,但仍然收到相同的錯誤。它在合併查詢中打印完整的case語句。我只是想從這種情況下獲得ID – Andrew

回答

1

以及該@KevinEsche指出THEN後失蹤的空白,你的case語句後還缺少一個AND(或OR) :

<snip> 
    || ' END) 
WEB_SERVICE_NAME =''RatorWebShopService'' <snip> -- <---- missing and/or before web_service_name 

所以,看這是你的程序的輸出,有合併聲明是撲過來,不約而同地在同一條線上兩個問題:

ID > (CASE WHEN DB_LINK = 'FONIC_RETAIL' THEN201601071130573261 ELSE END) AND 

你忘了在THEN後的空間加入THEN' || LAST_SM_ID,再加上你有沒有照顧LAST_SM_ID_MB被空。


以下是我會寫程序

procedure ext_soap_monitoring (in_db_link in varchar2) 
as 
    last_sm_id number := 0; 
    last_capt_date date; 
    last_sm_id_mb number := 0; 
    last_capt_date_mb date; 
    l_sql varchar2(5000); 
    l_sql1 varchar2(5000); 
    db_connection_name varchar2(100); 

begin 
    select db_link 
    into db_connection_name 
    from rator_monitoring_configuration.db_connection 
    where db_link = in_db_link; 

    --DELETE FROM TEMP_SOAP_MONITORING table before inserting new data into this table 
    execute immediate 'TRUNCATE TABLE TEMP_SOAP_MONITORING'; 

    -- first retrieve the last id (of the newest record) which has been imported at last extraction 
    --FONIC 
    select last_task_id, capturing_date 
    into last_sm_id, last_capt_date 
    from capturing 
    where db_table = 'TEMP_SOAP_MONITORING' 
    and db = 'FONIC_RETAIL'; 

    --MB 
    select last_task_id, capturing_date 
    into last_sm_id_mb, last_capt_date_mb 
    from capturing 
    where db_table = 'TEMP_SOAP_MONITORING' 
    and db = 'MB_RETAIL'; 

    l_sql:= 
'merge into temp_soap_monitoring tsm 
using (select * 
     from (select id, 
         request_xml, 
         response_xml, 
         web_service_name, 
         web_method_name, 
         create_date, 
         error_code, 
         error_message 
       from [email protected]'||db_connection_name||' 
       where id > (case when :db_connection_name = ''FONIC_RETAIL'' then ' || last_sm_id || ' else ' || last_sm_id_mb ||' end) 
       and web_service_name = ''RatorWebShopService'' 
       and web_method_name = ''placeShopOrder'') 
     where rownum <= 1000) data 
on (tsm.id = data.id) 
when not matched then 
insert (id, 
     request_xml, 
     response_xml, 
     web_service_name, 
     web_method_name, 
     create_date, 
     error_code, 
     error_message, 
     db_link) 
values (data.id, 
     data.request_xml, 
     data.response_xml, 
     data.web_service_name, 
     data.web_method_name, 
     data.create_date, 
     data.error_code, 
     data.error_message, 
     :db_connection_name)'; 

    dbms_output.put_line('lsql' || l_sql); 

    execute immediate l_sql using db_connection_name, db_connection_name; 

end ext_soap_monitoring; 
/

注意使用綁定變量,以消除在SQL本身的變量文字的展示位置。我知道當你從表中選擇時,你無法避免使用動態sql來添加數據庫鏈接名稱,但是你可以在其他地方使用綁定變量,這會使你的代碼不太容易進行sql注入。另請參閱我如何格式化合並語句 - 是的,它在變量中佔用更多空間,但它現在是一個更可讀的空間!

+0

嗨bonist我編輯了我的問題,並添加了數據庫管理系統的結果,正如你所說的正確的,我缺少AND或(或)案件陳述後,我已糾正,但我仍然得到相同的錯誤。 – Andrew

+0

你可以看到它的打印在合併查詢的情況下表達 – Andrew

+0

確定我將添加條件檢查NULL條件也 – Andrew