【问题标题】:Merge with select with multiple rows与多行选择合并
【发布时间】:2021-04-20 13:04:18
【问题描述】:

我有一个每次运行的查询,选择与表相关的 user_triggers 行(p_table_name_in)。我想每天运行这个过程,我只想插入新行,而不是再次插入所有行。但是当我安装这个 oackage 时,我得到了这个错误:

ORA-00932 (130: 21):PL / SQL:ORA-00932:不一致的数据类型: 预期 CLOB,收到 LONG(第 31 行)

当我尝试将 TRIGGER_BODY AS BODY_TRIGGER 更改为 TO_LOB(TRIGGER_BODY) AS BODY_TRIGGER 时,我收到此错误:

ORA-00932 (111: 29):PL / SQL:ORA-00932:不一致的数据类型:- 预期,收到 LONG(第 12 行)

程序:

PROCEDURE save_trigger_definitions ( p_table_name_in in VARCHAR2 ) IS        
BEGIN                  
        MERGE INTO hot_utils_reload_triggers t1
        USING
        (
        SELECT TRIGGER_NAME ,
                            TABLE_NAME , 
                            STATUS , 
                            DESCRIPTION,
                            TRIGGER_BODY AS BODY_TRIGGER,
                            WHEN_CLAUSE 
                FROM user_triggers
        )t2
        ON(t2.TABLE_NAME like upper(p_table_name_in))
        WHEN MATCHED THEN UPDATE SET
            t1.DESCRIPTION = t2.DESCRIPTION,
            t1.WHEN_CLAUSE = t2.WHEN_CLAUSE
        WHEN NOT MATCHED THEN 
            INSERT (TRIGGER_NAME,
                    TABLE_NAME, 
                    STATUS, 
                    DESCRIPTION,
                    BODY_TRIGGER,
                    WHEN_CLAUSE)
            VALUES (t2.TRIGGER_NAME,
                    t2.TABLE_NAME, 
                    t2.STATUS, 
                    t2.DESCRIPTION, 
                    t2.BODY_TRIGGER, 
                    t2.WHEN_CLAUSE); 
            commit;
END save_trigger_definitions;

【问题讨论】:

    标签: oracle sql-insert clob sql-merge lob


    【解决方案1】:

    Oracle 不允许在SELECTMERGE 语句中使用TO_LOB,而INSERT 则允许使用。因此,您可以单独使用INSERTMERGE,只使用包含MATCHED 部分的部分,例如

    CREATE OR REPLACE PROCEDURE save_trigger_definitions ( p_table_name_in in VARCHAR2 ) IS    
    BEGIN  
        INSERT INTO hot_utils_reload_triggers
            (trigger_name,
             table_name,
             status,
             description,
             body_trigger,
             when_clause)
        SELECT trigger_name,
               table_name,
               status,
               description,
               TO_LOB(trigger_body),
               when_clause
          FROM user_triggers
         WHERE table_name LIKE UPPER(p_table_name_in)
           AND NOT EXISTS ( SELECT 1 
                              FROM hot_utils_reload_triggers 
                             WHERE trigger_name = u.trigger_name
                               AND table_name = u.table_name
                               AND status = u.status );
    
        UPDATE hot_utils_reload_triggers h
           SET h.description = description, h.when_clause = when_clause
         WHERE table_name LIKE UPPER(p_table_name_in);
    
        COMMIT;
    END;
    /
    

    假设您不希望某些列(例如 trigger_nametable_namestatus)出现重复行,我在 NOT EXISTS 子句之后为它们添加了一个子查询。

    Ref1

    Ref2

    使用DBMS_REDEFINITION.START_REDEF_TABLE() 可能是LONGLOB 转换情况的另一种选择。

    【讨论】:

    • 感谢您的回答。但是您的代码的问题是当重复行进入表时,程序将引发错误并且不会继续。
    • 嗨@monashiri,我在reproduced 时没有发现任何问题,除了我刚刚添加的一些我错过的小部分。
    • @BarbarosÖzhan 您正在考虑没有主键的表,如果您向表中添加键,您的代码将返回异常dbfiddle.uk/…
    • 好吧,刚刚注意到你又说不是所有的行,但是请告诉我你需要什么标准来复制? @monashiri。它们对于六列应该是唯一的吗?我根据三列编辑了答案。
    • @BarbarosÖzhan 谢谢,我认为现在可以了。
    猜你喜欢
    • 1970-01-01
    • 2013-11-23
    • 2011-09-18
    • 1970-01-01
    • 2014-08-19
    • 1970-01-01
    • 2013-01-16
    • 2016-03-25
    • 2020-08-06
    相关资源
    最近更新 更多