学习笔记 day17 系统编程:数据库

4、库函数(带缓存)文件访问

/*
C库函数的文件操作是独立于具体的操作系统平台的,不管是在DOS、Windows、Linux还是在VxWorks中都是这些函数。

*/

FILE *fopen(const char *filename, const char *mode)
FILE *fcolse(FILE* stream)
/*
filename:打开的文件名(包含路径,缺省为当前路径)
mode:打开模式
    “r”:只读,文件必须已存在
    “w”:只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate)为0字节再重新写,也就是替换掉原来的文件内容
    “a”:只能在文件末尾追加数据,如果文件不存在则创建
    
    “r+”:允许读和写,文件必须已存在
    “w+”:允讲读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写
    “a+”:允许读和追加数据,如果文件不存在则创建
	
	b用于区分二进制文件和文本文件,这一点在DOS、Windows系统中是有区分的,但Linux不区分二进制文件和文本文件


*/
size_t  fread(void *ptr, size_t size, size_t n, FILE* stream)
/*
功能:从stream指向的文件中读取n个字段,每字段为size字节,并将读取的数据放入ptr所指的字符数组中,返回实际已读取的字段数。

ptr:缓冲区
size:所需读入缓冲区每个字段的大小
n:所需读入缓冲区size大小字段的个数
stream:指向的文件

返回值:实际读取的字段数(不一定读取n个字段)
*/

size_t fwrite (const void *ptr, size_t size, size_t n,FILE *stream)
/*
功能:从缓冲区ptr所指的数组中把n个字段写到stream指向的文件中,每个字段长为size个字节,返回实际写入的字段数.
*/

int fgetc(FILE *stream)//fgets、fputs的用法  stdin stdout
/*
功能:从指定的文件中读一个字符
*/
    
char *fgets(char *s, int size, FILE *stream);
/*
功能:从stream种取size个字节数据存入s中
*/

int fputc(int c, FILE *stream)
/*
功能:向指定的文件中写入一个字符
*/
int fseek(FILE *stream, long off, int whence)

练习

//1 用库函数实现file_cp.c
#include<stdio.h>
#include<stdlib.h>
int main()
{
    FILE *fp;
    FILE *fp_to;
    char ch;
    if((fp=fopen("c1.txt","r"))==NULL)
    {
   	 	printf("\nCannot open file strike any key exit!");
   	    //getchar();
 	    exit(1);
	}
    fp_to=fopen("c2.txt","w+");
	ch=fgetc(fp);
	while(ch!=EOF)
	{
		//putchar(ch);
        fputc(ch,fp_to);
		ch=fgetc(fp);
	}
	fclose(fp);
	fclose(fp_to);
}


二、数据库

1、简介

/*
数据库(DataBase,简记为DB)就是一个有结构的、集成的、可共享的统一管理的数据集合。它不仅包括数据本身,而且包括相关数据之间的联系。数据库技术主要研究如何存储、使用和管理数据;

所谓有结构的,指的是数据是按一定的模型组织起来的。
    数据模型可用数据结构来描述。
    数据模型决定数据的组织方式、操作方法。
    理解数据库的前提是理解数据模型。
    现在的数据库多数是以关系模型来组织数据的。
    可以简单地把关系模型的数据结构-关系理解成为一张二维表。
所谓集成的,是指数据库中集中存放着企业各种各样的数据。
    集中存放的好处是:一个数据只需一个备份,重复存储少,即消除了数据的冗余。
    没有数据冗余,也就能保证数据的一致。
所谓共享,指的是数据库中的数据可以被不同的用户使用。也就是说,每一个用户可以按自己的要求访问相同的数据库。
所谓统一管理的,指的是数据库由DBMS统一管理,任何数据访问都是通过DBMS来完成的。

数据库管理系统(DataBase Management System,DBMS)是用来管理数据库的一种商品化软件。
所有访问数据库的请求都由DBMS来完成的。 DBMS提供了操作数据库的许多命令(语言),即SQL语言。

数据库系统的三级模式结构是指数据库系统是由外模式、模式和内模式三级组成。

*/
/*
外模式(External Schema) :
     外模式也称子模式或用户模式,它是数据库用户(包括应用程序员和最终用户)看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。外模式一般是模式的子集。一个模式可以有多个外模式。一个应用程序只能使用一个外模式。外模式是保证数据库安全性的一个有力措施。
     
模式(Schema) :
    模式也称为逻辑模式或概念模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公用数据视图。一个数据库只有一个模式。模式是数据项值的框架。数据库系统模式通常还包含有访问控制、保密定义、完整性检查等方面的内容。 
    
内模式(internal Schema) :
    内模式也称为存储模式,它是数据库在物理存储器上具体实现的描述,是数据在数据库内部的表示方法,也是数据物理结构和存储方式的描述。一个数据库只有一个内模式


数据库系统在三级模式之间提供了两层映像:外模式/模式映像和模式/内模式映像。正是这两层映像保证了数据库系统的数据能够具有较高的逻辑独立性和物理独立性。

数据的逻辑独立性
    模式描述的是数据的全局逻辑结构,外模式描述的是数据的局部逻辑结构。对应于同一个模式可以有任意多个外模式。对于每一个外模式,数据库系统都有一个外模式/模式映像,它定义了该外模式与模式之间的对应关系。当模式改变时(例如,增加新的数据类型、新的数据项、新的关系等),由数据库管理员对各个外模式/模式的映像作相应改变,可以使外模式保持不变,从而应用程序不必修改,保证了数据的逻辑独立性

数据的物理独立性
    数据库中只有一个模式,也只有一个内模式,所以模式/内模式映像是惟一的,它定义了数据全局逻辑结构与存储结构之间的对应关系。当数据库的存储结构改变时(例如,采用了更先进的存储技术),由数据库管理员对模式/内模式映像作相应改变,可以使模式保持不变,从而保证了数据的物理独立性。




关系(Relation):一个关系就是一张二维表,每一个关系有一个关系名,可以存储为一个文件。其定义可以描述为 的子集叫做域 , ,…, 上的关系,表示为 ,R表示关系的名称,n表示关系的目或度(Degree)。
   元组:表中的行称为元组,一行就是一个元组,对应存储文件中的一个记录。
   属性:关系中的一列称为一个属性。一个属性必须有唯一的属性名,一个关系可以有若干个属性值。
   域(Domain):属性的取值范围,是一组具有相同数据类型的值的集合。
   
关系的候选键与主键
表中某一列(或若干列的最小组合)的值能唯一标识一个行,称该列或列组为候选键。如Students表的学号列,就是一个候选键。
对于一个表,可能有多个候选键 。
候选键取决于应用范围,如给定条件,没有重复的学生姓名,则姓名是学生基本情况表的一个候选键。
如果一个表有多个候选键,数据库设计者通常选择其中一个候选键作为区分行的唯一性标识符,称为主键(primary key,PK)。如果一个表只有一个候选键,那么这个候选键就作为主键。例如,在学生基本情况表中,把学号作为该表的主键。
因为主键是候选键之一,而根据候选键的定义,候选键列上的各个值都唯一,因此主键列上的各个值也都唯一

外键(Foreign Key,FK):若一个表R1中的一个列或列组对应另一个表R2的主键,那么该列或列组称为表R1的外键。
外键可以由一个或多个列组成,可以有重复值




*/

2、sqlite3使用及SQL命令

/*
.sqlite3		//启动
.head on		//显示属性名
.mode column	//修改显示模式
.schema			//查看表结构
.database		//
.tables			
.q/.quit/.exit	//退出

sqlite3 database_test.db

数据类型:
    空:这个值为空值 NULL
    整数:int integer 值被标识为整数
    实数:real 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号. 
    文本:text 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE). 
    定长字符串:char (n) 长度为n的字符串,若输入不够n,使用空格填充
    变长字符串:varchar(m) 若输入不够m,只存m个
    BLOB: 值是BLOB数据,如何输入就如何存储,不改变格式. 
    




对列的操作(数据定义)create drop alter
对行的操作(数据操纵)select insert update delete

create table mytable(id integer primary key,name text);
insert into mytable(id,name) values(1,'mlm');
select * from mytable;
update mytable set name='ccc' where id=1;
delete from mytable where id=1;
alter table mytable add column email text not null default '';
update mytable set email='waicc777@163.com' where id=1;

//删除一列
create table newtable as select id,name from mytable;
drop table mytable;
alter table newtable rename to mytable;

*/

3、API

#include <sqlite.h>


int sqlite3_open(const char* fileName, sqlite3** ppDB);
/*
函数功能:打开一个数据库;若该数据库文件不存在,则自动创建。打开或者创建数据库的命令会被缓存,直到这个数据库真正	被调用的时候才会被执行。
输入参数:fileName:待打开的数据库文件名称,包括路径,以’\0’结尾; 
	特别说明:SQLite 支持内存数据库,内存方式	存储使用文	件名“:memory:”
输出参数:ppDB:返回打开的数据库句柄;
返回值:执行成功返回SQLITE_OK,否则返回其他值;
*/
int sqlite3_close(sqlite3* pDB);
/*
函数功能:关闭一个打开的数据库;
输入参数:pDB:打开的数据库句柄
返回值:执行成功返回SQLITE_OK,否则返回其他值
*/
const char *sqlite3_errmsg(sqlite3* pDB);
/*
函数功能:获取最近调用的API 接口返回的错误说明,这些错误信息UTF-8的编码返回,并且在下一次调用任何SQLite API 函数时被自动清除;
输入参数:pDB:打开的数据库句柄
返回值:错误说明的字符串指针
*/
int sqlite3_errcode(sqlite3* pDB);
/*
函数功能:获取最近调用的API 接口返回的错误代码;
输入参数:pDB,打开的数据库句柄
返回值:错误代码
*/
int sqlite3_exec(sqlite3* pDB, const char *sql, sqlite_callback callback, void*para, char** errMsg);
/*
函数功能:编译和执行零个或多个SQL 语句,查询的结果返回给回调函数callback
输入参数:pDB,数据库句柄;
		sql,待执行的SQL 语句字符串,以’\0’结尾;
		callback,回调函数,用来处理查询结果如果不需要回调(比如做insert 或者delete 操作时),可以输入NULL;
		para,用户传入的参数,可以为NULL,该参数指针最终会被传给回调函数callback,供用户在回调函数中使用;
输出参数:errMsg,返回错误信息,注意是指针的指针。
返回值:执行成功返回SQLITE_OK,否则返回其他值
*/
typedef int (*sqlite_callback)(void* para,int columnCount,char** columnValue,char** columnName);
/*
函数功能:由用户处理查询的结果
输入参数:para,从sqlite3_exec()传入的参数指针;
		columnCount, 查询到的这一条记录有多少个字段(即这条记录有多少列);
		columnValue,查询出来的数据都保存在这里,它实际上是个1 维数组(不要以为是2 维数组),每一个元素都是一个char * 值,是一个字段内容						(用字符串来表示,以‘\0’结尾);
		columnName,与columnValue 是对应的,表示这个字段的字段名称。
输出参数:无
返回值:执行成功返回SQLITE_OK,否则返回其他值
*/
int sqlite3_get_table(sqlite3* pDB, const char *sql,char ***pResult, int * rowCount,int * columnCount, char** errMsg);
/*
函数功能:执行SQL 语句,通过一维数组返回结果;一般用于数据记录查询
输入参数:pDB,打开的数据库句柄;sql,待执行的SQL 字符串,以’\0’结尾;
输出参数:rowCount,查询出多少条记录(即查出多少行);
		columnCount,查询出来的记录有多少个字段(多少列); 
		errMsg,返回错误信息;
		pResult,查询结果,是由字符串组成的一维数组(不要以为是二维数组,更不要以为是三维数组)。
				它的内存布局是:第一行是字段名称,后面紧接着每个字段的值;
返回值:执行成功返回SQLITE_OK,否则返回其他值
*/
void sqlite3_free_table(char **result);
/*
函数功能:释放查询结果占用的内存;
输入参数:result,通过函数sqlite3_get_table()查询到的记录结果
输出参数:无
返回值:无
*/
int sqlite3_prepare(sqlite3* pDB, const char* sql , int maxSqlLen,sqlite3_stmt** ppStmt, const char**pTail);
/*
函数功能:将SQL 语句编译成SQLite 能够识别的二进制字节码(也即SQL声明,statement),结果保存在ppStat 中。
	注:输入的参数中只有第一个SQL语句会被编译。SQL 语句间通过分号‘;’分隔。
输入参数:pDB ,数据库句柄;
		sql ,待编译的SQL 语句字符串;
     	maxSqlLen,SQL 语句的最大长度,如果此值小于0,SQLite 会自动计算字符串长度;
输出参数:ppStmt,编译后SQL 语句存放位置;
		pTail,未编译的SQL 语句的起始位置,一般输入NULL 就可以了。
返回值:执行成功返回SQLITE_OK,否则返回其他值

*/

/*

*/

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

#define SUCCESS 0
#define FAILURE -1

int create_table(sqlite3 *pdb){
    char *errmsg=NULL;
    char *sql=NULL;
    sql="create table if not exists mytable (id int primary key,name text);";
    if(SQLITE_OK!=sqlite3_exec(pdb,sql,NULL,NULL,&errmsg)){
        printf("create table error! : %s\n",errmsg);
        return -1;
    }
    return 0;

}
int insert_record(sqlite3 *pdb){
    char *errmsg=NULL;
    char sql[100];

    int id;
    char name[20];

    printf("please input id and name:\n");
    scanf("%d %s",&id,name);
    sprintf(sql,"insert into mytable (id,name) values (%d,'%s');",id,name);
    if(SQLITE_OK!=sqlite3_exec(pdb,sql,NULL,NULL,&errmsg)){
        printf("insert record error! : %s\n",errmsg);
        return -1;
    }
    return 0;

}
int display(void *para,int col_num,char **col_val,char **col_name){
    int i;
    int *flag=NULL;
    flag=(int *)para;
    if(*flag==0){
        printf("col_nul=%d\n",col_num);
        for(i=0;i<col_num;i++){
            printf("%10s",col_name[i]);
        }
        putchar(10);
        *flag=1;
    }
   
    for(i=0;i<col_num;i++){
        printf("%10s",col_val[i]);
    }
    putchar(10);
    return 0;
}
int inquire_usecb(sqlite3 *pdb){
    char *errmsg=NULL;
    char *sql=NULL;
    int flag=0;
    sql="select * from mytable;";
    if(SQLITE_OK!=sqlite3_exec(pdb,sql,display,(void *)&flag,&errmsg)){
        printf("select error! : %s\n",errmsg);
        return -1;
    }
    return 0;
}
int main(int argc, char const *argv[])
{
    sqlite3 *pdb=NULL;
    int ret;
    ret=sqlite3_open("mydatabase.db",&pdb);
    if(ret!=SQLITE_OK){
        fprintf(stderr,"open database error! : %s\n",sqlite3_errmsg(pdb));
        exit(-1);
    }
    else{
        printf("you have opened a database successfully!\n");
    }
    if(create_table(pdb)==-1){
        sqlite3_close(pdb);
        exit(-1);
    }
    if(insert_record(pdb)==-1){
        sqlite3_close(pdb);
        exit(-1);
    }
    if(inquire_usecb(pdb)==-1){
        sqlite3_close(pdb);
        exit(-1);
    }
    ret=sqlite3_close(pdb);
    if(ret!=SQLITE_OK){
        fprintf(stderr,"close database failure! : %s\n",sqlite3_errmsg(pdb));
        exit(-1);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛奶奥利奥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值