这周做数据库作业,其中一个小部分是从文件中读入格式化数据并存入sqlite3中。一开始只是为了完成实验内容而写了一个专门的函数来完成。
但写完之后发现有时候我们确实是需要从文件中读入格式化数据的。所以想写一个通用的函数,通过给定的参数来从文件中读入数据。
先是各个函数的解读,然后是所有的代码。
int insertData(sqlite3 *db, char *fileName, int maxSize, char *tableName, int length, int *format);
这个函数就是封装的读取插入数据的最终形态。参数简要描述如注释里面说的那样。前4个参数应该都好理解,可能需要解释的就是最后两个参数了。
int length 指的是你要插入数据的表(tableName)里一共有多少字段。
int *format 这其实是一个整型数组。你在定义的时候可以使用format[n]的形式,实参就是format。这个数组代表的是数据库表中每一个字段是数字还是字符串。了解数据库的同学应该都知道,简单的DBMS的sql语句在插入数值时其实只有三种:数字,字符串,NULL。而数字和NULL的插入方式是一样的。
如下是插入数字的sql语句:
insert into tableName (number)values(12);
这句话想tableName中插入了一组记录,插入的类型是数字。
如下是插入字符串的sql语句:
insert into talbeName (string) values ('hello world');
应该看出区别的了,两者的唯一区别就是字符串多了一对单(双)引号。因为在c语言中,字符串只能用双引号("")来括起来,所以我们在c语言里的sql语句只能使用单引号('')了。
那么上面的format就好理解了。按照顺序,如果第i个字段(从0计数)为字符串形式,则format[i] = 0,如果第i个字段为数字形势,则format[i] = 1;
当然,这个函数时假设插入的数据中是按顺序包含每一个字段。
如果需要只插入某些,可以自行修改。
int myGetSQL(FILE *file, int maxSize, char *tableName, char **SQL, int fields, int *format) ;
这个函数的作用就是从文件中获取格式化的内容并返回sql语句。很容易理解。
这个函数的唯一调用者就是insertData()函数了。
//************************************
// Method: join 将字符串b接在字符串a后面
// FullName: join
// Access: public
// Returns: void
// Qualifier:
// Parameter: char * * a 原始字符串
// Parameter: char * * b 需要添加的字符串
//************************************
void join(char **a, char **b);
这个函数的作用就是把一个字符串添加到另一个字符串的后面,相当于c语言中的字符串的"+"操作符了。
接下来就是全部的代码了。
#include "stdio.h"
#include "io.h"
#include "stdlib.h"
#include "string.h"
#include "sqlite3.h"
#include "time.h"
#define STR 0
#define NUM 1
void join(char **, char**);
int myGetSQL(FILE *, int , char *, char **, int, int *);
int insertData(sqlite3 *, char *, int, char *, int, int *);
int main(int argc,char *argv[])
{
clock_t t1 = clock();
sqlite3 *db;
int rc;
char *ErrMsg = 0;
const char *dbName = "DBforCourse.db3";
if(!access(dbName,0)){
if(0!=remove("DBforCourse.db3")){
printf("删除文件失败!\n");
}
}
rc = sqlite3_open("DBforCourse.db3", &db);
if (rc){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}
char *College = "create table College(cName VARCHAR(20),state VARCHAR(20),enrollment int)";
char *Student = "create table Student(sID int,sName VARCHAR(20),GPA real,sizeHS int)";
char *Apply = "create table Apply(sID int,cName VARCHAR(20),major VARCHAR(20),decision VARCHAR(10))";
sqlite3_exec(db,College,0,0,0);
sqlite3_exec(db,Student,0,0,0);
sqlite3_exec(db,Apply,0,0,0);
int college[3] = { STR, STR, NUM };
int apply[4] = {NUM,STR,STR,STR};
int student[4] = {NUM,STR,NUM,NUM};
if(!insertData(db,"dbcollege.txt",200,"College",3,college))
printf("插入College表失败!\n");
if(!insertData(db,"dbapply.txt",200,"Apply",4,apply))
printf("插入Apply表失败!\n");
if(!insertData(db,"dbstudent.txt",200,"Student",4,student))
printf("插入Student表失败!\n");
sqlite3_close(db);
clock_t t2 = clock();
printf("耗时%ld毫秒\n",t2-t1);
}
int myGetSQL(FILE *file, int maxSize, char *tableName, char **SQL, int fields, int *format) {
int i, s = 0, k = 0;
char *query[fields];
char input[maxSize];
char *enter;
char *a0 = "insert into ";
char *a1 = " values(";
char *a2 = ",";
char *a3 = "'";
char *a4 = "',";
char *a5 = ")";
*SQL = a0;
join(SQL, &tableName);
join(SQL, &a1);
if (fgets(input, maxSize, file)){
i = 0;
if (enter = strchr(input, '\n'))
*enter = '\0';
query[i] = strtok(input, ",");
while (query[++i] = strtok(0, ",")){}
for (s = 0; s < fields - 1; s++){
if (*(format + s)){
join(SQL, &query[s]);
join(SQL, &a2);
}
else{
join(SQL, &a3);
join(SQL, &query[s]);
join(SQL, &a4);
}
}
if (*(format + s)){
join(SQL, &query[s]);
}
else{
join(SQL, &a3);
join(SQL, &query[s]);
join(SQL, &a3);
}
join(SQL, &a5);
k = 1;
}
else
k = 0;
return k;
}
void join(char **a, char **b)
{
size_t size = strlen(*a) + strlen(*b) + 1;
char *result = (char *)malloc(size);
strcpy(result, *a);
strcat(result, *b);
free(*a);
*a = result;
}
int insertData(sqlite3 *db, char *fileName, int maxSize, char *tableName, int length, int *format){
FILE *file;
if (!(file = fopen(fileName, "r"))){
printf("打开文件%s失败!\n", fileName);
return 0;
}
char *SQL = 0;
sqlite3_exec(db, "begin;", 0, 0, 0);
while (myGetSQL(file, maxSize, tableName, &SQL, length, format)){
if (SQLITE_OK != sqlite3_exec(db, SQL, 0, 0, 0))
printf("%s 语句执行失败!\n", SQL);
}
fclose(file);
sqlite3_exec(db, "commit;", 0, 0, 0);
return 1;
}