【问题标题】:Separate incrementing trigger for every row in the table表中每一行的单独递增触发器
【发布时间】:2018-05-29 17:56:12
【问题描述】:

我在为表中的每一行创建递增触发器时遇到问题。我需要的是计算依赖于其中一列的行。例如:

     table
column1|column2
    1  |  1
    1  |  2
    2  |  1
    1  |  3
    3  |  1
    2  |  2

我已经创建了序列:

CREATE SEQUENCE inc_seq
MINVALUE 1
START WITH 1
INCREMENT BY 1;

并触发:

CREATE OR REPLACE TRIGGER inc_on_insert
BEFORE INSERT ON table
FOR EACH ROW
BEGIN
SELECT inc_seq.nextval
INTO :new.column2
FROM dual;
END;

我现在得到的是递增的值,但每一行都会继续递增,并且不会重置。我不知道如何在 column1 的每个不同值上创建从 1 开始的语句。

编辑:

CREATE TABLE moves (
    move_id        NUMBER,
    game_id NOT NULL
        REFERENCES games ( game_id )
            ON DELETE CASCADE,
    move_number    NUMBER NOT NULL,
    stages_count   NUMBER DEFAULT 1,
    CONSTRAINT move_pk PRIMARY KEY ( move_id ),
    CONSTRAINT moves_const_1 UNIQUE ( game_id,
                                      move_number,
                                      stages_count )
);

【问题讨论】:

    标签: sql oracle plsql triggers


    【解决方案1】:

    触发器不适合此类用途。我宁愿使用row_number() 创建一个视图。您仍然可以使用触发器/序列为表生成 id 列。

    CREATE
        OR replace VIEW t_view AS
    SELECT column1
        ,row_number() OVER (
            PARTITION BY column1 ORDER BY id --id generated using your trigger
            ) AS column2
    FROM t
    ORDER BY id;
    

    Demo

    select * from t_view;
    
    | COLUMN1 | COLUMN2 |
    |---------|---------|
    |       1 |       1 |
    |       1 |       2 |
    |       2 |       1 |
    |       1 |       3 |
    |       3 |       1 |
    |       2 |       2 |
    

    【讨论】:

    • 所以如果我有这个表创建脚本(在主帖中编辑以获得更好的可见性),我如何将move_number 替换为依赖于row_number()row_number()
    • @Jaav :您不能将move_number 替换为row_number,反之亦然。 row_number 是一个分析函数 docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm ,您只需在我的查询中替换 column1 和 id 以包含正确的列。 id 可以是你的move_id。但是,我不确定其他列,因为您没有显示其中包含的内容。
    【解决方案2】:

    我赞同 Kaushik 的意见,不会为此使用触发器。例如,如果一行被删除会怎样?

    但是,如果您坚持,我会这样编码:

    CREATE TABLE mytable (column1 NUMBER, column2 NUMBER);
    
    CREATE OR REPLACE TRIGGER inc_on_insert
    BEFORE INSERT ON mytable
    FOR EACH ROW
    BEGIN
      SELECT COUNT(*)+1 INTO :NEW.column2 
        FROM mytable 
       WHERE column1=:NEW.column1;
    END;
    /
    
    INSERT INTO mytable(column1) VALUES (5);
    SELECT * FROM mytable;
    5 1
    
    INSERT INTO mytable(column1) VALUES (5);
    SELECT * FROM mytable;
    5 1
    5 2
    
    INSERT INTO mytable(column1) VALUES (6);
    SELECT * FROM mytable;
    5 1
    5 2
    6 1
    
    INSERT INTO MYTABLE(COLUMN1) VALUES (5);
    SELECT * FROM mytable;
    5 1
    5 2
    6 1
    5 3
    

    【讨论】:

      【解决方案3】:

      请尝试以下方法:

      CREATE OR REPLACE TRIGGER inc_on_insert
      BEFORE INSERT ON table
      FOR EACH ROW
      
      BEGIN
      select count(1) into thereiscolumn1 from table where column1 = :new.column1 and rownum=1;
      if thereiscolumn1 > 0 THEN
          SELECT (MAX(column2) + 1 ) INTO :new.column2 from table WHERE column1 = :new.column1
      ELSE
          SELECT 1 INTO :new.column2 FROM dual;
      END IF;
      
      END;
      

      【讨论】:

        猜你喜欢
        • 2013-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-04
        • 2010-09-22
        • 2016-04-26
        • 1970-01-01
        相关资源
        最近更新 更多