if(!
action_at(status.top(),str[i],num)){
分析出错,返回错误位置为第i个单词;
}
if(num>0){//移进
状态栈中入栈num;
符号栈中入栈str[i++];
}
elseif(num<0){//规约
按照第num个产生式α→β进行规约,如果规约过程中出现栈空无法继续进行则返回错误位置为i-1
}
if(!
goto_at(status.top(),p->left,num)){
返回错误位置为i-1个单词
}
将num压入状态栈,将第num个产生式α→β的左部α压入符号栈。
}
elseif(num==0){
分析成功,返回OK
}
}
if(i==str.size())
返回出错位置为i-1个单词
(4)程序流程图
对字符串分割的函数流程图如下图3.1-2所示:
对输入的SQL语句进行文法分析的函数intanalysis:
:
analysis_str(charsql[],string&error)流程图如下所示:
(5)测试用例与实验结果
测试用例:
3.1-1:
createtablestu(idint,namechar(20),scoreint);
测试用例3.1-2:
selectname,age,addressfromuser;
测试用例3.1-3:
alerttttablestuaddidint;
测试用例3.1-4:
updatestuseta='abcd'wherea;
3.2创建数据库及数据操作功能
(1)功能介绍
1、实现建立数据库表结构的功能。
该部分还包括以下几个功能:
(1)支持整型int、字符型char、变长字符型varchar数据。
(2)以文件形式保存基本表。
(3)具有相应的数据字典存储表名、表的结构等相关信息。
2、实现输入数据库记录的功能,可以通过SQLinsert语句向已有的表中插入数据库记录。
当表不存在时会提示输入错误。
3、实现删除数据库记录的功能,通过delete语句删除某一条或者符合某一条件的记录。
同时会显示删除的记录个数。
4、实现修改数据库记录的功能,该部分通过update语句可以修改符合某一条件的记录。
同时会显示所修改的记录个数。
5、实现显示数据库结构和内容的功能。
6、实现在已有的关系中添加属性的功能,利用alert命令可以添加一个表的属性。
表不存在时会有错误提示。
7、实现从已有的关系中删除属性的功能利用alert命令可以添加一个表的属性。
表不存在时会有错误提示,当表只剩余一列时不允许再删除该属性可以通过drop语句删除表。
8、实现删除表的功能,使用drop命令删除表,当表不存在时会提示表不存在的错误信息。
(2)相关理论
1、文件和文件记录
数据通常都是以记录的形式存储在磁盘上。
记录由一组相关的数据值或数据项排列而成。
每个数据项对应于记录的一个域,由一个或几个字节组成。
记录的每个域具有一个名字和一个数据类型,如整数、字符串等。
一组域名字及其对应的数据类型构成了记录型或记录格式。
文件是一个记录序列。
一个文件的所有记录都具有相同的记录型。
如果一个文件的所有记录都具有相同的长度,这个文件被称为定长记录文件。
如果一个文件中的不同记录可能具有不同的长度,则称这个文件为变长记录文件。
以下是磁盘上存储文件的方法和特点。
连续存储方法:
按照文件中文件块的顺序把文件存储到连续磁盘块上。
存取整个文件的效率高。
文件扩充困难。
链接存储方法:
在每个文件块中增加一个指向下一个文件块所在的磁盘块的地址指针。
便于文件扩充。
读整个文件的速度很慢。
索引存储方法:
在磁盘上存储一个或多个索引块。
每个索引块包含指向文件块的指针。
每个数据库管理系统都包含一个称为数据字典的小型数据库。
2、数据字典
数据字典用来存储数据库中数据对象的描述信息和数据库管理系统需要的控制信息。
数据对象的描述信息包括概念模式、内模式、外模式以及它们之间的映象的描述。
数据库管理系统需要的控制信息包括查询优化、安全性检查、用户权限验证、事务处理、报告生成、约束验证、数据定义和操纵语言编译等系统程序模块所需要的信息。
3、堆文件的查找操作
查找一个满足给定条件的记录:
必须从文件的第一个记录开始搜索,直到发现满足条件的记录为止。
如果满足条件的记录不止一个,需要搜索整个文件。
4、堆文件的插入操作
堆文件的头存储它的最末一个磁盘块的地址。
插入一个记录时,首先,读文件头,找到最末磁盘块地址,把最末磁盘块读入主存储器缓冲区;然后,在缓冲区内把新记录存储到最末磁盘块的末尾;最后,把缓冲区中修改过的最末磁盘块写回原文件。
5、堆文件的删除操作
第一种方法:
首先找到被删除记录所在的磁盘块;然后读到主存缓冲区,在缓冲区中删除记录;最后把缓冲区内容写回磁盘文件。
这种方法将使文件中出现空闲的存储空间,需要周期地整理存储空间,避免存储空间的浪费。
第二种方法:
在每个记录的存储空间增加一个删除标志位。
当删除一个记录时,把删除标志位置1。
查找记录时跳过删除位置为1的记录。
这种方法也需要周期地整理存储空间。
第三种方法:
当删除一个记录时,把文件末尾记录移动到被删除记录的位置。
避免了存储空间的整理。
只适用于定长记录文件。
6、堆文件的修改操作
定长记录文件:
找到记录所在磁盘块,读入主存缓冲区,在缓冲区中修改记录,并写回磁盘。
变长记录文件:
先删除后插入。
(3)算法描述
1、创建表的功能
创建表的功能由Create类的函数intCreate:
:
create_table(charsql[]);来实现。
其中传入的参数sql为形如“createtabletable_name(id1类型1,id2类型2…idn类型n)”其具体的算法描述如下所示:
intCreate:
:
create_table(charsql[]){
chartname[100];
从sql语句中提取表名table_name,存储在table_name中.
if(isExistTable(table_name)){
提示表已经存在。
returnERROR;
}
向数据字典中追加table_name的表名table_name以及表的结构。
创建文件"database/"+table_name+".txt".
returnOK;
}
2、插入记录的功能
插入记录的功能由Insert类里的intInsert:
:
insertRecord(charsql[]);函数来实现。
传入的sql语句参数形如“insertintotable_name(id1,id2…idn)values('value1','value2'…'valuen');”或者形如“insertintotable_namevalues('value1','value2'…'valuen');”具体的算法如下所描述:
intInsert:
:
insertRecord(charsql[]){
if(获取表结构失败)
returnERROR;
if(sql[3]!
="("){//insertintotable_namevalues(...);
对表的结构做检验,如果插入结构不正确,则返回并提示结构不匹配。
向表中追加一条记录。
}
else{//insertintotable_name(id1..)values('value1'..);
if(sql语句中插入位置与插入的值不匹配)
returnERROR;
if(插入位置中列名与数据字典信息不符){
returnERROR;
向表中追加一条记录。
}
提示记录插入成功。
returnOK;
}
3、修改数据库记录的功能
修改数据库记录的函数实现由Update类中的intUpdate:
:
updateRecord(charsql[])函数来实现,具体算法如下所示:
intUpdate:
:
updateRecord(charsql[]){
从sql中提取表名table_name.
if(获取表结构失败)//表不存在
returnERROR;
if(set语句中存在与数据字典不符的列名)
returnERROR;
if(where语句中存在与数据字典不符的列名)
returnERROR;
从文件"database"+table_name+".txt"中读取表内容table。
for(introw=0;rowif(table[row]符合条件)
对table[row]修改。
}//for
table写回到文件"database"+table_name+".txt"中.
returnOK;
}
4、删除数据库记录的功能
修改数据库记录的函数实现由Update类中的intDelete:
:
deleteRecord(charsql[]);函数来实现,具体算法如下所示:
intDelete:
:
deleteRecord(charsql[]){
从sql语句中提取表名table_name;
if(从数据字典中获取table_name表结构失败)//该表不存在
returnERROR;
if(where语句中存在与数据字典不符的列名)
returnERROR;
从文件"database"+table_name+".txt"中读取表内容table。
for(introw=0;rowif(table[row]符合条件)
删除table[row]。
}//for
将table写回到文件"database"+table_name+".txt"中.
returnOK;
}
5、添加属性的功能
Alter类中的函数intAlter:
:
addColumn(charsql[])负责实现添加属性的功能。
除了需要对数据字典中表的结构进行修改外,还要对存储表的文件进行修改,使文件的表结构与数据字典里存储的结构一致。
具体的实现算法如下所示:
intAlter:
:
addColumn(charsql[]){
从sql语句中提取表名table_name;
if(从数据字典中获取table_name表结构失败)//该表不存在
returnERROR;
if(要添加的列名中存在与表结构中一致的列名)//sql语句中存在错误
returnERROR;
修改数据字典中的表的结构。
从文件"database"+table_name+".txt"中读取表的内容存储到table中。
for(inti=0;i向table[i]中添加相应的列,值为空。
将table写回到文件"database"+table_name+".txt"中。
returnOK;
}
6、删除属性的功能
Alter类中的函数intAlter:
:
delColumn(charsql[])负责实现删除属性的功能。
该函数的实现与添加属性中addColumn实现类似,除了有sql语句的校验还有对数据字典和存储文件的修改。
具体的实现算法如下所示:
intAlter:
:
delColumn(vectorvstr){//altertablenamedropid1,id2,id3...
从sql语句中提取表名table_name;
if(从数据字典中获取table_name表结构失败)//该表不存在
returnERROR;
if(要删除的列名中有未知的列名)//sql语句错误
returnERROR;
修改数据字典中的表的结构。
从文件"database"+table_name+".txt"中读取表的内容存储到table中。
for(inti=0;i从table[i]中删除要删掉的列。
将table写回到文件"database"+table_name+".txt"中。
returnOK;
}
7、删除表的功能
intDrop:
:
dropTable(charsql[]){
从sql中提取要删除的表table_name.
if(数据字典中不存在表table_name的记录)
returnERROR;
删除数据字典中关于table_name的记录
system("deldatabase\\"+table_name+".txt");//调用DOS功能对记录文件的删除
returnOK;
}
(4)程序流程图
1、创建表的功能
如图3.2-1为创建表的流程图。
即intCreate:
:
create_table(charsql[])函数的实现流程图。
图3.2-1
2、插入记录的功能
图3.2-2
3、修改数据库记录的功能
图3.2-3
4、删除数据库记录的功能
图3.2-4
5、添加属性的功能
图3.2-5
6、删除属性的功能
图3.2-6
7、删除表的功能
图3.2-7
(5)测试用例与实验结果
1、测试用例3.2-1:
createtablestudent(namechar(8),pswchar(8),xhint,sorceint);
执行结果如图所示:
数据字典中保存的信息如下所示:
2、测试用例3.2-2:
insertintostudentvalues('abc','abc','1','30');
insertintostudentvalues('abc','abc','2','60');
insertintostudentvalues('du','ccd','3','70');
insertintostudentvalues('li','ssc','4','90');
insertintostudentvalues('chen','ccc','5','80');
insertintostudentvalues('chen','ccc','5','a80');
如下图所示为“database/student.txt”中的保存信息:
3、测试用例3.2-3:
updatestudentsetsorce=55wherexh=5;
updatestudentsetsorce1=10wherename='abc';
执行结果如下图所示:
通过select语句查看表内容如下所示:
4、测试用例3.2-4:
deletefromstudentwherename='abc';
deletefromstudentwheresorce>=55;
执行结果如下图所示:
执行select*fromstudent;语句结果如下图所示:
5、测试用例3.2-5:
altertablestudentaddsorce1int;
执行结果如下图所示:
查看数据字典中如下图所示:
通过select语句查看表的内容如下所示:
6、测试用例3.2-6
altertablestudentdrop(sorce1);
altertablestudentdrop(a);
执行结果如下图所示:
数据字典中对于student的表结构的存储如下图所示:
通过select语句查看score1已经不存在了,表的内容如下截图所示:
7、测试用例3.2-7:
droptablestudent;
如下为执行的结果,通过select查看表时发现系统提示表已经不存在:
3.3索引的创建及删除
(1)功能介绍
此部分意在通过建立索引文件以提高查询的效率。
通过createindex命令建立相应的索引文件,当使用select语句查询表时如果存在相应列的索引,则系统会自动提示使用的索引文件。
同时用户还可以使用dropindex命令来删除已有的索引文件。
本系统中创建的是辅助索引。
由于时间仓促,使用的索引是普通索引,即基于二分查找的方式来提高查找的效率。
(2)相关理论
1、索引文件
类似于科技图书中的名词术语索引。
当查找一个记录时,先查阅索引,找到记录在文件中的地址,然后从文件读出这个记录。
一个文件的索引通常定义在该文件的一个或一组域上。
这组域称为索引域。
索引也是一个文件,称为索引文件。
被建立索引的文件称为数据文件。
索引文件的记录称为索引记录或索引项。
每个索引记录包括两个域
第一个域用来存储数据文件索引域的值K;
第二个域用来存储一个或一组指针,每个指针指向一个索引域值为K的记录所在磁盘块的地址。
索引文件通常都按照索引域值的大小排序,以提高存取效率。
索引文件一般都远小于数据文件。
2、索引的分类
按照索引文件的结构