插入Sqlite错误

时间:2018-01-19 02:08:02

标签: c++ sqlite

我对sqlite很新,特别是在C设置中。我试图在我的表格中插入一条记录。

这是我的代码:

int InsertIntoFileActionTable(FileActionData* fad)
{
    sqlite3_stmt * stmt;
    char *ErrMsg;
    const char *pzTail;
    int result = 0;

    string sql;
    sql = "INSERT INTO FileActionData (RootName, RootDirectory, RelativePath, ParentPath, FileName, Stem, Extension, UserName, SignalFlag, ProcessID, ProtectionOn, BSSMember, ProcessTime) ";
    sql += "VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    result = sqlite3_prepare(pDb, &sql[0], 1000, &stmt, &pzTail);//This reseult is x00001
    result = sqlite3_bind_text16(stmt, 1, (void*)(&fad->RootName[0]), fad->RootName.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_text16(stmt, 2, (void*)(&fad->RootDirectory[0]), fad->RelativePath.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_text16(stmt, 3, (void*)(&fad->RelativePath[0]), fad->RelativePath.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_text16(stmt, 4, (void*)(&fad->ParentPath[0]), fad->ParentPath.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_text16(stmt, 5, (void*)(&fad->FileName[0]), fad->FileName.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_text16(stmt, 6, (void*)(&fad->Stem[0]), fad->Stem.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_text16(stmt, 7, (void*)(&fad->Extension[0]), fad->Extension.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_text16(stmt, 8, (void*)(&fad->UserName[0]), fad->UserName.length(), SQLITE_STATIC);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_int(stmt, 9, fad->SignalFlag);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_int(stmt, 10, fad->ProcessID);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_int(stmt, 11, fad->ProtectionOn);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_int(stmt, 12, fad->BSSMember);//This reseult is x00015 SQLITE_MISUSE
    result = sqlite3_bind_int(stmt, 13, fad->ProcessTime);//This reseult is x00015 SQLITE_MISUSE

    result = sqlite3_step(stmt);//This reseult is x00015 SQLITE_MISUSE
    if (result == SQLITE_MISUSE)
    {
        printf("MISUSE error");
    }
    return result;
}

这是我的FileActionData定义:

class FileActionData
{
public:
    std::wstring RootName;
    std::wstring RootDirectory;
    std::wstring RelativePath;
    std::wstring ParentPath;
    std::wstring FileName;
    std::wstring Stem;
    std::wstring Extension;
    unsigned long SignalFlag;
    unsigned long ProcessID;
    BOOL ProtectionOn;
    BOOL BSSMember;
    std::wstring UserName;
    time_t ProcessTime;

};

我得到的错误是Prepare上的1(Generic)和其他来电时的x15(21)(Misuse)。

添加了其他信息: 我也尝试过:

        result = sqlite3_prepare16_v3(pDb, &sql[0], 1000, 0, &stmt, (const 
 void**)&pzTail);//This result is x00001

stmt为null,这就是我的其余调用返回Misuse的原因。

pDb在其他地方开放。

我做错了什么? TIA

2 个答案:

答案 0 :(得分:0)

查看sqlite的文档:

  

https://www.sqlite.org/capi3ref.html#sqlite3_bind_blob

int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
     

第三个参数是绑定到参数的值。如果sqlite3_bind_text()sqlite3_bind_text16()sqlite3_bind_blob()的第三个参数是NULL指针,则忽略第四个参数,最终结果与sqlite3_bind_null()相同。

     

在具有第四个参数的那些例程中,其值是参数中的字节数。要清楚:值是值中的字节数,而不是字符数。如果sqlite3_bind_text()sqlite3_bind_text16()的第四个参数是负数,那么字符串的长度是第一个零终止符之前的字节数。如果sqlite3_bind_blob()的第四个参数为负,则行为未定义。如果向sqlite3_bind_text()sqlite3_bind_text16()sqlite3_bind_text64()提供了非负的第四个参数,则该参数必须是假定字符串NUL终止时NUL终结符将发生的字节偏移量。如果在字节偏移小于第四个参数的值时出现任何NUL字符,则结果字符串值将包含嵌入的NUL。涉及具有嵌入式NUL的字符串的表达式的结果是未定义的。

第三个参数应该是一个字符串,第四个参数应该是字节大小,而不是 字符串长度。

应该是 1

result = sqlite3_bind_text16(stmt, 1, (void*)(fad->RootName.c_str()),
        fad->RootName.size() * sizeof(wchar_t), SQLITE_STATIC);

或者Mark Benningfield建议:

result = sqlite3_bind_text16(stmt, 1, (void*)(fad->RootName.c_str()),
        -1, SQLITE_STATIC);

1 我没有太多地使用C ++,这就是为什么我不得不查看如何获得 std::wstring的大小。我发现了这个:How can I get the byte size of std::wstring?

答案 1 :(得分:0)

我不得不做一些研究以确认我的唠叨怀疑。 std::string的内部表示不保证在内存中是连续的,甚至不能终止(直到C ++ 11,我不确定Visual Studio是否完全实现),所以发送SQLite第一个角色的地址不起作用。

为SQL文本定义char*,然后传递,或将调用结果传递给.c_str()成员函数。这同样适用于后续参数绑定调用:您也不能传递std::wstring的第一个字符的地址。

如果你有一个有效的UTF-8 sql语句,传递-1让SQLite将文本解析为空终止符,并且数据库句柄实际上是打开的,它应该可以工作。