我有一个包含几个 SQL 语句的文件,我想用它们来初始化一个新的 sqlite3 数据库文件。显然,sqlite3 只通过函数处理一个查询中的多个语句 sqlite3_exec()
,而不是通过prepare/step/finalize
函数。没关系,但我想直接使用 QtSQL api 而不是 c api。通过 QSqlQuery 加载同一个初始化文件只执行第一条语句,就像直接使用 sqlite3 api 中的 prepare/step/finalize 函数一样。有没有办法让 QSqlQuery 运行多个查询,而不必为每个语句单独调用 query.exec() ?
问问题
12115 次
2 回答
13
正如QSqlQuery::prepare()和QSqlQuery::exec()的 Qt 文档中明确指出的那样,
对于 SQLite,查询字符串一次只能包含一条语句。如果给出了多个语句,则该函数返回 false。
正如您已经猜到的,唯一已知的解决此限制的方法是将所有 sql 语句用某个字符串分隔,拆分语句并在循环中执行每个语句。
请参阅以下示例代码(它使用“;”作为分隔符,并假设查询中未使用相同的字符。这缺乏通用性,因为您可能在 where/insert/update 语句中的字符串文字中有给定的字符):
QSqlDatabase database;
QSqlQuery query(database);
QFile scriptFile("/path/to/your/script.sql");
if (scriptFile.open(QIODevice::ReadOnly))
{
// The SQLite driver executes only a single (the first) query in the QSqlQuery
// if the script contains more queries, it needs to be splitted.
QStringList scriptQueries = QTextStream(&scriptFile).readAll().split(';');
foreach (QString queryTxt, scriptQueries)
{
if (queryTxt.trimmed().isEmpty()) {
continue;
}
if (!query.exec(queryTxt))
{
qFatal(QString("One of the query failed to execute."
" Error detail: " + query.lastError().text()).toLocal8Bit());
}
query.finish();
}
}
于 2012-01-30T11:12:36.340 回答
1
我编写了一个简单的函数来从文件中读取 SQL 并一次执行一条语句。
/**
* @brief executeQueriesFromFile Read each line from a .sql QFile
* (assumed to not have been opened before this function), and when ; is reached, execute
* the SQL gathered until then on the query object. Then do this until a COMMIT SQL
* statement is found. In other words, this function assumes each file is a single
* SQL transaction, ending with a COMMIT line.
*/
void executeQueriesFromFile(QFile *file, QSqlQuery *query)
{
while (!file->atEnd()){
QByteArray readLine="";
QString cleanedLine;
QString line="";
bool finished=false;
while(!finished){
readLine = file->readLine();
cleanedLine=readLine.trimmed();
// remove comments at end of line
QStringList strings=cleanedLine.split("--");
cleanedLine=strings.at(0);
// remove lines with only comment, and DROP lines
if(!cleanedLine.startsWith("--")
&& !cleanedLine.startsWith("DROP")
&& !cleanedLine.isEmpty()){
line+=cleanedLine;
}
if(cleanedLine.endsWith(";")){
break;
}
if(cleanedLine.startsWith("COMMIT")){
finished=true;
}
}
if(!line.isEmpty()){
query->exec(line);
}
if(!query->isActive()){
qDebug() << QSqlDatabase::drivers();
qDebug() << query->lastError();
qDebug() << "test executed query:"<< query->executedQuery();
qDebug() << "test last query:"<< query->lastQuery();
}
}
}
于 2013-10-06T11:53:46.730 回答