C Как правильно хранить sqlite3 строки данных? - PullRequest
1 голос
/ 13 января 2020

Я работал в C с sqlite3 над программой, которая должна хранить более 1 строки данных в переменной для дальнейшей обработки. Программа использует базу данных продуктов, каждый продукт имеет название, цену за единицу, категорию и количество указанного продукта. Обычно для таких операторов, как Select * from Products;, мы используем функцию sqlite3_exec и необходимые callback function, например:

#include <sqlite3.h>
#include <stdio.h>



int callback(void *, int, char **, char **);


int main(void) {

sqlite3 *db;
char *err_msg = 0;

int rc = sqlite3_open("test.db", &db);

if (rc != SQLITE_OK) {

    fprintf(stderr, "Cannot open database: %s\n", 
            sqlite3_errmsg(db));
    sqlite3_close(db);

    return 1;
}

char *sql = "SELECT * FROM Cars";

rc = sqlite3_exec(db, sql, callback, 0, &err_msg);

if (rc != SQLITE_OK ) {

    fprintf(stderr, "Failed to select data\n");
    fprintf(stderr, "SQL error: %s\n", err_msg);

    sqlite3_free(err_msg);
    sqlite3_close(db);

    return 1;
} 

sqlite3_close(db);

return 0;
}

int callback(void *NotUsed, int argc, char **argv, 
                char **azColName) {

NotUsed = 0;

for (int i = 0; i < argc; i++) {

    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}

printf("\n");

return 0;
}

Теперь приведенный выше код отображает только все строки в таблице. Я хочу сохранить данные для дальнейшей обработки. Это код, который я написал, чтобы попробовать это. Проблема в том, что он печатает дубликаты строк. Еще одна вещь, о которой я подумал, - это изменить функцию обратного вызова, чтобы получить дополнительный параметр для хранения каждой строки, но я не понимаю, как указать новый параметр.

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

void display_all_products(char *destination)
{
sqlite3 *db;
sqlite3_stmt *stmt;
char *err_msg = 0;
int step;
int rc = sqlite3_open("test.db", &db);
if(rc != SQLITE_OK)
{
    fprintf(stderr, "Problem opening Database: %s\n", sqlite3_errmsg(db));
    sqlite3_free(err_msg);
        sqlite3_close(db);
}
char *sql = "Select * from Products;";
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);

    if (rc != SQLITE_OK ) 
{
        fprintf(stderr, "Problem retrieving data: %s\n", sqlite3_errmsg(db));
        sqlite3_free(err_msg);
        sqlite3_close(db);
    }

while(1)
{
    step = sqlite3_step(stmt);
    if (step == SQLITE_ROW)
    {
        strcat(destination, "Product name : ");
        strcat(destination, sqlite3_column_text(stmt, 1));
        strcat(destination, "\n");
        strcat(destination, "Price per unit : ");
        strcat(destination, sqlite3_column_text(stmt, 2));
        strcat(destination, "\n");
        strcat(destination, "Category of requested article : ");
        strcat(destination, sqlite3_column_text(stmt, 3));
        strcat(destination, "\n");
        strcat(destination, "Quantity avalible on stock : ");
        strcat(destination, sqlite3_column_text(stmt, 4));
        strcat(destination, "\n");
        strcat(destination, "-----------------------------------------------\n");
        printf("%s", destination);
    }
    else
    {
        break;
    }
}
sqlite3_finalize(stmt);
sqlite3_close(db);

}

int main()
{
sqlite3 *db;
sqlite3_stmt *stmt;
char msg[2000] = " ";
display_all_products(msg);
// do something with msg here

return 0;


}

Хотелось бы узнать, что еще я могу сделать .

1 Ответ

1 голос
/ 13 января 2020

Мне удалось заставить его работать. Все это содержится в документации после тщательного прочтения несколько раз.

int callback(void *notUsed, int argc, char **argv, 
            char **azColName) {

NotUsed = 0;

for (int i = 0; i < argc; i++) {

//printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
strcat(notUsed, azColName[i]);
strcat(notUsed, " = ");
strcat(notUsed, argv[i] ? argv[i] : "NULL");
}

printf("\n");

return 0;
} 

void display_all_products(char *test)
{
sqlite3 *db;
sqlite3_stmt *stmt;
char *err_msg = 0;
int rc = sqlite3_open("test.db", &db);
if(rc != SQLITE_OK)
{
    fprintf(stderr, "Problem opening Database: %s\n", sqlite3_errmsg(db));
    sqlite3_free(err_msg);
        sqlite3_close(db);
}
char *sql = "Select * from Products;";
rc = sqlite3_exec(db, sql, callback, test, &err_msg);

    if (rc != SQLITE_OK ) 
{
        fprintf(stderr, "Problem retrieving data: %s\n", sqlite3_errmsg(db));
        sqlite3_free(err_msg);
        sqlite3_close(db);
    }
sqlite3_close(db);

}
int main()
{
sqlite3 *db;
sqlite3_stmt *stmt;
char msg[4000] = " ";
display_all_products(msg);
// do something with msg here

return 0;


}

Разница заключается в теле функции callback. Также, когда мы вызываем функцию sqlite3_exec(), мы передаем указатель test вместо 0, как я делал ранее.

 rc = sqlite3_exec(db, sql, callback, test, &err_msg);

4-й аргумент sqlite3_exe c () передается на 1-й аргумент каждого вызова обратного вызова.

Это означает, что 4-й аргумент для sqlite3_exec() можно сделать так, чтобы он содержал значение первого аргумента функции callback, о которой я был озадачен после прочтения документации в первый раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...