Flex:多次插入调用的sqlite last_insert_rowid

时间:2010-09-22 16:00:44

标签: flex actionscript-3 sqlite

我的文件中包含多个要执行的SQL语句。

INSERT INTO reports (a,b,c) VALUES (1,2,3);

INSERT INTO units (report_id, e, f, g) VALUES ( (SELECT last_insert_rowid() FROM reports), 4, 5, 6);

INSERT INTO elements (report_id, h, i, j) VALUES ( (SELECT last_insert_rowid() FROM reports), 7, 8, 9);

子选择的 FROM reports 部分不执行任何操作。

最终发生的事情是:

  1. 在报告中插入一行,并自动增加reports.id字段
  2. 将一行插入到report_id等于报告ID
  3. 的单元中
  4. 在report_id等于插入的最后一行的units.id的元素中插入一行
  5. 这与sqlite文档中描述的一样。

    我的问题是我希望报告插入后的所有查询都使用report.id。

    无论如何,我可以在数据库端使用它而无需在as3中使用解决方案吗?

1 个答案:

答案 0 :(得分:2)

有一种方法可以做到这一点,但它在AS3中使用参数。

所做的不是在每次调用中使用SELECT last_insert_row()函数,而是用参数替换它。

INSERT INTO elements (report_id, h, i, j) VALUES (@id, 7, 8, 9);

现在在我的代码中,我必须将文件拆分为一个数组,以便每个单独的查询都是单独处理的(这就是AS3如何实现sqlite的API)。

var sqlArray:Array = sql.split(";\n\n");

现在我要做的是执行导入报告本身的第一个语句。

statement.text = sqlArray[0];
statement.execute();

现在有趣的部分。你需要把ID拿回来。所以我们运行另一个查询。

statement.text = "SELECT last_insert_rowid() as ID";
statement.execute();
var id:int = statement.getResult().data[0].id;

现在我们可以使用id作为参数来遍历其余的查询。

for(var i:int = 1; i < sqlArray.length - 1; i++) { 
  /**
   * start at 1 because we already inserted the report
   * end at length -1 because our last entry is empty because of how split works on our data
   **/
  statement.text = sqlArray[i];
  statement.parameters['@ID'] = id;
  statement.execute();
}

这有点复杂,但并不多,最终会起作用。

将所有内容组合成一个函数(省略很多类开销)将是:

function importFromSQLString(sql:String):void {
  try{
    connection.begin();
    var sqlArray:Array = sql.split(";\n\n");
    statement.text = sqlArray[0];
    statement.execute();

    statement.text = "SELECT last_insert_rowid() as ID";
    statement.execute();
    var id:int = statement.getResult().data[0].id;

    for(var i:int = 1; i < sqlArray.length - 1; i++) { 
      statement.text = sqlArray[i];
      statement.parameters['@ID'] = id;
      statement.execute();
    }
    connection.commit();
    statement.clearParameters();
  } catch (e:Error) {
    connection.rollback(); //cleanup if there was a failure
  }
}