Plsql 基于条件的PL/SQL插入

Plsql 基于条件的PL/SQL插入,plsql,oracle11g,Plsql,Oracle11g,我将非常感激能得到的一切帮助。我正在学习PL/SQL,偶然发现了一个问题,因此请帮助我找到处理这种情况的适当方法:) 我在运行Oracle 11gR2 我的模式: CREATE TABLE "ENTRY" ( "TYPE" VARCHAR2(5 CHAR) , "TRANSACTION" VARCHAR2(5 CHAR), "OWNER" VARCHAR2(5 CHAR) ); CREATE TABLE "VIEW" ( "TYPE" VARCHAR2(5 CHAR) , "TR

我将非常感激能得到的一切帮助。我正在学习PL/SQL,偶然发现了一个问题,因此请帮助我找到处理这种情况的适当方法:) 我在运行Oracle 11gR2

我的模式:

CREATE TABLE "ENTRY" 
(
 "TYPE" VARCHAR2(5 CHAR) ,
 "TRANSACTION" VARCHAR2(5 CHAR),
 "OWNER" VARCHAR2(5 CHAR)
);

CREATE TABLE "VIEW" 
(
 "TYPE" VARCHAR2(5 CHAR) ,
 "TRANSACTION" VARCHAR2(5 CHAR),
 "OWNER" VARCHAR2(5 CHAR)
);

CREATE TABLE "REJECTED" 
(
 "TYPE" VARCHAR2(5 CHAR) ,
 "TRANSACTION" VARCHAR2(5 CHAR),
 "OWNER" VARCHAR2(5 CHAR)
);
我的样本数据:

insert into entry (type, transaction, owner) values (11111, 11111, 11111);
insert into entry (type, transaction, owner) values (22222, 22222, 22222);
现在,对于令人费解的部分,我编写了这个过程,如果不存在特定(事务和所有者)组合的记录,那么应该将条目表中的值复制到视图表中。如果视图表中存在这样的组合,则该记录应转到被拒绝的表。这个过程可以做到这一点,但在多次运行该过程时,我会在被拒绝的表中获得越来越多的条目,因此我的问题是如何限制被拒绝表中的插入-如果被拒绝的表中已经存在记录,则什么也不做

create or replace PROCEDURE COPY AS         

v_owner_entry ENTRY.owner%TYPE;
v_transaction_entry ENTRY.transaction%TYPE;

v_owner VIEW.owner%TYPE;
v_transaction VIEW.transaction%TYPE;

begin 

begin 

select e.owner, e.transaction, v.owner, v.transaction 
into v_owner_entry, v_transaction_entry, v_owner, v_transaction
from entry e, view v
where e.owner = v.owner
and e.transaction = v.transaction;

EXCEPTION
when too_many_rows
then
  insert into REJECTED
  (
    TYPE,
TRANSACTION,
OWNER
  )
  SELECT
    s1.TYPE,
    s1.TRANSACTION,
    s1.OWNER
    FROM ENTRY s1;


when no_data_found
THEN

insert into VIEW
    (
      TYPE,
  TRANSACTION,
  OWNER
    )
    SELECT
      s.TYPE,
  s.TRANSACTION,
  s.OWNER
      FROM ENTRY s;

 end;
 end;
有什么建议吗

干杯

更新 抱歉,如果原始帖子不够清晰- 该过程应该(每天)将数据从DB1复制到DB2,并根据条件插入视图或拒绝。这是一张照片,也许会更清楚: 使用声明:

merge into REJECTED r
using ENTRY e
   on (r.type = e.type and
       r.transaction = e.transaction and
       r.owner = e.owner)
 when not matched then insert (type, transaction, owner)
 values (e.type, e.transaction, e.owner)
此查询将只在表
条目中插入表
条目中尚未出现的(
类型
交易
所有者
)的组合。

使用语句:

merge into REJECTED r
using ENTRY e
   on (r.type = e.type and
       r.transaction = e.transaction and
       r.owner = e.owner)
 when not matched then insert (type, transaction, owner)
 values (e.type, e.transaction, e.owner)

此查询将只在表
条目中的(
类型
交易
所有者
)组合中插入被拒绝的
,这些组合尚未出现。

您正试图将自己编码出一个您已经建立自己模型的困境

表应该包含您的实体。不应该有一个一个状态中实体的表,另一个状态中实体的表,以及另一个状态中实体的表。你看到了这会导致什么样的问题


状态可以是一个表的属性(字段或列)。或者标准化为
状态
表,但仍然只有一个实体表。当一个实体改变状态时,这是通过更新来完成的,而不是从一个表移动到另一个表。

您正试图将自己从建模所陷入的困境中编码出来

表应该包含您的实体。不应该有一个一个状态中实体的表,另一个状态中实体的表,以及另一个状态中实体的表。你看到了这会导致什么样的问题


状态可以是一个表的属性(字段或列)。或者标准化为
状态
表,但仍然只有一个实体表。当实体更改状态时,这是通过更新完成的,而不是从一个表移动到另一个表。

我认为Dmitry试图建议在异常处理程序的过多行情况下使用MERGE。因此,您已经提前完成了选择,并确定条目行出现在视图表中,因此它引发异常的行太多

问题是您不知道哪些记录引发了异常(假设您的条目表在调用此过程时有多行)。因此,我认为您使用exception部分来确定行太多的想法很优雅,但不足以满足您的需要

作为一个熟练的程序员,我不会试图想出一些非常优雅的东西,我会使用更多的蛮力

更像是:

BEGIN
    FOR entry_cur IN
        (select e.owner, e.transaction, SUM(NVL2(v.owner, 1, 0)) rec_count
           from entry e, view v
          where e.owner = v.owner(+)
            and e.transaction = v.transaction(+)
         GROUP BY e.owner, e.transaction)
    LOOP
        CASE WHEN rec_count > 0
             THEN INSERT INTO view
             ELSE MERGE INTO rejected r
                     ON (r.transaction = entry_cur.transaction
                    AND r.owner = entry_cur.owner)
                   WHEN NOT MATCHED THEN INSERT blah blah blah
        ;
    END LOOP;
END;
如果计数(*)大于1,则 没有抛出异常。循环为您提供了不希望插入到视图中的正确记录。顺便说一句,我无法理解您在对象名中使用关键字-视图、事务等。您在CREATETABLE“view”语句中引用了表名,这绕过了这些是关键字的事实,但您在稍后引用它们时没有这样做,所以我很惊讶编译器没有拒绝代码。我认为这会导致灾难,因为这会使调试变得更加困难。我只是希望您在这里的示例中这样做,而不是在PL/SQL中


就我个人而言,我在使用MERGE语句时遇到了一些问题,因为它似乎无法始终如一地工作,但那是很久以前的Oracle版本,可能是我自己不知道它应该如何工作。

我认为Dmitry试图建议在异常处理程序的行数过多的情况下使用MERGE。因此,您已经完成了SE预先选择并确定条目行出现在视图表中,因此它引发异常太多行

问题是,您不知道哪些记录引发了异常(假设您的条目表中有多行,这个过程很容易调用)。因此,我认为您使用exception部分来确定您有太多行的想法很好,但不足以满足您的需要

作为一个熟练的程序员,我不会试图想出一些非常优雅的东西,我会使用更多的蛮力

更像是:

BEGIN
    FOR entry_cur IN
        (select e.owner, e.transaction, SUM(NVL2(v.owner, 1, 0)) rec_count
           from entry e, view v
          where e.owner = v.owner(+)
            and e.transaction = v.transaction(+)
         GROUP BY e.owner, e.transaction)
    LOOP
        CASE WHEN rec_count > 0
             THEN INSERT INTO view
             ELSE MERGE INTO rejected r
                     ON (r.transaction = entry_cur.transaction
                    AND r.owner = entry_cur.owner)
                   WHEN NOT MATCHED THEN INSERT blah blah blah
        ;
    END LOOP;
END;
如果计数(*)大于1,则 没有引发异常。循环为您提供了不希望插入到视图中的正确记录。顺便说一句,我无法忘记您对对象名称使用了关键字-视图、事务等。您在“创建表”视图中引用了表名称语句,它绕过了这些是关键字这一事实,但您在稍后引用它们时没有这样做,所以我很惊讶编译器没有拒绝这些代码。我认为这会导致灾难,因为这会使调试变得更加困难。我只是希望您在这里的示例中这样做,而不是在PL/SQL中

就我个人而言,我在使用MERGE语句时遇到了一些问题,因为它似乎不一致,但那是很久以前的Oracle版本,可能是我自己不知道它应该如何工作。

感谢您的快速回复!:)我将尝试它并发布结果,但如果同一行被拒绝,则该过程应该只将数据插入被拒绝的表中