我的文件中包含多个要执行的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 部分不执行任何操作。
最终发生的事情是:
这与sqlite文档中描述的一样。
我的问题是我希望报告插入后的所有查询都使用report.id。
无论如何,我可以在数据库端使用它而无需在as3中使用解决方案吗?
答案 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
}
}