代码之家  ›  专栏  ›  技术社区  ›  Guillaume

HSQL触发器生成SQL错误:-458,SQL状态:S1000/java.lang.ArrayIndexOutOfBoundsException

  •  0
  • Guillaume  · 技术社区  · 8 年前

    我有一个Oracle数据库模式的HSQL版本来执行单元测试。

    我需要在更新时使用当前时间戳更新列。

    我实现的触发器是由hsql引擎毫无怨言地加载的,但当我尝试更新行时,它在运行时崩溃。

    下面是一个示例测试用例,您可以在配置了spring和junit的项目中运行:

    public class UtSqlTriggerTest {
        @Test public void testTrigger() throws SQLException {
            ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
            resourceDatabasePopulator.addScript(new InMemoryResource(
                "CREATE TABLE TEST (ID NUMERIC NOT NULL PRIMARY KEY,DATA VARCHAR(200), LAST_UPDATE TIMESTAMP);\n" +
    
                 "CREATE TRIGGER updTimestamp AFTER UPDATE OF DATA ON TEST\n" +
                 "REFERENCING NEW AS newrow OLD AS oldrow\n" +
                 "FOR EACH ROW\n" +
                 "SET newrow.LAST_UPDATE = current_timestamp;"));
    
            Connection connection = DriverManager.getConnection("jdbc:hsqldb:file:/opt/db/testdb;shutdown=true", "SA", "");
            resourceDatabasePopulator.populate(connection);
    
            JdbcTemplate tjdbc = new JdbcTemplate(new SingleConnectionDataSource(connection, true));
            tjdbc.update("INSERT INTO TEST(ID, DATA) VALUES (0, 'HELLO')");
            tjdbc.update("UPDATE TEST SET DATA = 'HELLO WORLD' WHERE ID = 0");
            tjdbc.queryForObject("SELECT LAST_UPDATE FROM TEST WHERE ID = 0", Date.class);
        }               
    }
    

    这个触发器怎么了?为什么会生成ArrayIndexOutOfBoundException?

    CREATE TRIGGER updateDateAjoutFichier AFTER UPDATE OF DATA ON TEST
    REFERENCING NEW AS newrow OLD AS oldrow
    FOR EACH ROW
    SET newrow.LAST_UPDATE = current_timestamp;
    
    1 回复  |  直到 8 年前
        1
  •  3
  •   a_horse_with_no_name    8 年前

    在SQL客户端中运行CREATE触发器时,将看到以下错误消息:

    尝试分配给不可更新列:LAST_UPDATE[SQL状态=0U000,DB错误代码=-2500]

    这是因为您正在尝试修改 AFTER 触发只有在 BEFORE 触发因此,您应该使用:

    CREATE TRIGGER updTimestamp BEFORE UPDATE OF DATA ON TEST
    REFERENCING NEW AS newrow OLD AS oldrow
    FOR EACH ROW
       SET newrow.LAST_UPDATE = current_timestamp;