首页 > 解决方案 > SQLite3 - 以函数参数为值

问题描述

我正在尝试使用sqlite3数据库创建一个类,该方法应在用户将文件添加到应用程序时将数据插入表中,但它没有按预期工作,

    void Database::InsertSample(int Favorite, std::string Filename,
                                std::string SamplePack, int Channels, int Length,
                                int SampleRate, int Bitrate, std::string Comment,
                                std::string Path)
    {
        try
        {
            rc = sqlite3_open("Samples.db", &DB);
    
        sql = "INSERT INTO SAMPLES (FAVORITE, FILENAME, SAMPLEPACK, CHANNELS, \
                                    LENGTH, SAMPLERATE, BITRATE, BITSPERSAMPLE, PATH) \
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
    
        rc = sqlite3_prepare_v2(DB, sql.c_str(), 0, &stmt, 0);   // create the prepared statement
    
        rc = sqlite3_bind_int(stmt, 1, Favorite);
    
        rc = sqlite3_bind_text(stmt, 2, Filename.c_str(), Filename.size(), SQLITE_STATIC);
    
        rc = sqlite3_bind_text(stmt, 3, SamplePack.c_str(), SamplePack.size(), SQLITE_STATIC);
    
        rc = sqlite3_bind_int(stmt, 4, Channels);
    
        rc = sqlite3_bind_text(stmt, 5, Filename.c_str(), Filename.size(), SQLITE_STATIC);
    
        rc = sqlite3_bind_int(stmt, 6, Length);
    
        rc = sqlite3_bind_int(stmt, 7, SampleRate);
    
        rc = sqlite3_bind_int(stmt, 8, Bitrate);
    
        rc = sqlite3_bind_text(stmt, 9, Comment.c_str(), Comment.size(), SQLITE_STATIC);
    
        rc = sqlite3_bind_text(stmt, 10, Path.c_str(), Path.size(), SQLITE_STATIC);
    
        rc = sqlite3_step(stmt);
    
        rc = sqlite3_exec(DB, Sample.c_str(), NULL, 0, &ErrorMessage);
    
            if (rc != SQLITE_OK)
            {
                std::cerr << "Error! Cannot insert data into table." << std::endl;
                sqlite3_free(ErrorMessage);
            }
            else
            {
                std::cout << "Data inserted successfully." << std::endl;
            }
    
            sqlite3_close(DB);
        }
        catch (const std::exception &exception)
        {
            std::cerr << exception.what();
        }
    }

但这失败了,抛出错误语句“错误!无法将数据插入表中。” . 我在这里做错什么了吗。

我在另一个类中使用这个函数,

void Browser::OnClickDirCtrl(wxCommandEvent& event)
{
    TagLib::FileRef File (DirCtrl->GetFilePath());
    TagLib::String Artist = File.tag()->artist();
    TagLib::String Album = File.tag()->album();
    TagLib::String Genre = File.tag()->genre();
    TagLib::String Title = File.tag()->title();
    TagLib::String Comment = File.tag()->comment();
    int Bitrate = File.audioProperties()->bitrate();
    int Channels = File.audioProperties()->channels();
    int Length = File.audioProperties()->lengthInMilliseconds();
    int LengthSec = File.audioProperties()->lengthInSeconds();
    int SampleRate = File.audioProperties()->sampleRate();

    wxVector<wxVariant> Data;
    Data.clear();
    Data.push_back(false);
    Data.push_back(TagLibTowx(Title));
    Data.push_back(TagLibTowx(Artist));
    Data.push_back(wxString::Format("%d",Channels));
    Data.push_back(wxString::Format("%d",LengthSec));
    Data.push_back(wxString::Format("%d",SampleRate));
    Data.push_back(wxString::Format("%d",Bitrate));
    Data.push_back(TagLibTowx(Comment));

    SampleListView->AppendItem(Data);

    db.InsertSample(0, Title.to8Bit(), Artist.to8Bit(), Channels, Length, SampleRate, Bitrate, Comment.to8Bit(), DirCtrl->GetFilePath().ToStdString());
}

这只是应该将文件添加到数据库的功能的一部分。如您所见,我将文件的路径存储在数据库中,这是项目所需的重要数据。

/ - - - - - - - - - /

编辑:添加一个简短的样本,

main.cpp

#include "testdb.hpp"

int main()
{
    Database db;

    db.InsertData("Hello, World!");
    return 0;
}

testdb.hpp

#include <sqlite3.h>
#include <string>

class Database
{
    public:
        Database();
        ~Database();

    public:
        sqlite3* DB;
        int rc;
        char* ErrorMessage;
        std::string Test;
        std::string sql;

        sqlite3_stmt* stmt;

    public:
        void InsertData(std::string Path);
};

testdb.cpp

#include <exception>
#include <iostream>
#include <string>

#include "testdb.hpp"

Database::Database()
{
    /* Create SQL statement */
    Test = "CREATE TABLE TEST("
        "TEST           TEXT    NOT NULL);";

    try
    {
        rc = sqlite3_open("Test.db", &DB);
        rc = sqlite3_exec(DB, Test.c_str(), NULL, 0, &ErrorMessage);

        if (rc != SQLITE_OK)
        {
            std::cerr << "Error! Cannot create table." << std::endl;
            sqlite3_free(ErrorMessage);
        }
        else
        {
            std::cout << "Table created successfuly." << std::endl;
        }

        sqlite3_close(DB);
    }
    catch (const std::exception &exception)
    {
        std::cerr << exception.what();
    }
}

void Database::InsertData(std::string Test)
{
    try
    {
        rc = sqlite3_open("Test.db", &DB);

    sql = "INSERT INTO TEST (PATH) VALUES (?);";

    rc = sqlite3_prepare_v2(DB, sql.c_str(), 10, &stmt, 0);   // create the prepared statement
    // error handling goes here

    rc = sqlite3_bind_text(stmt, 10, Test.c_str(), Test.size(), SQLITE_STATIC);
    // error handling goes here

    rc = sqlite3_step(stmt);
    // error handling goes here

    rc = sqlite3_finalize(stmt);

        if (rc != SQLITE_OK)
        {
            std::cerr << "Error! Cannot insert data into table." << std::endl;
            sqlite3_free(ErrorMessage);
        }
        else if (rc == SQLITE_BUSY)
        {
            std::cout << "BUSY" << std::endl;
        }
        else if (rc == SQLITE_DONE)
        {
            std::cout << "DONE" << std::endl;
        }
        else if (rc == SQLITE_ERROR)
        {
            std::cout << "ERROR" << std::endl;
        }
        else if (rc == SQLITE_MISUSE)
        {
            std::cout << "MISUSE" << std::endl;
        }
        else
        {
            std::cout << "Data inserted successfully." << ErrorMessage << std::endl;
        }

        sqlite3_close(DB);
    }
    catch (const std::exception &exception)
    {
        std::cerr << exception.what();
    }
}

Database::~Database(){}

编译使用g++ main.cpp testdb.cpp -l sqlite3 -o db.

这里发生了同样的事情,它说数据已插入,但数据库在sqlitebrowser.

标签: c++sqlite

解决方案


您有一个sqlite3_step跟随sqlite3_exec,这可能不是您想要的。这当然不好。您必须致电sqlite3_resetsqlite3_finalize完成准备好的陈述。它还将提供一个特定的错误代码,如果您从sqlite3_step.

参见“sqlite3_step”的解释


推荐阅读