时间:2020/1/16

写这个DBMS(说DBMS夸张了,应该是一个控制台程序)的起因是数据库实践老师布置的一个大作业,先贴上GitHub地址: https://github.com/machi12/MyDatabase,如果大家觉得可以的话,希望点个star.

这篇博文主要会讲一下自己在实现这个DBMS时遇到的一些问题以及自己解决的思路.

一.实现功能

我写的这个DBMS实现了如下功能(主要的指令格式参照了MySQL的命令行指令):

1.show databases;  //列出目前所有存在的数据库

2.create database 数据库名;  //创建一个数据库

3.drop database 数据库名;  //删除一个数据库

4.use 数据库名;  //使用一个数据库

5.show tables;  //列出当前数据库中存在的所有表

6.create table(列名 类型 约束, .......);  //创建一个表

7.describe 表名;  // 打印一个表的详细信息

8.insert into 表名 (列名,.....) values (值,......);  //向表中插入数据

9.select * from 表名;  //查询表中的所有数据

10.drop table 表名;  //删除一个表

11.help;  //帮助信息;

12.quit;  //退出

下面是指令执行的截图:

1.

2.

3.

4.

5.

6.

二.项目配置

从GitHub仓库下载下来源码并解压后,需要在本地配置一下相关的信息. (我这里用的IDE是idea)

项目目录如下

要使这个项目可以在本地运行,需要更改SQLConstant.java中的相关代码

 //数据库的根路径
private static final String path = "E:\\MyDatabase";

将上面的根目录改成本地的一个目录

 //自定义的分隔符
private static final String separate = "~";

同时也可以自定义数据库中的分隔符,我这里使用的是"~".

更改完路径后这个代码就可以在本地运行了,创建的数据库都会在指定的路径下.

三.需要解决的问题

在这里我结合我在做这个系统的遇到的问题来说一下做一个简单的DBMS需要解决哪几个方面的问题:

1.对输入的语句进行标准化

在使用的过程中你要考虑到用户的输入可能不是百分百的符合标准的格式,你要确保在没有语法错误的情况下也能正确解析出用户输入的语句,比如大小写,多个空格以及换行符等.

2. 语句的解析

在进行完标准化后就可以进行语句的解析了,这部分主要是确定用户想要执行操作的大类,至于具体的操作,需要在大类中再细分.

3.语句的执行

在解析完语句后就会跳转到具体的类去执行相应的操作,对于操作问题,主要是创建删除文件以及对文件的读写等,当然,这里面也会有一些很细节的东西,比如你要自定义分隔符,这样在读写的时候才能和之前定义的字段一一对应,要不你不知道每个数据是从哪里分割的,当然还有其他问题,这个可能需要你写的时候慢慢想.

这部分只是给出操作时可能遇到的问题,主要想让大家在做之前想一下每部分怎么实现比较好,至于我的实现方法会在下面的部分具体给出.

四,问题的解决

1.对输入的语句进行标准化

对于这部分的实现,我做的并没有很细,只是把能想到的给做了,如去掉语句两端的空格,把多个空格转化为一个空格等,具体实现代码如下:

 public static String sqlFromat(String input){
String sql = "";
//去掉最后的;和空格
//sql = input.replaceAll(";", "");
//去掉字符串前后两端的空格
sql = input.trim();
//将字符串都转化为小写
String string = sql.toLowerCase();
//通过正则表达式将多个空格转换为一个空格
String str = string.replaceAll("\\s{2,}", " ");
//去掉;前的空格
String s = str.replaceFirst("( ;)$", ";");
//System.out.println(s);
return s;
}

我对于所有的语句默认必须以;结尾,在项目的Input类中我会通过endsWith方法判断输入语句的最后一个字符是不是";". 如果是,则结束输入并将输入的语句交给SqlAnalysis类进行解析.

2.语句解析

将输入的语句传到语句解析方法中,根据正则表达式匹配语句中的第一个单词来转到相应的语句处理类中.这里的解析只是一个大类上的解析,根据输入语句的第一个单词进行处理,函数如下:

 package sdnu.machi;

 import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* @ Description : 实现一个sql解析器,目前支持create, show, use, quit
* @ Author : 马驰
* @ CreateDate : 2019/12/26 17:03
*/
public class SqlAnalysis { //private static String[] str;
//private static final String path = "E:\\MyDatabase";
//下面是目前支持的sql语句类型
private static final String create = "create";
private static final String help = "help";
private static final String show = "show";
private static final String use = "use";
private static final String quit = "quit";
private static final String describe = "describe";
private static final String insert = "insert";
private static final String select = "select";
private static final String drop = "drop"; public static void analysis(String sql){
//str = sql.split(" ");
String start = "";
//正则表达式的匹配规则
String regex = "^[a-z]+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sql);
//获取匹配值
while(matcher.find()){
start = matcher.group();
} //根据第一个单词判断该语句的作用
switch (start){
case create:
Create.createSql(sql);
break;
case help:
Help.help();
break;
case show:
Show.showSql(sql);
break;
case use:
Use.useSql(sql);
break;
case quit:
Quit.quitSql();
break;
case describe:
Describe.describeSql(sql);
break;
case insert:
Insert.insertSql(sql);
break;
case select:
Select.selectSql(sql);
break;
case drop:
Drop.dropSql(sql);
break;
default:
System.out.println("输入的命令无法识别,可以输入help查看目前支持的sql语句");
Input.get();
break;
}
//System.out.println(start);
} } 

3.语句的执行

语句的执行这部分主要有两个方面的任务:

一是对从第二步解析完的指令进行进一步的细分,就以create指令来说,当你在第二步识别出这是一个create指令后,你还要接着识别这是一个create table还是create database指令,因为这两种指令完成的操作是不一样的.

二是对细分后的指令进行执行操作,这里涉及到操作就比较多,一是映射问题,我这里把一个数据库映射成一个文件夹,把一个数据表映射成一个txt文件(如果你使用xlxs格式或者csv格式的话会更加容易,因为这样你就不需要考虑分隔符的问题,这些文件格式有自己定义的分割符). 二是控制信息(列名,类型,主外键等)和数据信息存放位置的问题,你是要单独为每一个表创建一个存放控制信息文件还是在一个文件中同时存放控制信息和数据信息,我这里采用的是第二种方式,我把一个txt文件的前三行用来存放控制信息(第一行是列名,第二是数据类型,第三行其余信息),之后的位置用来存放数据信息. 三是转义的问题,如果数据中含有你的分隔符要怎么存放,我这里是如果含有,则在分隔符前面再加一个分隔符,取的时候去掉多余的.还有其他可能存在的问题,这里可能记不太清了(原谅我,考试周复习的有点记不得了......)

对于每个操作我都对用一个java类,例如create操作我写了一个create类,由于代码较多,我就不贴出来了,大家可以在GitHub上下载下来看.

五.最后

在写这个项目之前自己也查过很多资料,在查的过程中不乏有劝退的,理由无非是网上这方面的开源项目已经很多了,没有必要去花时间造轮子了.做完后就说一下自己的想法吧,如果你觉得你不确定能不能做出来的情况下,最好去做一下,感觉做完之后还是蛮有提高的,而且对于自己的信心提升也挺大,如果你感觉你的能力做这样一个东西太简单了,那就没有必要了,花时间去看一些最新的框架比这个提升会更大.

最后,新的一年和大家在这里共勉.希望在2020年考研顺利,继续开心的撸代码.

用Java实现一个简单的DBMS(总结)的更多相关文章

  1. 使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小

    原文:http://www.jb51.net/article/75002.htm 这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实 ...

  2. 使用 java 实现一个简单的 markdown 语法解析器

    1. 什么是 markdown Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的 ...

  3. java:jsp: 一个简单的自定义标签 tld

    java:jsp: 一个简单的自定义标签 tld 请注意,uri都是:http://www.tag.com/mytag,保持统一,要不然报错,不能访问 tld文件 <?xml version=& ...

  4. 使用JAVA写一个简单的日历

    JAVA写一个简单的日历import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateF ...

  5. Java实现一个简单的网络爬虫

    Java实现一个简单的网络爬虫 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWri ...

  6. Java实现一个简单的文件上传案例

    Java实现一个简单的文件上传案例 实现流程: 1.客户端从硬盘读取文件数据到程序中 2.客户端输出流,写出文件到服务端 3.服务端输出流,读取文件数据到服务端中 4.输出流,写出文件数据到服务器硬盘 ...

  7. 如何设计Java框架----一个简单的例子【翻译】

    原文:http://www.programcreek.com/2011/09/how-to-design-a-java-framework/ 原文和翻译都只是参考,如有不对,欢迎指正. 你可能会好奇框 ...

  8. Java写一个简单学生管理系统

    其实作为一名Java的程序猿,无论你是初学也好,大神也罢,学生管理系统一直都是一个非常好的例子,初学者主要是用数组.List等等来写出一个简易的学生管理系统,二.牛逼一点的大神则用数据库+swing来 ...

  9. 利用java实现一个简单的远程监控程序

    一般的远程监控软件都是用c或者c++等语言开发的,而使用java如何来实现相同的功能呢. 首先我们先介绍一下一个简单的远程监控程序的实现原理. 功能一,远程屏幕监视 (1) 必须要有监控端与被监控端, ...

随机推荐

  1. Java方法的参数传递是值传递还是引用传递?

    当基本数据类型(Boolean,byte,char,String,int,Long,float,double)作为参数传递时,传递的是实参值的副本,即传的是值,无论在函数中怎么操作这个副本,实参的值是 ...

  2. Python学习3月5号【python编程 从入门到实践】---》笔记

    ---恢复内容开始--- 1.变量 一.只能包含字母.数字.下划线.****不能以数字开头作变量 二.不能包含空格, 三.不要将python关键字和函数名用作变量名 四.最好能有描述性和简短的特征 五 ...

  3. vue学习笔记(四)事件处理器

    前言 在上一章vue学习笔记(三)class和style绑定的内容中,我们学习了如何在vue中绑定class和style,介绍了常用的绑定方法,class的数组绑定和对象绑定以及style的数组绑定和 ...

  4. leetcode.1266访问所有点的最小时间

    平面上有 n 个点,点的位置用整数坐标表示 points[i] = [xi, yi].请你计算访问所有这些点需要的最小时间(以秒为单位). 你可以按照下面的规则在平面上移动: 每一秒沿水平或者竖直方向 ...

  5. 洛谷$P$3160 局部极小值 $[CQOI2012]$ 状压$dp$

    正解:状压$dp$ 解题报告: 传送门! 什么神仙题昂,,,反正我是没有想到$dp$的呢$kk$,,,还是太菜了$QAQ$ 首先看数据范围,一个4×7的方格,不难想到最多有8个局部极小值,过于显然懒得 ...

  6. Java集合使用之next方法与remove方法 | Java集合使用之remove方法使用易错

    Iterator接口的remove方法将会删除上次调用next方法时返回的元素. next方法和remove方法的调用具有相互依赖性,如果调用remove方法前没有调用next方法是不合法的. 错误使 ...

  7. 「博客美化」I 页面的CSS

    要有自己的CSS十分重要 可以改别人写的CSS代码 也可以改博客园模板 我这里改的是SympleMomery 别忘了禁用模板 /*......去除广告..........*/ div[id^=&quo ...

  8. 分布式唯一ID:雪花ID Snowflake .Net版

    先抄个雪花ID介绍,雪花算法: 雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等. 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景.GUID:采用无意义字 ...

  9. Ant Design 表单中getFieldDecorator、getFieldValue、setFieldValue用法

    Ant Design 表单中getFieldDecorator.getFieldValue.setFieldValue用法 一.getFieldDecorator getFieldDecorator是 ...

  10. 实现github的自动钩子

    实现github的自动钩子 最近在学习go,也写了一些玩具放到自己的服务器中,但是感觉每次写完在本地交叉编译后上传到服务器略显麻烦,上传代码到服务器中编译也是略显麻烦,把编译文件加入到git管理中会导 ...