【问题标题】:syntax error with sqlite3_exec in C, but works fine in sqlite3 CLI programC 中 sqlite3_exec 的语法错误,但在 sqlite3 CLI 程序中工作正常
【发布时间】:2017-02-24 19:34:25
【问题描述】:

我正在尝试开发一个跨平台的 C 程序来执行简单的 SQLite 数据库管理。它只是创建一些表、触发器,然后定期插入记录。

我遇到的问题是我尝试通过直接使用 SQL 命令调用 sqlite3_exec 以编程方式创建触发器时遇到语法错误。有趣的是,我的程序在 Windows 中运行良好。它成功创建/删除触发器。但是,在 Linux (Ubuntu) 上运行时,出现以下语法错误。

Info: connecting device...
Info: Opened database ./test.db successfully
Info: operation done successfully
Error: Time:Fri Feb 24 17:22:29 2017 File:/home/stephen/code/IoTGW/azure-iot-gateway-sdk_0222/modules/sqlite/src/sqlite.c Func:sqlite_exec Line:315 SQL error: near ",": syntax error
Error: Time:Fri Feb 24 17:22:29 2017 File:/home/stephen/code/IoTGW/azure-iot-gateway-sdk_0222/modules/sqlite/src/sqlite.c Func:sqlite_exec Line:317 Error Query: @CREATE TRIGGER MODBUS_size_control INSERT ON MODBUS WHEN (select count(*) from MODBUS)>10
BEGIN
DELETE FROM MODBUS WHERE (ADDRESS,MAC,DATETIME) IN (SELECT ADDRESS,MAC,DATETIME FROM MODBUS ORDER BY DATETIME limit (select count(*) - 10 from MODBUS));
END;@

*请注意,添加@ 符号只是为了确保我没有在 SQL 命令中包含一些愚蠢的不可见值。 @ 不是 sqlite3_exec 执行的 SQL 命令的一部分。

除此之外,其他插入操作都可以正常工作。

另一个奇怪的事情是我运行了完全相同的 SQL 命令,导致 sqlite3 shell 程序出错。它工作得很好。

在 sqlite3 shell 中创建触发器后。我再次运行我的程序,它给了我一个完全不同的错误。

Error: Time:Fri Feb 24 17:52:49 2017 File:/home/stephen/code/IoTGW/azure-iot-gateway-sdk_0222/modules/sqlite/src/sqlite.c Func:sqlite_exec Line:315 SQL error: malformed database schema (MODBUS_size_control) - near ",": syntax error
Error: Time:Fri Feb 24 17:52:49 2017 File:/home/stephen/code/IoTGW/azure-iot-gateway-sdk_0222/modules/sqlite/src/sqlite.c Func:sqlite_exec Line:317 Error Query: @CREATE TRIGGER MODBUS_size_control INSERT ON MODBUS WHEN (select count(*) from MODBUS)>10
BEGIN
DELETE FROM MODBUS WHERE (ADDRESS,MAC,DATETIME) IN (SELECT ADDRESS,MAC,DATETIME FROM MODBUS ORDER BY DATETIME limit (select count(*) - 10 from MODBUS));
END;@
Error: Time:Fri Feb 24 17:52:51 2017 File:/home/stephen/code/IoTGW/azure-iot-gateway-sdk_0222/modules/sqlite/src/sqlite.c Func:sqlite_exec Line:315 SQL error: malformed database schema (MODBUS_size_control) - near ",": syntax error
Error: Time:Fri Feb 24 17:52:51 2017 File:/home/stephen/code/IoTGW/azure-iot-gateway-sdk_0222/modules/sqlite/src/sqlite.c Func:sqlite_exec Line:317 Error Query: @INSERT INTO MODBUS(VALUE,ADDRESS,MAC,DATETIME) VALUES(09221,40002,'01:01:01:01:01:01','2017-02-24 17:52:51');INSERT INTO MODBUS(VALUE,ADDRESS,MAC,DATETIME) VALUES(29113,40001,'01:01:01:01:01:01','2017-02-24 17:52:51');@

如图所示,即使以前有效的插入命令也不再有效。似乎触发器导致了所有问题。但我就是不明白为什么。它适用于 Windows,适用于 sqlite3 shell 中的 Ubuntu。即使我在创建触发器后从 sqlite3 shell 插入记录,它也可以正常工作。 请指教。提前致谢。

【问题讨论】:

  • 已添加。谢谢提醒。
  • 这不是最小的。
  • 对不起,我现在没有我的开发机器。我会尽快创建一个。

标签: c sqlite ubuntu syntax-error


【解决方案1】:

问题记录在SQLite Documentation:

触发器中 UPDATE、DELETE 和 INSERT 语句的语法限制

触发器中的 UPDATE、DELETE 和 INSERT 语句不支持 UPDATE、DELETE 和 INSERT 语句的完整语法。以下限制适用:

  • 不支持 UPDATE 和 DELETE 语句中的 ORDER BY 和 LIMIT 子句。 ORDER BY 和 LIMIT 通常不支持任何上下文中的 UPDATE 或 DELETE,但可以使用 SQLITE_ENABLE_UPDATE_DELETE_LIMIT 编译时选项为顶级语句启用。但是,该编译时选项仅适用于顶级 UPDATE 和 DELETE 语句,不适用于触发器中的 UPDATE 和 DELETE 语句。

您在触发器的 DELETE 语句中使用了 LIMIT-Clause:

DELETE FROM MODBUS 
    WHERE (ADDRESS,MAC,DATETIME) IN (SELECT ADDRESS,MAC,DATETIME FROM MODBUS 
    ORDER BY DATETIME
    limit (select count(*) - 10 from MODBUS));

但是,错误消息有些误导。

【讨论】:

  • 感谢您的解释。所以我可能在不同的编译时选项中构建了 SQLite 库和 SQLite3 shell 程序。
  • @S.C 根据文档,它甚至应该从不在触发器内工作。
  • 对,但不知何故,它在 Windows 平台和 Windows 中的 SQLite shell 程序中工作。我将重写查询以遵守规则。
猜你喜欢
  • 2021-10-13
  • 2015-06-03
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多