实现一个基本的数据库

    大概一年前的这个时候,为了深入了解数据库的内部原理和实现,我决定编写一个数据库系统的原型程序,这个行动断断续续坚持了一年,写了接近3W行C代码,现在除了事务和并发(只做到了存储引擎层面的并发),其他的功能基本都实现了。数据库是底层软件,实现起来有一定难度,为了编写这个程序(暂且就叫做XSQL吧),我阅读了很多关于开源数据库内部原理的书籍资料,总结了主流数据库的结构,然后依据其原理写出了XSQL。接下来我打算把实现这个程序中遇到的问题,解决的办法和涉及的技术写成一个专题,这样可以让更多同学更加深入的理解数据库系统的内部原理,还可以让他人发现我实现过程中的不足之处,指出优化方法。

 

XSQL中的数据类型(绿色暂未实现):

CHAR

定长字符串

VARCHAR

变长字符串

FLOAT

单精度浮点型

DOUBLE

双精度浮点型

INT

整型

SMALLINT

短整型

BIGINT

长整型

DATETIME

时间戳

TEXT

文本

FILE

文件


 

XSQL支持的函数:

字符串函数

LENGTH(exp)

返回字符串exp的长度

SUBSTR(exp1,exp2)

返回串exp2在exp1中出现的下标,如果不存在则返回-1

时间函数

GETDATE()

返回当前的系统时间字符串

TODATE(exp)

将时间戳exp转化为时间字符串

TOTIMESTAMP(exp)

将时间字符串exp转化为时间戳

数学函数

POWER(exp1,exp2)

返回exp1的exp2次幂

SIN(exp)

返回exp的正弦值

COS(exp)

返回exp的余弦值

SQRT(exp)

返回exp的平方根

ABS(exp)

返回exp的绝对值

聚合函数

MAX(exp)

返回最大的exp

MIN(exp)

返回最小的exp

SUM(exp)

返回所有行的exp的和

COUNT(exp)

返回行数

AVG(exp)

返回所有行的exp平均值

 

在XSQL中执行如下命令建立学生选课关系表:


CREATE TABLE student
(
 s# INT AUTO_INCREMENT NOT NULL ,
 name CHAR(20) ,
 age SMALLINT CHECK(age  BETWEEN 15 AND 20) ,
 sex CHAR(2) CHECK(sex IN('男','女')) ,
 address VARCHAR(50) ,
 reg_time DATETIME ,
 PRIMARY KEY(s#)
)

INSERT INTO student(s#,name,age,sex ,address ,reg_time)
VALUES (NULL,'wang',20,'男','哈尔滨',totimestamp(getdate()))

INSERT INTO student(s#,name,age,sex ,address ,reg_time)
VALUES (NULL,'li',19,'男','哈尔滨',totimestamp(getdate()))

INSERT INTO student(s#,name,age,sex ,address ,reg_time)
VALUES (NULL,'chen',17,'男','哈尔滨',totimestamp(getdate()))

INSERT INTO student(s#,name,age,sex ,address ,reg_time)
VALUES (NULL,'wu',18,'男','哈尔滨',totimestamp(getdate()))

INSERT INTO student(s#,name,age,sex ,address ,reg_time)
VALUES (NULL,'luo',20,'女','哈尔滨',totimestamp(getdate()))

INSERT INTO student(s#,name,age,sex ,address ,reg_time)
VALUES (NULL,'zhou',20,'女','哈尔滨',totimestamp(getdate()))

CREATE TABLE course
(
 c# INT AUTO_INCREMENT NOT NULL,
 cname CHAR(15),
 teacher CHAR(15),
 PRIMARY KEY(c#)
)

INSERT INTO course(c#,cname,teacher) VALUES(NULL,'数据库','li')
INSERT INTO course(c#,cname,teacher) values(NULL,'数学','ma')
INSERT INTO course(c#,cname,teacher) values(NULL,'化学','zhou')
INSERT INTO course(c#,cname,teacher) values(NULL,'物理','shi')
INSERT INTO course(c#,cname,teacher) values(NULL,'操作系统','wen')

CREATE TABLE sc
(
 s# INT  NOT NULL,
 c# INT  NOT NULL,
 grade SMALLINT CHECK(grade BETWEEN 0 AND 100),
 PRIMARY KEY(s#,c#),
 FOREIGN KEY(s#) REFERENCES student(s#),
 FOREIGN KEY(c#) REFERENCES course(c#)
)

INSERT INTO sc(s#,c#,grade) values(1,1,55)
INSERT INTO sc(s#,c#,grade) values(1,2,78)
INSERT INTO sc(s#,c#,grade) values(1,3,85)
INSERT INTO sc(s#,c#,grade) values(1,4,91)
INSERT INTO sc(s#,c#,grade) values(1,5,69)
INSERT INTO sc(s#,c#,grade) values(2,1,85)
INSERT INTO sc(s#,c#,grade) values(3,1,90)
INSERT INTO sc(s#,c#,grade) values(3,2,86)
INSERT INTO sc(s#,c#,grade) values(3,3,95)
INSERT INTO sc(s#,c#,grade) values(4,1,71)
INSERT INTO sc(s#,c#,grade) values(4,4,63)
INSERT INTO sc(s#,c#,grade) values(5,1,70)
INSERT INTO sc(s#,c#,grade) values(5,2,65)
INSERT INTO sc(s#,c#,grade) values(5,3,80)
INSERT INTO sc(s#,c#,grade) values(5,5,65)
INSERT INTO sc(s#,c#,grade) values(6,1,78)
INSERT INTO sc(s#,c#,grade) values(6,3,90)

 

查询演示:

--列出student表的所有行

SELECT s#,name ,age ,sex ,address ,todate(reg_time)

FROM student

 

--列出course表的所有行

SELECT*

FROM course

实现一个基本的数据库_第1张图片

 

--检索学习课程号为2的学生学号与姓名

SELECT s#,name

FROM student

WHERE EXISTS (

         SELECT *

         FROM sc

         WHERE c#=2 AND s#=student.s#

         )

 

--检索学习数学的学生学号,姓名和入学时间

SELECT name,student.s# ,todate(reg_time) as '入学时间'

FROM student,sc,course

WHERE cname='数学' AND student.s#=sc.s# AND sc.c#=course.c#

实现一个基本的数据库_第2张图片

 

--检索学习全部课程的学生姓名

SELECT name

FROM student

WHERE NOT EXISTS(

              SELECT *

              FROM course

              WHERE NOT EXISTS(

                            SELECT *

                            FROM sc

                            WHERE s#=student.s# ANDc#=course.c#

                            )

              )

 

--检索名字小于等于平均长度的学生信息

SELECT *

FROM student

WHERE LENGTH(name) <= (SELECT AVG(LENGTH(name)) FROM student)

 

--检索大于等于平均年龄且最高分数和最低分数之差不超过10分或者小于平均年龄且之差不超过15的学生信息

SELECT *

FROM student

WHERE

(

10 > (SELECT MAX(grade) - MIN(grade)

      FROM SC

      WHERE s# =student.s#) AND age >= (SELECT AVG(age) FROM student)

) OR (

15 > (SELECT MAX(grade) - MIN(grade)

      FROM SC

      WHERE s# =student.s#) AND age < (SELECT AVG(age) FROM student)

)

你可能感兴趣的:(实现一个基本的数据库)