C++:使用sqlite创建动态数据库以传输语音流

标签 c++ database sqlite soap

我有一个字符数组列表,我想将所有项目存储在 SQLite 数据库中,我的问题是如何将字符串数组值存储在 SQLite 数据库中,其中我的字符串数组是动态可变的,因为字符串数组值来自服务器。

我在这里完成了 sqlite3 通过传递参数插入项目,我只想动态地使用这个数据库。任何人都可以给我任何想法。 我是 C++ 开发新手:

#include <iostream>
using namespace std;
#include "sqlite3.h"
#include<string.h>
#define STRING_MAX 32

typedef struct metadata_t {
    char userid[256];
    char firstname[256];
    char lastname[256];
    char username[256];
    char password[256];
    char email[256];
    char userphone[256];
    char time[256];
} metadata_t;

void insertdata1(metadata_t * data);

int main(int argc, const char *argv[])
{

    struct metadata_t *data;
    cin >> data->userid;
    cin >> data->firstname;
    cin >> data->lastname;
    cin >> data->username;
    cin >> data->password;
    cin >> data->email;
    cin >> data->userphone;
    cin >> data->time;

    insertdata1(data);

}

void insertdata1(metadata_t * data)
{
    sqlite3 *db;
    sqlite3_open("test1.db", &db);

    string createQuery =
        "CREATE TABLE IF NOT EXISTS items (userid INTEGER PRIMARY KEY, firstname TEXT,lastname TEXT,username TEXT,password TEXT,email text,userphone INTEGER, "
        "time TEXT NOT NULL DEFAULT (NOW()));";
    sqlite3_stmt *createStmt;
    cout << "Creating Table Statement" << endl;
    sqlite3_prepare(db, createQuery.c_str(), createQuery.size(),
            &createStmt, NULL);
    cout << "Stepping Table Statement" << endl;
    if (sqlite3_step(createStmt) != SQLITE_DONE)
        cout << "Didn't Create Table!" << endl;

    char *a = "(";
    char *d = ")";
    char *b = "'";
    char *c = ",";
    char str1[1000];
    char *str2 = "";
    char *g = ";";
    strcpy(str1,
           "INSERT INTO items (userid,firstname,lastname,username,password,email,userphone,time)VALUES");

    strcat(str1, a);

    strcat(str1, b);
    strcat(str1, data->userid);
    strcat(str1, b);
    strcat(str1, c);
    strcat(str1, b);
    strcat(str1, data->firstname);
    strcat(str1, b);
    strcat(str1, c);
    strcat(str1, b);
    strcat(str1, data->lastname);
    strcat(str1, b);
    strcat(str1, c);
    strcat(str1, b);
    strcat(str1, data->username);
    strcat(str1, b);
    strcat(str1, c);
    strcat(str1, b);
    strcat(str1, data->password);
    strcat(str1, b);
    strcat(str1, c);
    strcat(str1, b);
    strcat(str1, data->email);
    strcat(str1, b);
    strcat(str1, c);
    strcat(str1, b);
    strcat(str1, data->userphone);
    strcat(str1, b);
    strcat(str1, c);
    strcat(str1, b);
    strcat(str1, data->time);
    strcat(str1, b);
    strcat(str1, d);
    strcat(str1, g);

    std::string insertQuery = str1; // WORKS!
    sqlite3_stmt *insertStmt;
    cout << "Creating Insert Statement" << endl;
    sqlite3_prepare(db, insertQuery.c_str(), insertQuery.size(),
            &insertStmt, NULL);
    cout << "Stepping Insert Statement" << endl;
    if (sqlite3_step(insertStmt) != SQLITE_DONE)
        cout << "Didn't Insert Item!" << endl;

}

最佳答案

我建议使用 bind variables - 它们使您的代码更清晰,更能防止输入错误甚至 SQL 注入(inject)。

还有一些不会伤害的好习惯:

  • 在每次调用 sqlite3_* 函数后检查返回值,并将 sqlite3_errmsg() 的输出写入 stderr (=cerr) 或在出现错误时写入日志文件;

  • 通过在不再使用的每个准备好的语句上调用 sqlite3_finalize() 完成清理。

不遵循这些做法将使您的业力在以后其他人使用或调试您的代码时受到影响。

因此,这里是建议的 insertdata1()(我希望它现在更清晰和可读了):

// some basic error handling
void exit_with_sqlite_error(sqlite3 *db, const char* file, int line)
{
cerr << "Error: " << sqlite3_errmsg(db) << " at " << file << ":" << line << endl;
exit(1);
}

// helps to get exact location of an error 
#define EXIT_WITH_SQLITE_ERR(db) \
exit_with_sqlite_error(db, __FILE__, __LINE__)

void insertdata1(metadata_t *data)
{
sqlite3 *db;
sqlite3_open("test1.db", &db);

string createQuery = 
    "CREATE TABLE IF NOT EXISTS items ("
    "userid INTEGER PRIMARY KEY,'
    "firstname TEXT,"
    "lastname TEXT,"
    "username TEXT,"
    "password TEXT,'
    "email TEXT,"
    "userphone INTEGER,"
    "time TEXT NOT NULL DEFAULT (NOW()));";

cout << "Creating Table Statement" << endl;
int rc = sqlite3_exec(db, createQuery.c_str(), NULL, NULL, NULL);
if (rc != SQLITE_OK) 
    EXIT_WITH_SQLITE_ERR(db);

sqlite3_stmt *insertStmt = NULL;
rc = sqlite3_prepare_v2(db, 
    "INSERT INTO items "
    "(userid,firstname,lastname,username,password,email,userphone,time)"
    "VALUES"
    "(:userid,:firstname,:lastname,:username,:password,:email,:userphone,:time);",
    -1, &insertStmt, NULL);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);

rc = sqlite3_bind_int(insertStmt, 1, atoi(data->userid));
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
rc = sqlite3_bind_text(insertStmt, 2, data->firstname, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
rc = sqlite3_bind_text(insertStmt, 3, data->lastname, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
rc = sqlite3_bind_text(insertStmt, 4, data->username, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
rc = sqlite3_bind_text(insertStmt, 5, data->password, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
rc = sqlite3_bind_text(insertStmt, 6, data->email, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
rc = sqlite3_bind_int(insertStmt, 7, atoi(data->userphone));
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
rc = sqlite3_bind_text(insertStmt, 8, data->time, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);

rc = sqlite3_step(insertStmt);
if (rc != SQLITE_DONE && rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);

sqlite3_finalize(insertStmt);

// call to sqlite3_close() helps to find resource leaks, because it fails
// if you have obvious leaks, such as prepared statements not finalized
rc = sqlite3_close(db);
if (rc != SQLITE_OK) EXIT_WITH_SQLITE_ERR(db);
}

关于C++:使用sqlite创建动态数据库以传输语音流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11288092/

相关文章:

php - 无法从 MySQL 数据库中的不同表中选择 id

tsql - 自上个纪元以来的T-Sql日期格式(秒)/sqlite输入的格式

c++ - 使用 lexical_cast<float>(string) 时会丢失精度

c++ - 接口(interface)和-Wctor-dtor-privacy

c++ - 这是返回迭代器元素和后增量的有效方法吗?

ios - 如何在初始化sql字符串时向字符串添加转义字符?

sqlite - RKFace.modelId 对应的 Apple Photos 中的 facetile 是如何实现的?

c++ - 使用指针在 C++ 中缩小类型转换

mysql - 更新一列后将该行移动到 sql 中的另一个表

用于连接的 MySQL 全局触发器