【问题标题】:2 Merge Statements inside a Procedure PLSQL2 PLSQL 过程中的合并语句
【发布时间】:2020-09-23 13:38:19
【问题描述】:

我正在尝试在过程中使用 2 个合并语句。 一个应该删除不在另一个表中的行。

另一个应该插入不在表格中的那些。

在这种情况下,我收到了缺少关键字的错误。

create or replace noneditionable procedure merge_test
as
BEGIN

Execute immediate 'alter table
   table person
DISABLE constraint
FK_FGH_ID ';


Merge into (select distinct * from 
person_test) t1
Using (select * from person) p1
On (p1.person_id = t1.person_id)
When not matched then
DELETE
FROM
    person
WHERE
    Person_id = p1.person_id;
COMMIT;

Merge into person p
USING (select distinct * from 
person_test) t
On (t.person_id = p.person_id)
When not matched then
Insert(person_id,vorname, nachname, mobil, telefon, fax, e_mail, fgh_id)
values(t.person_id, t.vorname, t.nachname, t.mobil, t.telefon, t.fax, t.e_mail, t.fgh_id);
COMMIT;

Execute immediate 'alter table
   person
ENABLE constraint
   FK_FGH_ID ';


End merge_test;

在第一次合并中,关键字丢失错误出现在“WHEN NOT MATCHED”处。 另一个问题是是否有可能在一个过程中包含 2 个合并语句。

【问题讨论】:

  • 你绝对应该避免这种可怕的“select *”事情。用明确的列名替换它。
  • MERGE 语句中的 DELETE 仅适用于 merged 表,即我们只能从 WHEN MATCHED 分支调用它。整个第一个 MERGE 语句是完全错误的。

标签: sql oracle plsql keyword


【解决方案1】:

是的,在一个过程中包含两个MERGE 语句绝对是可能的,但是为什么在这种情况下使用它们呢?只需使用简单的DELETE 然后INSERT 语句,类似于下面的语句。

CREATE OR REPLACE NONEDITIONABLE PROCEDURE merge_test
AS
BEGIN
    EXECUTE IMMEDIATE 'alter table person DISABLE constraint FK_FGH_ID';

    DELETE FROM person
          WHERE person_id NOT IN (SELECT person_id FROM person_test);

    INSERT INTO person (person_id,
                        vorname,
                        nachname,
                        mobil,
                        telefon,
                        fax,
                        e_mail,
                        fgh_id)
        SELECT person_id,
               vorname,
               nachname,
               mobil,
               telefon,
               fax,
               e_mail,
               fgh_id
          FROM person_test
         WHERE person_id NOT IN (SELECT person_id FROM person);

    EXECUTE IMMEDIATE 'alter table person ENABLE constraint FK_FGH_ID';
END merge_test;

【讨论】:

  • 搜索者在从 person_test 查询时使用 DISTINCT。假设他们有这样做的正当理由,您应该将其包含在您的 INSERT ... SELECT 语句中。
【解决方案2】:

在存储过程中使用多个MERGE 语句没有问题。

你仍然可以通过转换相关部分来使用第一个MERGE语句

WHEN NOT MATCHED THEN
DELETE FROM person
WHERE Person_id = p1.person_id

到:

 WHEN MATCHED THEN UPDATE SET t1.person_id = p1.person_id 
                   DELETE WHERE person_id = p1.person_id

但是DELETE 语句不能在WHEN NOT MATCHED THEN 之后发生

顺便说一句,两个在单个事务中拥有多个 COMMIT 并不是一个好习惯,而是只保留最后一个。

【讨论】:

    【解决方案3】:

    类似这样的:

    create or replace noneditionable procedure merge_test
    IS
    
    BEGIN
    
        Execute immediate 'alter table person DISABLE constraint FK_FGH_ID ';
    
        Merge into person_test t1
        Using (select * from person) p1
        On (t1.person_id = p1.person_id)
        when matched then 
             update set t1.Person_id = t1.Person_id
                 where t1.Person_id = p1.person_id
             delete 
                 where t1.Person_id = p1.person_id;
    
        COMMIT;
        
        Merge into person p
        USING (select * from person_test) t
        On (t.person_id = p.person_id)
        When not matched then
            Insert(person_id,vorname, nachname, mobil, telefon, fax, e_mail, fgh_id)
            values(t.person_id, t.vorname, t.nachname, t.mobil, t.telefon, t.fax, t.e_mail, t.fgh_id);
        
        COMMIT;
        
        Execute immediate 'alter table person ENABLE constraint FK_FGH_ID ';
    
    End merge_test;
    /
    

    请注意,您的第一个 Execute immediate 语句中有错误。应该是:

    Execute immediate 'alter table person DISABLE constraint FK_FGH_ID ';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      • 2019-09-02
      • 2021-12-03
      • 1970-01-01
      • 2012-02-10
      • 2021-11-03
      • 2020-07-21
      相关资源
      最近更新 更多