c++ - 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
.
解决方案
您有一个sqlite3_step
跟随sqlite3_exec
,这可能不是您想要的。这当然不好。您必须致电sqlite3_reset
或sqlite3_finalize
完成准备好的陈述。它还将提供一个特定的错误代码,如果您从sqlite3_step
.
推荐阅读
- javascript - 有没有办法通过一个 API 请求 Instagram Graph API 来获取所有包含信息的媒体?
- go - `gorm` 获取更新的 id
- el - ui:repeat:无论验证错误如何,内部组件都保持“有效”状态
- sonarqube - 将值设置为 SonarQube 中的 JavaScript 全局变量设置
- java - 获取 HTTP 状态 400 - 放心发布请求中的错误请求
- c++ - 如何在 C++ 中使用 fflush(stdin)
- keycloak - Keycloak 管理控制台在远程连接时需要 HTTPS(我应该禁用 SSL)
- java - 一个类的Junit测试需要其他类的对象
- laravel - 联系我们页面接收信息但没有收到消息
- php - 微小的 MCE 编辑器无法传递 textarea 内容