2017-07-11 59 views
0

我有一個Stored procedurePLSQL其中根據某些條件插入和更新記錄。更新列在Oracle PLSQL中不起作用

現在這裏的問題是。在第一次插入記錄時,它根據需要正確插入記錄,但是

在更新它時不更新表的記錄。

下面是SP

PROCEDURE INSERT_INTO_VSAT_MST_DATA 
    (
    P_SAPID IN NVARCHAR2, 
    P_CIRCLE IN NVARCHAR2, 
    P_CANDIDATEID IN NVARCHAR2, 
    P_SITEID IN NVARCHAR2, 
    P_PRIORITYID IN NVARCHAR2, 
    P_SITENAME IN NVARCHAR2, 
    P_LATITUDE IN NVARCHAR2, 
    P_LONGITUDE IN NVARCHAR2, 
    P_CONTACT_DETAILS IN CLOB, 
    P_SITETYPE IN NVARCHAR2, 
    P_SITE_PLOT_DIMENSION IN NUMBER, 
    P_TECHNOLOGY IN NVARCHAR2 
) 
    AS 

    V_COUNT NUMBER:=0; 
    V_PANAROMICIMG_COUNT NUMBER:=0; 
    V_SATELLITEIMG_COUNT NUMBER:=0; 
    V_SITEPLOTIMG_COUNT NUMBER:=0; 
    V_VSAT_DETAIL_ID NUMBER:=0; 

    BEGIN 

SELECT COUNT(VSAT_DETAIL_ID) INTO V_COUNT FROM TBL_VSAT_MST_DETAIL WHERE SAP_ID = P_SAPID AND CANDIDATE_ID = P_CANDIDATEID; 

IF V_COUNT > 0 THEN 

SELECT VSAT_DETAIL_ID INTO TBL_INSERT FROM TBL_VSAT_MST_DETAIL WHERE SAP_ID = P_SAPID AND CANDIDATE_ID = P_CANDIDATEID; 
UPDATE TBL_VSAT_MST_DETAIL SET 
          CIRCLE = P_CIRCLE, 
          CONTACT_DETAILS = P_CONTACT_DETAILS, 
          SITE_TYPE = P_SITETYPE, 
          SITE_DETAILS_DIMENSION = P_SITE_PLOT_DIMENSION, 
          SITE_DETAILS_TECHNOLOGY = P_TECHNOLOGY 
          WHERE VSAT_DETAIL_ID = V_VSAT_DETAIL_ID 
       RETURNING VSAT_DETAIL_ID INTO TBL_INSERT;   
ELSE  
INSERT INTO TBL_VSAT_MST_DETAIL 
           (
            SAP_ID, 
            CIRCLE, 
            CANDIDATE_ID, 
            SITE_ID, 
            PRIORITY, 
            SITE_NAME, 
            LATITUDE, 
            LONGITUDE, 
            CONTACT_DETAILS, 
            SITE_TYPE, 
            SITE_DETAILS_DIMENSION, 
            SITE_DETAILS_TECHNOLOGY          
VALUES 
           (
            P_SAPID, 
            P_CIRCLE, 
            P_CANDIDATEID, 
            P_SITEID, 
            P_PRIORITYID, 
            P_SITENAME, 
            P_LATITUDE, 
            P_LONGITUDE, 
            P_CONTACT_DETAILS, 
            P_SITETYPE, 
            P_SITE_PLOT_DIMENSION, 
            P_TECHNOLOGY 
            ) RETURNING VSAT_DETAIL_ID INTO TBL_INSERT; 
END IF;  
IF TBL_INSERT > 0 THEN 
BEGIN     
    SELECT COUNT(*) INTO V_PANAROMICIMG_COUNT FROM TBL_VSAT_IMAGE_DETAIL WHERE IMG_TYPE = 'Panaromic' AND IMG_ID = TBL_INSERT;   
    SELECT COUNT(*) INTO V_SATELLITEIMG_COUNT FROM TBL_VSAT_IMAGE_DETAIL WHERE IMG_TYPE = 'Satellite' AND IMG_ID = TBL_INSERT;   
    SELECT COUNT(*) INTO V_SITEPLOTIMG_COUNT FROM TBL_VSAT_IMAGE_DETAIL WHERE IMG_TYPE = 'SitePlot' AND IMG_ID = TBL_INSERT;   
    IF V_PANAROMICIMG_COUNT > 0 THEN 
    BEGIN   
     DELETE FROM TBL_VSAT_IMAGE_DETAIL WHERE IMG_TYPE = 'Panaromic' AND IMG_ID = TBL_INSERT; 
    END;   
    END IF;   
    IF V_SATELLITEIMG_COUNT > 0 THEN 
    BEGIN   
     DELETE FROM TBL_VSAT_IMAGE_DETAIL WHERE IMG_TYPE = 'Satellite' AND IMG_ID = TBL_INSERT; 
    END; 
    END IF;   
    IF V_SITEPLOTIMG_COUNT > 0 THEN 
    BEGIN   
     DELETE FROM TBL_VSAT_IMAGE_DETAIL WHERE IMG_TYPE = 'SitePlot' AND IMG_ID = TBL_INSERT; 
    END; 
    END IF; 
    FOR PMULTIFIELDS IN (SELECT REGEXP_SUBSTR(P_PANORAMIC_IMAGES,'[^,]+', 1, LEVEL) AS IMAGES FROM DUAL 
           CONNECT BY REGEXP_SUBSTR(P_PANORAMIC_IMAGES, '[^,]+', 1, LEVEL) IS NOT NULL 
          ) 
    LOOP 
       INSERT INTO TBL_VSAT_IMAGE_DETAIL 
          (
           IMG_ID, 
           IMG_NAME, 
           IMG_TYPE, 
           IMG_UPLOADED_DATE, 
           UPLOADED_BY 
          ) 
          VALUES 
          (
           TBL_INSERT, 
           PMULTIFIELDS.IMAGES, 
           'Panaromic', 
           SYSDATE, 
           P_CREATEDBY 
          ); 
    END LOOP; 
    FOR PSATELLITEIMG IN (SELECT REGEXP_SUBSTR(P_SATELLITE_IMAGES,'[^,]+', 1, LEVEL) AS IMAGES FROM DUAL 
            CONNECT BY REGEXP_SUBSTR(P_SATELLITE_IMAGES, '[^,]+', 1, LEVEL) IS NOT NULL 
           ) 
    LOOP 
       INSERT INTO TBL_VSAT_IMAGE_DETAIL 
          (
           IMG_ID, 
           IMG_NAME, 
           IMG_TYPE, 
           IMG_UPLOADED_DATE, 
           UPLOADED_BY 
          ) 
          VALUES 
          (
           TBL_INSERT, 
           PSATELLITEIMG.IMAGES, 
           'Satellite', 
           SYSDATE, 
           P_CREATEDBY 
          ); 
    END LOOP; 

    IF P_SITEPLOT_IMAGES IS NOT NULL THEN 
    BEGIN  
    INSERT INTO TBL_VSAT_IMAGE_DETAIL 
           (
           IMG_ID, 
           IMG_NAME, 
           IMG_TYPE, 
           IMG_UPLOADED_DATE, 
           UPLOADED_BY 
          ) 
           VALUES 
           (
           TBL_INSERT, 
           P_SITEPLOT_IMAGES, 
           'SitePlot', 
           SYSDATE, 
           P_CREATEDBY 
          ); 
     END; 
     END IF;  
     END; 
     END IF;  
    COMMIT;  
    EXCEPTION WHEN OTHERS THEN  
    ROLLBACK; 

注意

雖然更新記錄我的TBL_INSERT收益爲NULL

+0

'tbl_insert'似乎沒有被定義,並且在第54行之前缺少右括號,但那些將是編譯錯誤。你能否確認'vsat_detail_id'是通過觸發器設置的?你可能會得到一個例外,但是因爲你在別人的時候被你壓制/隱藏它。通常在程序中提交/回滾通常不是一個好主意,但是如果你必須捕捉異常,你應該重新提高它。 (在'rollback'之後加'raise;')。也看看保存點.... –

+0

@AlexPoole:真的非常感謝您的評論,是'vsat_detail_id'通過觸發器設置。另外我怎麼能知道它給我一個'例外',因爲我無法找到它。如果你讓我知道處理這件事,IT會很棒。 – BNN

+0

我已經說過了,在用'when others'緩存後重新拋出異常。但是,正如user7294900指出的那樣,您用於更新的值設置爲零,而不是您期望的值 - 來自之前的「select」....但您仍然可能會遇到異常,例如如果'v_count'大於1,而不是完全爲1. –

回答

1

擴大對什麼@ user7294900指出你對...的聲明部分的你:

V_VSAT_DETAIL_ID NUMBER:=0; 

然後如果v_count > 0你這樣做:

SELECT VSAT_DETAIL_ID INTO TBL_INSERT FROM TBL_VSAT_MST_DETAIL WHERE SAP_ID = P_SAPID AND CANDIDATE_ID = P_CANDIDATEID; 
UPDATE TBL_VSAT_MST_DETAIL SET 
          CIRCLE = P_CIRCLE, 
          CONTACT_DETAILS = P_CONTACT_DETAILS, 
          SITE_TYPE = P_SITETYPE, 
          SITE_DETAILS_DIMENSION = P_SITE_PLOT_DIMENSION, 
          SITE_DETAILS_TECHNOLOGY = P_TECHNOLOGY 
          WHERE VSAT_DETAIL_ID = V_VSAT_DETAIL_ID 
       RETURNING VSAT_DETAIL_ID INTO TBL_INSERT;   

selectTBL_INSERT設置爲表中的ID值。但是當你做update你的過濾器使用V_VSAT_DETAIL_ID,它仍然被設置爲其初始值爲零。

你大概的意思做。

SELECT VSAT_DETAIL_ID INTO V_VSAT_DETAIL_ID FROM TBL_VSAT_MST_DETAIL WHERE SAP_ID = P_SAPID AND CANDIDATE_ID = P_CANDIDATEID; 

雖然你當前的選擇仍然可以和使用,在update太(使returning into有點多餘

注意的是,如果v_count不完全是1,即您有多個行匹配P_SAPIDP_CANDIDATEID的值,select將得到太多的行異常。您不會看到這一點,因爲您正在默默壓縮在運行時得到的任何錯誤

無論如何,在程序中提交或回滾通常不是一個好主意;應該由調用者決定要做什麼,因爲這可能是您真正想要視爲原子事務的一系列聲明和調用之一。 (您可能感興趣的savepoints

如果你真的想在過程中的異常回滾,所以調用者知道有一個問題,你至少應該重新拋出異常:

EXCEPTION WHEN OTHERS THEN  
    ROLLBACK; 
    RAISE; 
END INSERT_INTO_VSAT_MST_DATA; 

但我會avoid when others if you can


您也可以通過獲取ID在啓動(再次一種假設最多有一個匹配行),並丟棄單獨計數和v_count可變結合幾個步驟:

SELECT MAX(VSAT_DETAIL_ID) INTO V_VSAT_DETAIL_ID 
FROM TBL_VSAT_MST_DETAIL 
WHERE SAP_ID = P_SAPID AND CANDIDATE_ID = P_CANDIDATEID; 

IF V_VSAT_DETAIL_ID IS NOT NULL THEN 

    UPDATE TBL_VSAT_MST_DETAIL SET 
          CIRCLE = P_CIRCLE, 
          CONTACT_DETAILS = P_CONTACT_DETAILS, 
          SITE_TYPE = P_SITETYPE, 
          SITE_DETAILS_DIMENSION = P_SITE_PLOT_DIMENSION, 
          SITE_DETAILS_TECHNOLOGY = P_TECHNOLOGY 
          WHERE VSAT_DETAIL_ID = V_VSAT_DETAIL_ID 
       RETURNING VSAT_DETAIL_ID INTO TBL_INSERT;   
    ELSE  
... 

而且我不確定爲什麼你要做的事情在你之後刪除之前計算,而且看起來像就像你所有的tbl_insert引用應該是/應該是v_vast_detail_id-似乎沒有明顯的理由有兩個變量。傳遞逗號分隔的字符串,然後必須標記化也有點痛苦 - 您應該考慮傳入值的集合,而不管它是否可以管理該值。

同樣指出,您可以使用merge而不是單獨的插入/更新邏輯。

+0

我的'select'語句是我猜的好。我會有興趣讓「迴歸」更加合乎邏輯,因爲我的方案完全依賴於它。在引發異常部分,我會嘗試根據標準例外 – BNN

+0

對其進行重新評估,謝謝您的回答。還有一件事在這裏。提出異常可以嗎? '例外,當其他人 ROLLBACK; RAISE; ROLLBACK;'或者我需要修改一些東西? – BNN

+0

你永遠不會到達第二個'rollback',raise會退出塊(在這個例子中是程序)。 –

0

你不分配值V_VSAT_DETAIL_ID這是在你更新使用作爲一個關鍵。

你應該使用merge對於這種操作

+0

那麼如何分配,它會正常工作? – BNN

+0

'vsat_detail_id'被初始化爲零,但看起來您打算在更新中使用'tbl_insert',或者您想在更新之前在行中選擇'v_vsat_detail_id'而不是'tbl_insert'。 –

+1

你應該使用合併這種操作 – user7294900