【问题标题】:Updating column is not working in Oracle PLSQL更新列在 Oracle PLSQL 中不起作用
【发布时间】:2017-07-11 08:44:58
【问题描述】:

我在PLSQL 中有一个Stored procedure,它根据某些条件插入和更新记录。

现在问题来了。第一次插入记录时,它会根据需要正确插入记录,但是

更新时不会更新表的记录。

下面是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

【问题讨论】:

  • tbl_insert 似乎没有被定义,并且您在第 54 行之前缺少一个右括号,但这将是编译错误。你能确认vsat_detail_id 是通过触发器设置的吗?您可能遇到了异常,但由于您的 when others 捕获,您正在压制/隐藏它。无论如何,在过程中提交/回滚通常不是一个好主意,但如果你必须捕获异常,你应该重新引发它。 (在rollback 之后添加raise;)。还要查看保存点....
  • @AlexPoole:非常感谢您的评论,是的,vsat_detail_id 是通过触发器设置的。还有我怎么知道它给了我一个exception,因为我找不到它。如果你让我知道来处理这个,那就太好了。!
  • 我已经说过,使用when others 缓存异常后重新引发异常。但正如 user7294900 指出的那样,您用于更新的值设置为零,而不是您期望的值 - 来自前面的 select.... 但您仍然可能遇到异常,例如如果 v_count 大于 1,而不是正好 1。
  • @AlexPoole: 哦,我真正想要的是我想在vsat_detail_id 的基础上更新表记录,但是当我去更新它时,我的v_count 总是会出现0 和它不会更新记录。另一方面,从服务器代码我的TBL_INSERT 在更新时总是以NULL 出现。目前我正在尝试按照您所说的提出异常。请让我知道,以便我可以逐步解决此问题
  • 如果你对代码应用了一些基本的格式,我保证你会感觉对程序结构有更多的控制。养成这个习惯真的很值得。

标签: oracle stored-procedures plsql insert-update


【解决方案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 将得到一个 too-many-rows 异常。您不会看到这一点,因为您正在默默地消除运行时遇到的任何错误。

无论如何,在过程中提交或回滚通常不是一个好主意;应该由调用者决定做什么,因为这可能是您真正希望将其视为原子事务的一系列语句和调用之一。 (您可能对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 - 没有为此有两个变量似乎是一个明显的理由。传入一个逗号分隔的字符串,然后你必须对其进行标记,这也有点痛苦——你应该考虑传入一个值的集合,如果任何调用 this 都可以做到的话。

正如还指出的那样,您可以使用 merge 而不是单独的插入/更新逻辑。

【讨论】:

  • 我的select 声明很好,我猜。我有兴趣让returning into 更合乎逻辑,因为我的场景完全取决于它。在引发异常部分,我将尝试按照标准异常重新引发它
  • 感谢您的更新回答。这里还有一件事。引发异常可以吗? EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; ROLLBACK; 或者我需要修改什么?
  • 你永远不会到达第二个rollback,raise 退出块(在这种情况下是过程)。
  • 哦,所以我不必过多考虑提出异常部分。但如果我有时间,我仍然会研究merge 部分
【解决方案2】:

您没有为 V_VSAT_DETAIL_ID 分配值,它在您的更新中用作键。

您应该使用merge 进行此类操作

【讨论】:

  • vsat_detail_id 正在初始化为零,但看起来您打算在更新中使用 tbl_insert,或者您打算在行中选择 v_vsat_detail_id 而不是 tbl_insert更新前。
  • 这种操作应该使用合并
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 2015-03-15
  • 2016-08-04
  • 1970-01-01
  • 2019-11-07
相关资源
最近更新 更多