【问题标题】:Oracle: Insert only unique records into custom record in compound triggerOracle:仅将唯一记录插入复合触发器中的自定义记录
【发布时间】:2022-01-10 07:38:43
【问题描述】:

我有一个以下格式的复合触发器。我需要确保我的自定义声明 ints_rows 只采用“唯一行”。意思是如果ints_rows 已经有一个类似于正在插入的记录,它应该忽略它。更像是一个 SET 数据结构。我如何在甲骨文中做到这一点? (我对 oracle 很陌生,因此我不擅长语法)我认为我必须更改 BULK COLLECT 语句或 int_records 的声明,但我可能错了。非常感谢任何帮助/提示。

这是我的复合触发代码。

CREATE OR REPLACE
TRIGGER MY_COMPOUND_TRIGGER
FOR UPDATE OF some_random_column ON some_random_table
COMPOUND TRIGGER
  TYPE int_records IS RECORD (
    column_one another_table.column_one%TYPE,
    column_two another_table.column_two%TYPE
  );

  TYPE row_list IS TABLE OF int_records INDEX BY simple_integer;
  ints_rows row_list;

  BEFORE STATEMENT IS
  BEGIN
    ints_rows.delete;
  END BEFORE STATEMENT;

  AFTER EACH ROW IS
  BEGIN
    SELECT column_one, column_two BULK COLLECT INTO ints_rows 
      FROM some_table_x WHERE some_col_id=:OLD.some_col_id;
  END AFTER EACH ROW;

  AFTER STATEMENT IS
  BEGIN
    FOR i IN 1 .. ints_rows.COUNT LOOP
      -- DO SOMETHING
    END LOOP;

    auctions_rows.delete;
  END AFTER STATEMENT;
END;

此语句根本不应该重复。

SELECT column_one, column_two BULK COLLECT INTO ints_rows 
  FROM some_table_x WHERE some_col_id=:OLD.some_col_id;

【问题讨论】:

    标签: database oracle stored-procedures plsql triggers


    【解决方案1】:

    AFTER EACH ROW 部分中,您覆盖 整个ints_rows。原则上可能是这个:

    CREATE TABLE SOME_RANDOM_TABLE (some_random_column NUMBER, some_col_id NUMBER);
    CREATE TABLE ANOTHER_TABLE (column_one NUMBER, column_two NUMBER);
    CREATE TABLE SOME_TABLE_X (some_col_id NUMBER, column_one NUMBER, column_two NUMBER);
    
    CREATE OR REPLACE TYPE int_records AS OBJECT (
      column_one NUMBER,
      column_two NUMBER,
      MAP MEMBER FUNCTION getId RETURN VARCHAR2
    );
    
    CREATE OR REPLACE TYPE BODY int_records AS 
      MAP MEMBER FUNCTION getId RETURN VARCHAR2 IS
      BEGIN
         RETURN column_one ||','|| column_two;
      END getId;
    END;
    /
    
    CREATE OR REPLACE TYPE row_list IS TABLE OF int_records; 
    
    
    CREATE OR REPLACE TRIGGER MY_COMPOUND_TRIGGER
    FOR UPDATE OF some_random_column ON SOME_RANDOM_TABLE
    COMPOUND TRIGGER
          
      ints_rows row_list;
    
      BEFORE STATEMENT IS
      BEGIN
        ints_rows := row_list();
      END BEFORE STATEMENT;
    
    
      AFTER EACH ROW IS
        int_row row_list;
      BEGIN
        SELECT int_records(column_one, column_two) 
        BULK COLLECT INTO int_row 
        FROM SOME_TABLE_X  x
        WHERE x.some_col_id = :OLD.some_col_id;
        ints_rows := ints_rows MULTISET UNION DISTINCT int_row;
        
      END AFTER EACH ROW;
    
      AFTER STATEMENT IS
      BEGIN
        FOR i IN 1 .. ints_rows.COUNT LOOP
          NULL;
        END LOOP;
    
      END AFTER STATEMENT;
    
    END;
    

    请进行测试,如果它不起作用,请告诉我们。您可以使用循环手动区分记录,或者您需要为 RECORD 实现 MAP MEMBER FUNCTION

    【讨论】:

    • 收到错误 ORA-00904: "INT_RECORDS": 标识符无效
    • 应该工作由于TYPE int_records IS RECORD ...也许是一个错字?
    • 您好,我确认它不是错字。我也收到了另一个错误 - Error(21,79): PLS-00642: local collection types not allowed in SQL statements 以及 ORA 094
    • 您需要将类型创建为模式对象,请参阅我的更新。请注意,您不能使用表引用,例如another_table.column_one%TYPE,您必须使用本机数据类型。
    • 非常感谢您的提议,但是 SO 是基于志愿者的,让我们坚持下去。你问了一个有趣的问题——不是第 100 次“为什么WHERE TO_DATE(SYSDATE) = '10/01/22' 不起作用?”。这就是我花几分钟来回答它的原因。
    猜你喜欢
    • 2020-12-29
    • 2021-12-06
    • 2020-04-12
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 2021-07-12
    • 2019-07-06
    • 2013-10-05
    相关资源
    最近更新 更多