📅  最后修改于: 2023-12-03 15:30:14.320000             🧑  作者: Mango
本文将介绍如何在C语言中使用CSV文件实现关系数据库的基本操作,包括创建数据库,创建表,插入数据以及查询数据等操作。在本文中,我们将使用libcsv库来处理CSV文件。另外,我们将使用SQLite来存储数据库数据。
首先,我们需要创建一个空的数据库文件,以便在其中存储表和数据。我们可以使用SQLite来创建一个空的数据库文件,代码如下:
#include <sqlite3.h>
int main() {
sqlite3 *db;
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;
}
sqlite3_close(db);
return 0;
}
上述代码创建了一个名为test.db的空数据库文件。如果在打开数据库文件时出现错误,我们将显示一个错误信息并退出程序。
在创建表之前,我们需要定义表的结构,即表的列名和列类型。接下来我们可以使用libcsv来读取包含表结构的CSV文件,并使用SQLite的API创建表。具体代码如下:
#include <csv.h>
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
void create_table(sqlite3 *db, const char *name, csv_parser *parser) {
// Get number of columns
int n_cols = csv_parser_get_num_cols(parser);
// Build list of column names and types
char **columns = malloc(n_cols * sizeof(char *));
char **types = malloc(n_cols * sizeof(char *));
for (int i = 0; i < n_cols; i++) {
csv_parser_get_col_info(parser, i, &columns[i], &types[i]);
}
// Build SQL statement
char *sql = malloc(1024);
strcpy(sql, "CREATE TABLE ");
strcat(sql, name);
strcat(sql, " (");
for (int i = 0; i < n_cols; i++) {
strcat(sql, "'");
strcat(sql, columns[i]);
strcat(sql, "' ");
strcat(sql, types[i]);
if (i < n_cols - 1) {
strcat(sql, ",");
}
}
strcat(sql, ")");
// Execute SQL statement
char *errmsg;
int rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "Error creating table: %s\n", errmsg);
sqlite3_free(errmsg);
}
// Cleanup
free(columns);
free(types);
free(sql);
}
int main() {
// Open CSV file
FILE *fp = fopen("customers.csv", "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open CSV file\n");
return 1;
}
// Create CSV parser
csv_parser *parser = csv_parser_new();
csv_init(parser, CSV_APPEND_NULL);
// Parse CSV file
char buf[1024];
size_t bytes_read;
while ((bytes_read = fread(buf, 1, 1024, fp)) > 0) {
csv_parse(parser, buf, bytes_read, NULL, NULL, NULL, NULL);
}
csv_fini(parser, NULL, NULL, NULL);
csv_parser_free(parser);
// Close CSV file
fclose(fp);
// Create database
sqlite3 *db;
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;
}
// Create table
create_table(db, "customers", parser);
// Close database
sqlite3_close(db);
return 0;
}
上述代码已经实现了创建表的功能。在上述代码中,我们定义了一个create_table函数,该函数将读取包含表结构的CSV文件,并在sqlite3数据库中创建一个表。具体来说,我们将使用csv_parser_get_num_cols函数获取列数,使用csv_parser_get_col_info获取列的信息,使用sqlite3_exec函数执行CREATE TABLE语句。
插入数据是关系数据库操作中最常见的操作之一。对于CSV文件,我们可以使用libcsv库读取数据行,并使用SQLite的API将数据插入到数据库中。具体代码如下:
#include <csv.h>
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
void insert_data(sqlite3 *db, const char *table_name, csv_parser *parser) {
// Get number of columns
int n_cols = csv_parser_get_num_cols(parser);
// Build list of column names
char **columns = malloc(n_cols * sizeof(char *));
for (int i = 0; i < n_cols; i++) {
csv_parser_get_col_info(parser, i, &columns[i], NULL);
}
// Build SQL statement
char *sql = malloc(1024);
strcpy(sql, "INSERT INTO ");
strcat(sql, table_name);
strcat(sql, " (");
for (int i = 0; i < n_cols; i++) {
strcat(sql, "'");
strcat(sql, columns[i]);
strcat(sql, "'");
if (i < n_cols - 1) {
strcat(sql, ",");
}
}
strcat(sql, ") VALUES (");
for (int i = 0; i < n_cols; i++) {
strcat(sql, "?");
if (i < n_cols - 1) {
strcat(sql, ",");
}
}
strcat(sql, ")");
// Prepare statement
sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, "Error preparing statement: %s\n", sqlite3_errmsg(db));
goto cleanup;
}
// Insert data
char **row;
int n_row;
while ((row = csv_parser_get_row(parser, &n_row)) != NULL) {
if (n_row == n_cols) {
for (int i = 0; i < n_cols; i++) {
sqlite3_bind_text(stmt, i + 1, row[i], strlen(row[i]), SQLITE_STATIC);
}
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
fprintf(stderr, "Error inserting row: %s\n", sqlite3_errmsg(db));
goto cleanup;
}
sqlite3_reset(stmt);
}
csv_parser_free_row(row);
}
cleanup:
sqlite3_finalize(stmt);
free(columns);
free(sql);
}
int main() {
// Open CSV file
FILE *fp = fopen("customers.csv", "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open CSV file\n");
return 1;
}
// Create CSV parser
csv_parser *parser = csv_parser_new();
csv_init(parser, CSV_APPEND_NULL);
// Parse CSV file
char buf[1024];
size_t bytes_read;
while ((bytes_read = fread(buf, 1, 1024, fp)) > 0) {
csv_parse(parser, buf, bytes_read, NULL, NULL, NULL, NULL);
}
csv_fini(parser, NULL, NULL, NULL);
csv_parser_free(parser);
// Close CSV file
fclose(fp);
// Open database
sqlite3 *db;
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;
}
// Insert data
insert_data(db, "customers", parser);
// Close database
sqlite3_close(db);
return 0;
}
上述代码已经实现了将数据插入到数据库中的功能。在上述代码中,我们定义了一个insert_data函数,该函数将读取CSV文件中的数据行,并将数据插入到sqlite3数据库中。具体来说,我们将使用sqlite3_prepare_v2函数准备INSERT语句,使用sqlite3_bind_text函数将数据绑定到语句中,使用sqlite3_step函数执行INSERT语句,并使用sqlite3_reset函数重置语句以准备下一条INSERT语句的执行。
查询数据是关系数据库操作中最常见的操作之一。我们可以使用SQLite的API来查询数据,并使用libcsv库将查询结果输出到CSV文件中。具体代码如下:
#include <csv.h>
#include <stdio.h>
#include <sqlite3.h>
void query_data(sqlite3 *db, const char *table_name, const char *output_file) {
// Build SQL statement
char *sql = malloc(1024);
sprintf(sql, "SELECT * FROM %s", table_name);
// Prepare statement
sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, "Error preparing statement: %s\n", sqlite3_errmsg(db));
goto cleanup;
}
// Open CSV file
FILE *fp = fopen(output_file, "w");
if (fp == NULL) {
fprintf(stderr, "Cannot open output file\n");
goto cleanup;
}
// Write header row to CSV file
int n_cols = sqlite3_column_count(stmt);
for (int i = 0; i < n_cols; i++) {
const char *col_name = sqlite3_column_name(stmt, i);
if (i > 0) {
fprintf(fp, ",");
}
fprintf(fp, "%s", col_name);
}
fprintf(fp, "\n");
// Write data rows to CSV file
while (sqlite3_step(stmt) == SQLITE_ROW) {
for (int i = 0; i < n_cols; i++) {
const char *col_value = (const char *)sqlite3_column_text(stmt, i);
if (i > 0) {
fprintf(fp, ",");
}
fprintf(fp, "\"%s\"", col_value);
}
fprintf(fp, "\n");
}
// Close CSV file
fclose(fp);
cleanup:
sqlite3_finalize(stmt);
free(sql);
}
int main() {
// Open database
sqlite3 *db;
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;
}
// Query data
query_data(db, "customers", "customers_output.csv");
// Close database
sqlite3_close(db);
return 0;
}
上述代码已经实现了查询数据的功能。在上述代码中,我们定义了一个query_data函数,该函数将执行SELECT语句,并将查询结果输出到指定的CSV文件中。具体来说,我们将使用sqlite3_prepare_v2函数准备SELECT语句,使用sqlite3_step函数执行SELECT语句,并将查询结果输出到CSV文件中。
本文介绍了如何在C语言中使用CSV文件实现关系数据库的基本操作,包括创建数据库,创建表,插入数据以及查询数据等操作。在本文中,我们使用了libcsv库来处理CSV文件,使用了SQLite来存储数据库数据。在实现过程中,我们使用了libcsv库的API来读取数据行,并使用了SQLite的API来执行SQL语句。同时,我们还介绍了如何将查询结果输出到CSV文件中。