SQLite 中的语法错误(C 绑定)

Posted

技术标签:

【中文标题】SQLite 中的语法错误(C 绑定)【英文标题】:Syntax error in SQLite (C bindings) 【发布时间】:2015-10-11 23:15:36 【问题描述】:

我最近遇到了这个错误,无法摆脱它。这让我感到困惑,因为完全相同的请求(复制粘贴)在 CLI 中像魅力一样工作。 我正在使用来自 Qt 应用程序的 C 绑定(我后来才发现有一个用于 SQL 数据库的 Qt 包装器类)。

有问题的请求如下:

NSERT INTO classes(score,classe) VALUES((SELECT avg((julianday(arrivee)-julianday(debutCourse))/moyenne) FROM coureurs NATURAL JOIN resultats NATURAL JOIN courses NATURAL JOIN categories WHERE classe='4èmeB' AND moyenne IS NOT NULL),'4èmeB');

错误是:

“'4èmeB'”附近:语法错误

我在那里使用了三个表,分别是 classes、coureurs(跑步者)、resultats(结果)、courses(比赛)、类别。

对于每个班级,我想计算以下内容: (跑步者的时间/其类别的平均时间)的平均值。 出发时间存储在课程(比赛)表中,到达时间存储在结果(结果)表中,类别的平均时间存储在 categories.moyenne 中。如果您有更优雅的方式来执行此类请求,我会很高兴听到它。但是,我想解释一下这里发生了什么。这是因为 UTF-8 字符吗?在其他地方似乎没有问题。

如果有帮助,这里是相关的 C++ 代码:

void database::voidQuery(QString query)

    sqlite3_stmt *res;
    int rc =sqlite3_prepare_v2(db,query.toStdString().c_str(),query.length(),&res,NULL);
    if(rc != SQLITE_OK)
        fprintf(stderr, "Error in voidquery : %s in the request %s\n", sqlite3_errmsg(db),query.toStdString().c_str());
        return;
    
    sqlite3_step(res);
    sqlite3_finalize(res);

连同调用代码:

for (QStringList::iterator it = classes.begin();it != classes.end(); ++it)
      
          QString query("INSERT INTO classes(score,classe) "
                        "VALUES(("
                            "SELECT avg((julianday(arrivee)-julianday(debutCourse))/moyenne) "
                            "FROM coureurs NATURAL JOIN resultats NATURAL JOIN courses NATURAL JOIN categories "
                            "WHERE classe='%1' and moyenne is not null),'%2');");
          voidQuery(query.arg(*it).arg(*it));
      

classes 是一个 QStringList,其中包含先前查询的不同行。

提前致谢! (我希望这不是一个小问题;我花了一些时间来调试它)。

【问题讨论】:

这里有两个危险信号:1)。使用字符串操作而不是使用准备好的查询来构建 SQL 查询。 2) 这里的字符串转换会根据你所在的平台给你不一致的结果,因为 QString 总是 UTF-16 并且 std::string 没有指定编码。 “4èmeB”真的是您要查找的字符串,还是另一个复制/粘贴错误?您依赖源代码文本编码,这是一个坏主意 - 无法通过 VCS 等跨平台生存。如果您正在尝试,请查看 \u 以嵌入 Unicode 字符。 请注意,Windows 上的命令行 shell (sqlite3.exe) 无法正确处理 UTF-8 字符。 @MrEricSir 查询是在 voidQuery 函数中准备好的,但你是对的,我应该保留准备好的查询并稍后绑定参数。到目前为止,我使用 std 字符串得到了非常一致的结果(或在这种情况下出现错误),但我会接受你的建议。 @Graham-perks “4èmeB”是在运行时从数据库中提取的,它实际上可以是任何东西:) 【参考方案1】:

使用

INSERT INTO classes (score,classe) 
SELECT avg((julianday(arrivee)-julianday(debutCourse))/moyenne), '4èmeB'
FROM coureurs 
NATURAL JOIN resultats 
NATURAL JOIN courses 
NATURAL JOIN categories 
WHERE classe='4èmeB' 
AND moyenne IS NOT NULL

【讨论】:

以上是关于SQLite 中的语法错误(C 绑定)的主要内容,如果未能解决你的问题,请参考以下文章

SQLite 中的语法错误(插入语句)

“COLUMN_NAME”附近:SQLite 中的语法错误(代码 1)

从 MS-Access 中联合选择查询中的 SQLite 语法错误

SQLite错误(1):靠近“=”:语法错误

SQLite 错误代码 1:语法错误

Android Sqlite 数据库 db.exec() 在 SQL 文本中返回语法错误