2017-06-16 85 views
0

感謝大家的幫助,我對PL/SQL非常陌生,我發現Syntax比T-SQL更具挑戰性。我有一個功能正常的PL/SQL cursor,它將我想要的內容插入到表中。下一步,我想將它包裝在一個存儲過程中,這樣我就可以傳入一個參數值,該參數值將替代腳本中看到的'MD01',並且用戶輸入任何4個字符的字符串。PL/SQL在存儲過程中包裝分層查詢

問題是當我這樣做時(簡單CREATE OR REPLACE PROCEDURE test AS)即使代碼在兩秒鐘前工作,我仍然收到一堆錯誤。我究竟做錯了什麼?以下發布的代碼段功能完美,但我不知道如何正確地將它包裝到PL/SQL中的存儲過程中。

ORA-00942:表或視圖不存在PLS-00364:循環索引變量 'EACH_REC' 使用無效ORA-00984:此處不允許柱

CREATE OR REPLACE PROCEDURE test IS 
DECLARE 
    CURSOR c1 IS SELECT * FROM 
(
SELECT 
    C.FEE_SCHEDULE 
, C.PROC 
, C.MODIFIER 
, C.MODIFIER2 
, C.PROVIDER 
, C.YMDEFF 
, C.YMDEND 
, C.NEXT_SPAN_DATE 
, C.SPAN 
, C.SPAN_FLAG 
, C.RATE 
, TO_DATE(D.YMDTRANS,'YYYYMMDD') AS YMDTRANS 
FROM 
(
SELECT 
    B.FEE_SCHEDULE 
, B.PROC 
, B.MODIFIER 
, B.MODIFIER2 
, PROVIDER 
, TO_DATE(B.YMDEFF,'YYYYMMDD') AS YMDEFF 
, TO_DATE(B.YMDEND,'YYYYMMDD') AS YMDEND 
, CASE WHEN RECURSION_LEVEL = 1 THEN NULL ELSE TO_DATE(B.T3,'YYYYMMDD')END  AS NEXT_SPAN_DATE 

, CASE WHEN B.YMDEND = '99991231' THEN NULL 
      WHEN B.RANK2 = '1' THEN NULL 
      ELSE TO_DATE(B.T3,'YYYYMMDD') - TO_DATE(B.YMDEND,'YYYYMMDD') END AS SPAN 

, CASE WHEN TO_DATE(B.T3,'YYYYMMDD') - TO_DATE(B.YMDEND,'YYYYMMDD') = '1' THEN 'CORRECT_SPAN' 
      WHEN B.YMDEND = '99991231'           THEN 'CORRECT_SPAN' 
      WHEN B.RANK2 = '1'             THEN 'CORRECT_SPAN' 
      ELSE 'GAPPED_SPAN' END AS SPAN_FLAG 
--, RANK1 
--, RECURSION_LEVEL 
, RATE 
, YMDTRANS 
FROM 
(
SELECT 
    A.* 
, CONNECT_BY_ISCYCLE AS T1 
, sys_connect_by_path(YMDEFF,' ') AS T2 
, SUBSTR(sys_connect_by_path(YMDEFF,' '),1,9) AS T3 
, LEVEL AS RECURSION_LEVEL 
FROM 
(
SELECT 
    SUBSTR(FEE_KEY,3,4)  AS FEE_SCHEDULE 
, SUBSTR(FEE_KEY,7,5)  AS PROC 
, SUBSTR(FEE_KEY,19,2) AS MODIFIER 
, SUBSTR(FEE_KEY,23,2) AS MODIFIER2 
, SUBSTR(FEE_KEY,29,12) AS PROVIDER 
, FEE_KEY 
, YMDEFF 
, YMDEND 
, YMDTRANS 
, DENSE_RANK() OVER (PARTITION BY  SUBSTR(FEE_KEY,3,4) 
, SUBSTR(FEE_KEY,7,5) 
, SUBSTR(FEE_KEY,19,2) 
, SUBSTR(FEE_KEY,23,2) 
, SUBSTR(FEE_KEY,29,12) 
ORDER BY YMDEFF) AS RANK1 

, DENSE_RANK() OVER (PARTITION BY  SUBSTR(FEE_KEY,3,4) 
, SUBSTR(FEE_KEY,7,5) 
, SUBSTR(FEE_KEY,19,2) 
, SUBSTR(FEE_KEY,23,2) 
, SUBSTR(FEE_KEY,29,12) 
ORDER BY YMDEND DESC) AS RANK2 
, RATE/100 AS RATE 

FROM AMIOWN.FEE_SCHEDULE 
WHERE 1 = 1 
AND SUBSTR(FEE_KEY,3,4) = 'MD01' 
) A 
START WITH FEE_SCHEDULE IN('MD01') 
CONNECT BY NOCYCLE 
    PRIOR RANK1   = RANK1 + 1 
AND PRIOR FEE_SCHEDULE = SUBSTR(FEE_KEY,3,4) 
AND PRIOR PROC   = SUBSTR(FEE_KEY,7,5) 
AND PRIOR MODIFIER  = SUBSTR(FEE_KEY,19,2) 
AND PRIOR MODIFIER2  = SUBSTR(FEE_KEY,23,2) 
AND PRIOR PROVIDER  = SUBSTR(FEE_KEY,29,12) 
AND LEVEL     = 2 
ORDER BY PROC, YMDEFF, LEVEL 
) B 
WHERE 1 = 1 

AND RECURSION_LEVEL = 2 
OR (RECURSION_LEVEL = 1 AND CASE WHEN RECURSION_LEVEL = 1 THEN NULL ELSE TO_DATE(B.T3,'YYYYMMDD')END IS NOT NULL ) 
OR B.YMDEND = '99991231' 
OR B.RANK2 = 1 
) C 

INNER JOIN 
(
SELECT 
    SUBSTR(FEE_KEY,3,4) AS FEE_SCHEDULE 
, MAX(YMDTRANS) AS YMDTRANS 
FROM AMIOWN.FEE_SCHEDULE 
WHERE SUBSTR(FEE_KEY,3,4) = 'MD01' 
GROUP BY SUBSTR(FEE_KEY,3,4) 
) D ON C.FEE_SCHEDULE = D.FEE_SCHEDULE 

WHERE 1 = 1 
); 

i NUMBER:= 0; 
BEGIN 
    FOR each_rec IN c1 LOOP 
INSERT INTO SCHEMA.FEE_SCHEDULE_GAPS_DETAIL 
(
    FEE_SCHEDULE 
, PROC 
, MODIFIER 
, MODIFIER2 
, PROVIDER 
, YMDEFF 
, YMDEND 
, NEXT_SPAN_DATE 
, SPAN 
, SPAN_FLAG 
, RATE 
, YMDTRANS 
) 
VALUES 
( each_rec.FEE_SCHEDULE 
, each_rec.PROC 
, each_rec.MODIFIER 
, each_rec.MODIFIER2 
, each_rec.PROVIDER 
, each_rec.YMDEFF 
, each_rec.YMDEND 
, each_rec.NEXT_SPAN_DATE 
, each_rec.SPAN 
, each_rec.SPAN_FLAG 
, each_rec.RATE 
, each_rec.YMDTRANS 
); 
i:= i+1; 

    END LOOP; 
END; 
/
+0

這不是一個CREATE OR REPLACE語句,它是引發錯誤的實際代碼嗎? – APC

+2

您的代碼區分源表模式('「AMIOWN」')與目標表模式(um這是否意味着存儲過程的所有者不同於這兩個模式中的任何一個或兩個?如果是這樣,那麼過程本身如何擁有這些表的特權?它們是如何被授予SELECT和/或INSERT?這很重要,因爲ORA-00942可以指示權限問題。 – APC

+0

爲什麼你要在這裏逐行(又名慢慢)的方法,當你可以通過簡單的「插入到(<你的表的列>)<您的選擇查詢>;'?然後它只是一個插入到你的程序體內的問題,並確保你有正確的權限(正如APC指出的!) – Boneist

回答

0

匿名塊:

DECLARE 
    <declarations> 
BEGIN 
    <actions> 
END; 

可以被轉換爲一個存儲過程是這樣的:

CREATE OR REPLACE PROCEDURE test IS 
    <declarations> 
BEGIN 
    <actions> 
END; 
+0

當我更改代碼,用CREATE OR REPLACE PROCEDURE測試替換我的DECLARE匿名塊時,得到「ORA-00942:表或視圖不存在錯誤」。除了「循環索引變量'EACH_REC'使用無效」錯誤。 – user41183

1

骨科醫生是正確的: 「作爲authid定義者(默認)的程序將不會查看角色以確定是否有必要的權限 - 相反,該權限需要是直接的 - 即。而不是將schema1.table1上的grant選擇爲some_role;授予some_role到schema2,它必須在schema1.table1上授予選擇到schema2「

我聯繫了我們的Oracle DBA,他們很快地授予我直接訪問權限,並且存儲過程完全正確地編譯。非常感謝您,很高興我不是瘋子