【问题标题】:Oracle update columns with Max value from same table and partial update on columnOracle 更新具有来自同一表的最大值的列和列的部分更新
【发布时间】:2016-12-13 17:28:17
【问题描述】:

我必须在同一张表上更新多个具有最大值的列。一个伪查询就像 -

UPDATE PERMIT 
SET P_ID = 'FIRST FIVE CHARACTERS WILL REMAIN SAME AND LAST few WILL BE REPLACED BY SELECT Max(prmt_appl_sq) FROM PERMIT SOME CONDITION',
prmt_appl_sq = 'AND NOW UPDATE WITH SAME MAX VALUE USED ABOVE'
WHERE 
CONDITION

表格数据就像 P_ID P_APPL_SQ C代码 2016-H-193-5 10 193 列 P_ID 有一个唯一约束,最后一部分 ***-5 实际上是 P_APPL_SQ 中的值,每次使用相同的其他三个值创建记录时都会递增。 例如,当创建具有 2016 年的新记录并键入 -H 和 Center 193 时,P_ID 将变为 ********-6。我必须将 CCode = 193 的所有记录更新为 195,并将 p_ID 更新为 2016-H-195-“前三个组合的最大值 +1”,然后还更新 P_APPL_SQ 具有相同的值。

我提出了查询,但它尝试在每一行上添加相同的值,从而引发唯一约束违规
更新 OSPDBA.OSPT001_PRMT_APPL
SET rted_to_org_cd = '55014040191', PRMT_ID = SUBSTR(PRMT_ID, 0, 11) || (选择最大值(prmt_appl_sq)+ 1 FROM OSPDBA.OSPT001_PRMT_APPL 其中 rted_to_org_cd = '55014040191' 和 prmt_sbmt_yr = 2016 和 prmt_typ_cd = 'H'), prmt_appl_sq = ((SELECT Max(prmt_appl_sq) + 1 FROM OSPDBA.OSPT001_PRMT_APPL 其中 rted_to_org_cd = '55014040191' 和 prmt_sbmt_yr = 2016 和 prmt_typ_cd = 'H')) 在哪里 rted_to_org_cd IN ('55014040193','55014040195') 和 prmt_sbmt_yr = 2016;

我们如何才能为每条记录设置唯一的最大值?

【问题讨论】:

  • 大多数此类问题都可以通过一条 SQL 语句解决。主要要求是问题陈述在逻辑上是一致的。 (否则问题无法通过任何方式解决。)但是,为了获得更多帮助,您需要提供表结构(列名和数据类型,仅针对问题所需的列),一些示例数据说明所有可能的并发症和特殊情况,以及期望的输出。
  • 这是definitely possible;你试过谷歌搜索吗?此外,当有句法疑问时,reading Oracle's SQL reference 通常是个好主意。

标签: sql oracle


【解决方案1】:

试试这个查询:

UPDATE P1
SET P1.P_ID = SUBSTRING(P2.P_ID,1,5) ||''|| P2.MaxValue, 
P1.prmt_appl_sq = P2.MaxValue
FROM PERMIT P1 INNER JOIN 
( select P_ID, MAX(prmt_appl_sq) OVER() AS MaxValue from  PERMIT where some condition) As P2
where P1.P_ID = P2.P_ID and some condition

【讨论】:

  • 出现语法错误更新 P1 SET P1.rted_to_org_cd = '55014040191', P1.PRMT_ID = SUBSTRING(P2.PRMT_ID,0,11) || p2.maxvalue,p1.prmt_appl_sq = p2.maxvalue从ospdba.oSpt001_prmt_appl p1内连接(选择prmt_sq,max(prmt_appl_sq)作为maxvalue从ospdba.ospt001_prmt_appl,其中rted_to_org_cd ='55014040191'和prmt_sbmt_yr = 2016和prmt_typ_cd ='h ') 作为 P2,其中 P1.prmt_sq = P2.prmt_sq 和 rted_to_org_cd IN ('55014040193','55014040195') 和 prmt_sbmt_yr = 2016;
【解决方案2】:

可以在单个查询中完成,没问题。更接近实际查询的伪查询将是

UPDATE PERMIT 
SET P_ID = substr(p_id, 0, 5) || (SELECT Max(prmt_appl_sq) FROM PERMIT SOME CONDITION),
prmt_appl_sq = (SELECT Max(prmt_appl_sq) FROM PERMIT SOME CONDITION)
WHERE 
CONDITION

但条件必须设计得很好,如果 PERMIT 足够大,您可能会遇到性能问题。

================================================ ========

更新查询

UPDATE OSPDBA.OSPT001_PRMT_APPL a 

SET rted_to_org_cd = '55014040191', 

PRMT_ID = SUBSTR(PRMT_ID, 0, 11) || (SELECT Max(prmt_appl_sq) + 1 FROM OSPDBA.OSPT001_PRMT_APPL b where a.rted_to_org_cd = b.rted_to_org_cd and prmt_sbmt_yr = 2016 and prmt_typ_cd = 'H'), 

prmt_appl_sq = (SELECT Max(prmt_appl_sq) + 1 FROM OSPDBA.OSPT001_PRMT_APPL c where a.rted_to_org_cd = c.rted_to_org_cd and prmt_sbmt_yr = 2016 and prmt_typ_cd = 'H') 

WHERE rted_to_org_cd IN ('55014040193','55014040195') and prmt_sbmt_yr = 2016;

【讨论】:

  • 我尝试了这个查询,但遇到了唯一约束冲突,因为它尝试为每条记录更新 prmt_appl_sq 相同的值。
  • 你不是说“P_ID 列的唯一约束”吗?如果 prmt_appl_sq 是唯一约束,那么您需要使其唯一,例如 max(prmt_appl_sq) + 1 ...
  • 是的,它在 P_ID 上。但它试图在每条记录上附加相同的最大值,这使得值重复。如果您只为一条记录运行查询,则该查询有效。
  • 更新 OSPDBA.OSPT001_PRMT_APPL SET rted_to_org_cd = '55014040191', PRMT_ID = SUBSTR(PRMT_ID, 0, 11) || (从OSPDBA.OSPT001_PRMT_APPL中选择MAX(PRMT_APPL_SQ)+ 1,其中RTED_TO_ORG_CD ='55014040191'和PRMT_SBMT_YR = 2016和PRMT_TYP_CD ='H'),PRMT_APPL_SQ =((从OSPDBA.OSPT001_PRMT_APPL中选择MAX(PRMT_APPL_SQ)+ 1,其中RTED_TO_ORG_CD ='55014040191 ' 和 prmt_sbmt_yr = 2016 和 prmt_typ_cd = 'H')) 其中 prmt_sq in (19246); -- 如果你在以下条件下运行它,它可以工作,但会出错 --rted_to_org_cd IN ('55014040193','55014040195') 和 prmt_sbmt_yr = 2016;
  • 好的,我把格式化的查询放在我的答案中,因为这里所有的格式都被剥离了。我想您需要将 SET rted_to_org_cd = '55014040191' 修改为动态的。
【解决方案3】:

我必须写一个游标来进行批量更新。

    DECLARE
    C_PRMT_SQ                   PRMT_APPL.PRMT_SQ%TYPE; 
    C_PRMT_SBMT_YR              PRMT_APPL.PRMT_SBMT_YR%TYPE;    
    MAX_APPL_SEQ                PRMT_APPL.PRMT_APPL_SQ%TYPE;    

    L_ERR_LEVEL                 NUMBER := 0;
    MAX_SEQ_VAL                 VARCHAR2(220);


    -- SELECT ALL PERMITS OF PURGED CC FROM THE DATABASE
    CURSOR CSEQUENCE IS
        SELECT PRMT_SQ,PRMT_SBMT_YR FROM PRMT_APPL 
        WHERE RTED_TO_ORG_CD IN ('55014040193','55014040195') ORDER BY PRMT_SBMT_YR DESC;
-- MAIN 
BEGIN
    OPEN CSEQUENCE; 
    L_ERR_LEVEL := 1;

    LOOP

    FETCH CSEQUENCE INTO C_PRMT_SQ,C_PRMT_SBMT_YR;

    DBMS_OUTPUT.PUT_LINE ('C_PRMT_SQ ' || TO_CHAR(C_PRMT_SQ) || '  '  || TO_CHAR(C_PRMT_SBMT_YR));

    EXIT WHEN CSEQUENCE%NOTFOUND;

    SELECT (MAX(PRMT_APPL_SQ) + 1) INTO MAX_APPL_SEQ FROM PRMT_APPL WHERE  RTED_TO_ORG_CD = '55014040191' AND PRMT_SBMT_YR = C_PRMT_SBMT_YR AND PRMT_TYP_CD = 'H'; 

    MAX_SEQ_VAL := 'MAX_APPL_SEQ ' || TO_CHAR(MAX_APPL_SEQ); 

    DBMS_OUTPUT.PUT_LINE (MAX_SEQ_VAL);

    UPDATE PRMT_APPL  
        SET   
            RTED_TO_ORG_CD = '55014040191',
            PRMT_ID = SUBSTR(PRMT_ID, 0, 7) || 191 || '-' || MAX_APPL_SEQ,
            PRMT_APPL_SQ = MAX_APPL_SEQ,
            UPDT_TMS = SYSTIMESTAMP
        WHERE   PRMT_SQ = C_PRMT_SQ;

    COMMIT;

    END LOOP;
    CLOSE CSEQUENCE;    
    L_ERR_LEVEL := 3;
END;

【讨论】:

    猜你喜欢
    • 2021-10-14
    • 1970-01-01
    • 2012-11-10
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多