H2. Как создать триггер базы данных, который записывает изменение строки в другую таблицу?

Как создать триггер базы данных, который регистрирует изменение строки в другой таблице в H2?

В MySQL это можно сделать легко:

CREATE TRIGGER `trigger` BEFORE UPDATE ON `table`
  FOR EACH ROW BEGIN
    INSERT INTO `log`
    (
      `field1`
      `field2`,
      ...
    )
    VALUES
    (
      NEW.`field1`,
      NEW.`field2`,
      ...
    ) ;
    END;

person Pinch    schedule 01.05.2015    source источник


Ответы (2)


Объявите этот триггер:

CREATE TRIGGER my_trigger
BEFORE UPDATE
ON my_table
FOR EACH ROW
CALL "com.example.MyTrigger"

Реализация триггера с помощью Java/JDBC:

public class MyTrigger implements Trigger {

    @Override
    public void init(Connection conn, String schemaName, 
                     String triggerName, String tableName, boolean before, int type)
    throws SQLException {}

    @Override
    public void fire(Connection conn, Object[] oldRow, Object[] newRow)
    throws SQLException {
        try (PreparedStatement stmt = conn.prepareStatement(
            "INSERT INTO log (field1, field2, ...) " +
            "VALUES (?, ?, ...)")
        ) {
            stmt.setObject(1, newRow[0]);
            stmt.setObject(2, newRow[1]);
            ...

            stmt.executeUpdate();
        }
    }

    @Override
    public void close() throws SQLException {}

    @Override
    public void remove() throws SQLException {}
}

Реализация триггера с помощью jOOQ:

Поскольку вы добавили к вопросу тег jOOQ, я подозреваю, что эта альтернатива тоже может быть актуальной. Конечно, вы можете использовать jOOQ внутри триггера H2:

    @Override
    public void fire(Connection conn, Object[] oldRow, Object[] newRow)
    throws SQLException {
        DSL.using(conn)
           .insertInto(LOG, LOG.FIELD1, LOG.FIELD2, ...)
           .values(LOG.FIELD1.getDataType().convert(newRow[0]), 
                   LOG.FIELD2.getDataType().convert(newRow[1]), ...)
           .execute();
    }
person Lukas Eder    schedule 03.05.2015

Более короткая версия ответа Лукаса Эдера:

CREATE TRIGGER my_trigger
BEFORE UPDATE
ON my_table
FOR EACH ROW
CALL "com.example.MyTrigger"
public class MyTrigger extends TriggerAdapter {

    @Override
    public void fire(Connection conn, ResultSet oldRow, ResultSet newRow) throws SQLException {
        // mannipulate the rows here by using the methods on the oldRow and newRow objects
    }
}
person Yonas    schedule 22.07.2020
comment
Красиво, но нет возможности сослаться на таблицу. - person Wojciech Marciniak; 27.04.2021