【问题标题】:How to execute a trigger multiple times in SQLite android?如何在 SQLite android 中多次执行触发器?
【发布时间】:2020-01-13 15:02:48
【问题描述】:

我正在开发一个实现 SQLite 数据库的 android 应用程序,我想创建一个触发器,该触发器可以运行多次,直到达到特定计数。

需要什么

有 2 个表 TABLE 1 和 TABLE 2

  • 在表 1 上插入后,应调用触发器 12 次,然后 根据特定的 WHERE CLAUSE 在表 2 中插入 12 行
  • 第 13 次 触发器不应插入任何新行。

我尝试了什么

DatabaseHelper 类中的 onOpen 函数

 @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
        if (!db.isReadOnly()) {
            // Enable foreign key constraints
            db.execSQL("PRAGMA foreign_keys=ON;");
            db.execSQL("PRAGMA recursive_triggers = ON;\n");
        }
    }

DatabaseHelper 类中的 onCreate 函数

  public void onCreate(SQLiteDatabase db) {
        createTables(db);
         db.execSQL("CREATE TRIGGER multi_insertion AFTER INSERT ON TABLE1 \n" +
                    " WHEN (SELECT COUNT (*) from TABLE2 where MYNUMBER=1) < 12\n" +
                    "  BEGIN\n " +
                    "          insert into SCHEDULE (COLUMN1,COLUMN2) values ('001','002');  \n   " +
                    "  END;");
    }

输出:它只在表 2 中插入了 1 行

有人可以帮我实现这一目标吗?任何帮助将不胜感激

【问题讨论】:

    标签: android triggers android-sqlite android-database


    【解决方案1】:

    我相信您的问题不在于您的触发器在理论上是错误的,而是您有 3 个表:-

    • 表 1,
    • 表 2 和
    • BN_MS_LS_SCHEDULE

    您从 TABLE2 获取行数,但插入到 BN_MS_LS_SCHEDULE。

    • 这个答案是基于 12 次插入到表 1 触发 12 次,而不是解释 在表 1 上插入后,触发器应该被调用 12 次并插入 12 行,这意味着应该是 12 行在插入 table1 中的第一行时插入,如果这是要求,那么您可以:-

      • 要么使用具有多组值的单个 INSERT,例如INSERT INTO BN_MS_LS_SCHEDULE (column1,column2) VALUES('001','002'),('003','004') ......
      • 或在 BEGIN .... END 构造中使用 12 个 INSERT 语句/操作(给定示例显示了此类多 (2) 个语句/操作)

    猜测你需要做一些类似的事情:-

    public void onCreate(SQLiteDatabase db) {
        createTables(db);
         db.execSQL("CREATE TRIGGER multi_insertion AFTER INSERT ON TABLE1 " +
                    " WHEN (SELECT COUNT (*) from TABLE2 where MYNUMBER=1) < 12" +
                    " BEGIN " +
                    " INSERT into BN_MS_LS_SCHEDULE (COLUMN1,COLUMN2) VALUES ('001','002');" +
                    " INSERT into TABLE2 VALUES(?????????); " + //<<<<<<<<< insert a row into table 2 to act as a counter 
                    "  END;");
    }
    
    • 显然?????????? 应替换为一个或多个适当的值。

    • 这将在表 2 中添加一行,并且 WHEN 子句将正确执行。

      • 如您所见,在 TRIGGER 的 BEGIN .... END 构造中可以有多个 ACTION。

    示例

    根据可以从您的代码中收集到的内容考虑这个工作示例,但 table2 添加了一个额外的列,用于将 table1 中的值记录到 table1 中,从而展示了如何使用 new.列在 TRIGGER 中。

    DROP TABLE IF EXISTS table1;
    DROP TABLE IF EXISTS table2;
    DROP TABLE IF EXISTS BN_MS_LS_SCHEDULE;
    DROP TRIGGER IF EXISTS multi_insertion;
    
    CREATE TABLE IF NOT EXISTS table1 (mydata);
    CREATE TABLE IF NOT EXISTS table2 (mynumber,valuefromtable1);
    CREATE TABLE IF NOT EXISTS BN_MS_LS_SCHEDULE (COLUMN1,COLUMN2,OTHERCOLUMNS);
    
    
    CREATE TRIGGER IF NOT EXISTS multi_insertion
        AFTER INSERT ON table1
        WHEN (SELECT COUNT (*) from TABLE2 where MYNUMBER=1) < 12
        BEGIN
            INSERT INTO table2 VALUES(1,new.mydata /* record value that caused insert */); /*<<<<<<<<<< ADDED TO TRIGGER >>>>>>>>>>*/
            INSERT into BN_MS_LS_SCHEDULE (COLUMN1,COLUMN2) VALUES ('001','002');
        END;
    
    
    /* Add some testing data which will exceed the 12 rows */
    INSERT INTO table1 VALUES('a');
    INSERT INTO table1 VALUES('b');
    INSERT INTO table1 VALUES('c');
    INSERT INTO table1 VALUES('d');
    INSERT INTO table1 VALUES('e');
    INSERT INTO table1 VALUES('f');
    INSERT INTO table1 VALUES('g');
    INSERT INTO table1 VALUES('h');
    INSERT INTO table1 VALUES('i');
    INSERT INTO table1 VALUES('j');
    INSERT INTO table1 VALUES('k');
    INSERT INTO table1 VALUES('l');
    INSERT INTO table1 VALUES('m');
    INSERT INTO table1 VALUES('n');
    INSERT INTO table1 VALUES('o');
    INSERT INTO table1 VALUES('p');
    INSERT INTO table1 VALUES('q');
    INSERT INTO table1 VALUES('r');
    
    /* Results */
    SELECT * FROM table1;
    SELECT * FROM table2;
    SELECT * FROM BN_MS_LS_SCHEDULE;
    
    /* Cleanup Text Environment */
    DROP TABLE IF EXISTS table1;
    DROP TABLE IF EXISTS table2;
    DROP TABLE IF EXISTS BN_MS_LS_SCHEDULE;
    DROP TRIGGER IF EXISTS multi_insertion; 
    

    结果

    运行上述结果:-

    Table1 即插入了所有 18 行。

    表2

    • 突出显示的列显示从表 1 检索的数据
    • 可以看出只添加了 12 行

    BN_MS_LS_SCHEDULE

    • 同样只添加了 12 行

    【讨论】:

      【解决方案2】:

      一种可能的解决方案是使用触发器,但您必须小心,我不确定使用递归触发器解决此类问题是否是一种好习惯。

      您的代码无法工作,因为您在TABLE1 上调用了一次触发器,它在TABLE2 中执行了一次INSERT,仅此而已。

      但是,请检查下面的代码 sn-p。我在TABLE2 上添加了另一个触发器,它插入同一行11 次。

      @Override
          public void onCreate(SQLiteDatabase db) {
              db.execSQL("PRAGMA recursive_triggers = ON;\n");
      
              db.execSQL("CREATE TABLE TABLE1 (NAME VARCHAR(20))");
      
              db.execSQL("CREATE TABLE TABLE2 (COL1 NUMBER, COL2 NUMBER)");
      
              db.execSQL("CREATE TRIGGER multi_insertion_table1 BEFORE INSERT ON TABLE1 \n" +
                      " WHEN (SELECT COUNT (*) from TABLE2 where COL1=1 and COL2=2) < 12\n" +
                      "  BEGIN \n" +
                      "          insert into TABLE2 values (1, 2);  \n   " +
                      "  END;");
      
              db.execSQL("CREATE TRIGGER multi_insertion_table2 AFTER INSERT ON TABLE2 \n" +
                      " WHEN (SELECT COUNT (*) from TABLE2 where COL1=1 and COL2=2) < 12\n" +
                      "  BEGIN \n" +
                      "          insert into TABLE2 values (1, 2);  \n  " +
                      "  END;");
          }
      

      在这种情况下,第二个触发器必须是 AFTER STATEMENT,否则 DB 将抛出异常并显示消息 too many levels of trigger recursion。检查这个answer

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-13
        • 2019-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-14
        • 1970-01-01
        相关资源
        最近更新 更多