【问题标题】:trying to create a table gives a sql logic error尝试创建表会出现 sql 逻辑错误
【发布时间】:2019-03-20 20:00:50
【问题描述】:

我正在尝试创建一个 SQLite 数据库。我创建了一个新文件,然后我想创建这个表:

CREATE TABLE 'session_properties'
(
    'user_name' TEXT NOT NULL, -- Name of the user.
    'user_surname' TEXT NOT NULL, -- Surname of the user.
    'description' TEXT NOT NULL, -- Description of the session.
    CONSTRAINT 'PK_user' PRIMARY KEY ('user_name','user_surname')
)
;

这是我的代码:

void checkErrorCode(int code){
  if (code != SQLITE_OK) {
    auto message = sqlite3_errstr(code);
    throw WSession::Exception(code, message);
  }
}

…

const char CreateDatabase_sql[] = {0x43,0x52,0x45,0x41,0x54,0x45,0x20,0x54,0x41,0x42,0x4c,0x45,0x20,0x27,0x73,0x65,0x73,0x73,0x69,0x6f,0x6e,0x5f,0x70,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x27,0x0d,0x0a,0x28,0x0d,0x0a,0x09,0x27,0x75,0x73,0x65,0x72,0x5f,0x6e,0x61,0x6d,0x65,0x27,0x20,0x54,0x45,0x58,0x54,0x20,0x4e,0x4f,0x54,0x20,0x4e,0x55,0x4c,0x4c,0x2c,0x20,0x2d,0x2d,0x20,0x4e,0x61,0x6d,0x65,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x75,0x73,0x65,0x72,0x2e,0x0d,0x0a,0x09,0x27,0x75,0x73,0x65,0x72,0x5f,0x73,0x75,0x72,0x6e,0x61,0x6d,0x65,0x27,0x20,0x54,0x45,0x58,0x54,0x20,0x4e,0x4f,0x54,0x20,0x4e,0x55,0x4c,0x4c,0x2c,0x20,0x2d,0x2d,0x20,0x53,0x75,0x72,0x6e,0x61,0x6d,0x65,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x75,0x73,0x65,0x72,0x2e,0x0d,0x0a,0x09,0x27,0x64,0x65,0x73,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x27,0x20,0x54,0x45,0x58,0x54,0x20,0x4e,0x4f,0x54,0x20,0x4e,0x55,0x4c,0x4c,0x2c,0x20,0x2d,0x2d,0x20,0x44,0x65,0x73,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x65,0x73,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x09,0x43,0x4f,0x4e,0x53,0x54,0x52,0x41,0x49,0x4e,0x54,0x20,0x27,0x50,0x4b,0x5f,0x75,0x73,0x65,0x72,0x27,0x20,0x50,0x52,0x49,0x4d,0x41,0x52,0x59,0x20,0x4b,0x45,0x59,0x20,0x28,0x27,0x75,0x73,0x65,0x72,0x5f,0x6e,0x61,0x6d,0x65,0x27,0x2c,0x27,0x75,0x73,0x65,0x72,0x5f,0x73,0x75,0x72,0x6e,0x61,0x6d,0x65,0x27,0x29,0x0d,0x0a,0x29,0x0d,0x0a,0x3b,0x0d,0x0a,0x00};
// you can change the string with this one:
// const char CreateDatabase_sql[] = "CREATE TABLE 'session_properties' ('user_name' TEXT NOT NULL, 'user_surname' TEXT NOT NULL, 'description' TEXT NOT NULL, CONSTRAINT 'PK_user' PRIMARY KEY ('user_name','user_surname'));\0";
const unsigned CreateDatabase_sql_size = sizeof(CreateDatabase_sql);
sqlite3_stmt* statement;
sqlite3* m_database;
checkErrorCode(sqlite3_open_v2("MyDatabase.myExt", &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr));
checkErrorCode(sqlite3_prepare_v2(m_database, CreateDatabase_sql, -1, &statement, nullptr));
checkErrorCode(sqlite3_step(statement));
checkErrorCode(sqlite3_finalize(statement));

CreateDatabase_sql[] 由用于嵌入 .sql 文件的脚本创建。

如果我运行此代码,sqlite3_prepare_v2 将返回错误 1 - SQL Logic error。如果我手动运行查询(例如使用DB Browser gui),它会起作用并创建表。

我做错了什么?

【问题讨论】:

  • CreateDatabase_sql 到底是什么东西?只需使用普通的人类可读字符串即可。
  • 正如我所说,这是我用于将外部文件嵌入到可执行文件中的脚本的结果。我想在示例中进行维护,以使代码与给我问题的代码尽可能相似。这正是为创建表而编写的 SQL 脚本的文本。
  • 好吧,当你的代码中最重要的东西不可读时,这很难提供帮助。
  • 已更新,但结果相同。
  • 表名周围有单引号。在我看来,这只是一个简单的印刷错误。

标签: c++ sql sqlite


【解决方案1】:

这是您代码的清理后、可编译的独立版本(带有更好的错误消息、错误修复(查看 sqlite3_step() 返回的内容),并从您的 sql 语句中删除了一堆奇怪的东西(单引号用于字符串,双引号用于标识符但通常不需要,为什么最后有一个文字\0 char?)):

#include <cstdlib>
#include <iostream>
#include <sqlite3.h>

void checkErrorCode(sqlite3 *db, int code) {
  if (code != SQLITE_OK && code != SQLITE_DONE) {
    const char *err;
    if (db) {
      err = sqlite3_errmsg(db);
    } else {
      err = sqlite3_errstr(code);
    }
    std::cerr << "Error " << code << ": " << err << '\n';
    std::exit(EXIT_FAILURE);
  }
}

int main() {
  sqlite3 *db;
  sqlite3_stmt *statement;
  const char CreateDatabase_sql[] = R"(
CREATE TABLE session_properties(user_name TEXT NOT NULL
                              , user_surname TEXT NOT NULL
                              , description TEXT NOT NULL
                              , CONSTRAINT PK_user
                                PRIMARY KEY(user_name, user_surname))
)";

  checkErrorCode(nullptr,
                 sqlite3_open_v2("test.db", &db,
                                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
                                 nullptr));
  checkErrorCode(
      db, sqlite3_prepare_v2(db, CreateDatabase_sql, -1, &statement, nullptr));
  checkErrorCode(db, sqlite3_step(statement));
  checkErrorCode(db, sqlite3_finalize(statement));
  std::cout << "It seems to have worked.\n";
  sqlite3_close(db);
  return 0;
}

现在,运行它...

$ ./a.out
It seems to have worked.

但是再次运行它......

$ ./a.out
Error 1: table session_properties already exists

(与你的时髦版本的声明相同的结果)

所以我怀疑你的问题来自于试图创建一个已经存在于你的数据库中的表。切换到CREATE TABLE IF NOT EXISTS ...,如果这确实是问题,它不应该给出错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-15
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 2019-04-22
    • 1970-01-01
    相关资源
    最近更新 更多