數據庫管理系統(DBMS):位於用戶與操作系統之間的一層數據管理軟件。主要功能:數據定義功能(DDL);數據組織、存儲和管理;數據操縱功能(DML);數據庫的事務管理和運行管理;數據庫的建立和維護功能;其他功能。
數據表:在關係型數據庫中,數據是以表的形式組織和存放的。表的結構:表由字段與記錄共同構成。主鍵:是表中一個或多個字段的組合,唯一的標識了一條記錄。
主鍵的值具有唯一性。
數據庫:長期存儲在計算機內、有組織、可共享的大量的數據的集合。數據庫中的數據按照一定的數據模型組織、描述和存儲,具有較小的冗餘度、較高的數據獨立性和易擴展性,並可爲各種用戶共享。特點:永久存儲、有組織、可共享。
數據:描述事物的符號記錄稱爲數據。特點:數據和關於數據的解釋不可分。
本次模擬了數據庫的創建,刪除(文件夾),數據表的創建,刪除(.txt文件)以及數據的增加、查詢、修改和刪除(簡化),用基本的幾條SQL語言來進行操作,即代碼中的說明。
代碼如下:
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <string>
#include <sstream>
#include <iomanip>
#include <direct.h>
#include <io.h>
#include <fstream>
using namespace std;
const int inf = 0x3f3f3f3f;
struct Tables {
string name;
string pathName;
vector<string>colName;//列名稱
vector<string>type;
vector<int>size;
FILE* fp;
};
class myDBMS {
vector<Tables*>tab;
bool open;
public:
string cmd;
string prePath;//數據庫的文件路徑
myDBMS() {
cmd = "";
prePath = "";
open = false;
//建庫刪庫,建表刪表,增刪改查
cout << "請按以下規則輸入命令語句(命令不分大小寫)" << endl;
cout << "新建數據庫: create database 數據庫名字" << endl;
cout << "刪除數據庫: drop database 數據庫名字" << endl;
cout << "打開數據庫: open database 數據庫名字" << endl;
cout << "關閉數據庫: close database 數據庫名字" << endl;
cout << "添加新表 : create table 表名" << endl;
cout << " (" << endl;
cout << " 列1(字段)名 數據類型1(大小:若爲1可省略)," << endl;
cout << " 列2(字段)名 數據類型2(大小:若爲1可省略)," << endl;
cout << " … …" << endl;
cout << " )" << endl;
cout << "刪除舊錶 : drop table 表名" << endl;
cout << "查看全表 : query all from 表名" << endl;
cout << "查詢單值 : query 列名 from 表名 where 列名 = 值(值可爲all,表全部範圍)" << endl;
cout << "插入 : insert into 表名(field1,field2,…) values(value1,value2,…)" << endl;
cout << "修改 : update 列名 = 新值 from 表名 where 列名 = 值(值可爲all,表全部範圍)" << endl;
cout << "刪除 : delete from 表名 where 列名 = 值(值可爲all,表全部範圍)" << endl;
cout << "退出程序 : exit" << endl;
}
~myDBMS() {
for (int i = 0; i < tab.size(); i++) {
if (tab[i]->fp != NULL)
fclose(tab[i]->fp);
delete tab[i];
}
tab.resize(0);
cmd = "";
prePath = "";
}
void transfer();//轉爲小寫
void openDataBase(string);//打開數據庫
void closeDataBase();//關閉數據庫
void myCreateDataBase(string); //建立數據庫
void myDropDataBase(string); //刪除數據庫
void myCreateTable(string); //創建表
void myDropTable(string); //刪除表
void myInsert(string,string); //插入數據
void myDelete(string,string); //刪除數據
void myUpdate(string, string, string, string); //更新數據
void myQuery(string, string, string); //查詢數據
int posIsNos(string);//輔助函數
};
void myDBMS::transfer() {
for (int i = 0; i < cmd.size(); i++)
cmd[i] = tolower(cmd[i]);
}
void myDBMS::openDataBase(string dataBaseName) {
if (open) {
cout << "請先關閉當前打開的數據庫" << endl;
return;
}
string pathName = "C:\\Users\\TKwang\\source\\repos\\Project1\\" + dataBaseName;
if (0 != access(pathName.c_str(), 0))printf("該數據庫不存在");
else {
prePath = pathName + "\\";
cout << "打開數據庫成功" << endl;
open = true;
}
}
void myDBMS::closeDataBase() {//和析構函數相同
for (int i = 0; i < tab.size(); i++) {
if (tab[i]->fp != NULL)
fclose(tab[i]->fp);
delete tab[i];
}
tab.resize(0);
cmd = "";
prePath = "";
open = false;
}
//C:\Users\TKwang\source\repos\Project1
void myDBMS::myCreateDataBase(string dataBaseName) {//建立數據庫
string pathName = "C:\\Users\\TKwang\\source\\repos\\Project1\\" + dataBaseName;
if (0 != access(pathName.c_str(), 0)) {
if (0 == mkdir(pathName.c_str()))//返回0表示創建成功,-1表示失敗
cout << "創建成功" << endl;
else
cout << "創建失敗" << endl;
return;
}
cout << "該數據庫已存在" << endl;
}
void myDBMS::myDropDataBase(string dataBaseName) {//刪除數據庫
string pathName = "C:\\Users\\TKwang\\source\\repos\\Project1\\" + dataBaseName;
if (0 == access(pathName.c_str(), 0)) {
pathName = "rd " + pathName;
if (0 == system(pathName.c_str()))
cout << "刪除數據庫" << dataBaseName << "成功" << endl;
else
cout << "刪除數據庫" << dataBaseName << "失敗" << endl;
return;
}
cout << "數據庫" << dataBaseName << "不存在" << endl;
}
void myDBMS::myCreateTable(string tableName) {//建立表
vector<string>colName;
vector<string>type;
vector<int>size;
string tmp;
getchar();
getline(cin, tmp);
getline(cin, tmp);
while (tmp != ")") {
stringstream ss(tmp);
string x;
ss >> x; colName.push_back(x);
ss >> x;
int pos = x.find('(');
if (pos == string::npos) {
type.push_back(x);
size.push_back(1);
}
else {
type.push_back(x.substr(0, pos));
int num = 0;
for (int i = pos + 1; i < x.length() - 1; i++)
num = num * 10 + x[i] - '0';
size.push_back(num);
}
getline(cin, tmp);
}
tableName += ".txt";
string pathName = prePath + tableName;
//cout << pathName.c_str() << endl;
if (0 != access(pathName.c_str(), 0)) {
Tables* ptr = new Tables;
ptr->name = tableName;
ptr->pathName = pathName;
ptr->colName = colName;
ptr->type = type;
ptr->size = size;
ptr->fp = fopen(pathName.c_str(), "w");
string wrin;
wrin.clear();
for (int i = 0; i < colName.size(); i++)
wrin += colName[i] + ";" + type[i] + ";" + to_string(size[i]) + ";";
wrin += "\n";
fprintf(ptr->fp,wrin.c_str());
fclose(ptr->fp);
tab.push_back(ptr);
cout << "創建新表成功!" << endl;
return;
}
cout << "該表已經存在!" << endl;
}
void myDBMS::myDropTable(string tableName) {//刪除表
tableName += ".txt";
string pathName = prePath + tableName;
if (0 != access(pathName.c_str(), 0))
cout << "該表不存在!" << endl;
else {
for (int i = 0; i < tab.size(); i++)
if (tab[i]->name == tableName) {
if (tab[i]->fp != NULL)
fclose(tab[i]->fp);
delete tab[i];
tab.erase(tab.begin() + i);
}
remove(pathName.c_str());
cout << "刪除成功!" << endl;
}
}
int myDBMS::posIsNos(string tableName) {
string pathName = prePath + tableName + ".txt";
if (0 != access(pathName.c_str(), 0)) {
cout << "該表不存在!" << endl;
return -1;
}
FILE* tempfptr = fopen(pathName.c_str(), "r");
char contant[100];
fscanf(tempfptr, "%s", contant);
string tmp = contant;
for (int i = 0; i < tmp.size(); i++)
if (tmp[i] == ';')
tmp[i] = ' ';
stringstream check(tmp);
string x, y, z;
Tables* nxt = new Tables;
nxt->name = tableName;
while (check >> x) {
check >> y >> z;
nxt->colName.push_back(x);
nxt->type.push_back(y);
nxt->size.push_back(atoi(z.c_str()));
}
nxt->pathName = pathName;
tab.push_back(nxt);
fclose(tempfptr);
return tab.size() - 1;
}
void myDBMS::myInsert(string tableName,string value) {//插入數據
if (!open) {
cout << "無選中數據庫!" << endl;
return;
}
int pos = inf;
for (int i = 0; i < tab.size(); i++)
if (tab[i]->name == tableName) {
pos = i; break;
}
if (pos == inf)
pos = posIsNos(tableName);
if (pos == -1)return;
stringstream ss(value);
string tmp2; ss >> tmp2;
tab[pos]->fp = fopen(tab[pos]->pathName.c_str(), "a");
for (int i = 0; i < tab[pos]->type.size(); i++) {
string tmp = tab[pos]->type[i];
//cout << "tmp:" << tmp << endl;
if (tmp == "int") {
int x; ss >> x;
fprintf(tab[pos]->fp, "%d", x);
}
else if (tmp == "float") {
float x; ss >> x;
fprintf(tab[pos]->fp, "%f", x);
}
else if (tmp == "double") {
double x; ss >> x;
fprintf(tab[pos]->fp, "%f", x);
}
else if (tmp == "char") {
if (tab[pos]->size[i] == 1) {
char x; ss >> x;
fprintf(tab[pos]->fp, "%c", x);
}
else {
int cnt = tab[pos]->size[i];
char* x = new char[cnt];
ss >> x;
fprintf(tab[pos]->fp, "%s", x);
delete x;
}
}
if (i != tab[pos]->type.size() - 1)
fprintf(tab[pos]->fp, "%c", ' ');
}
fprintf(tab[pos]->fp, "%c", '\n');
fclose(tab[pos]->fp);
cout << "插入成功!" << endl;
}
void myDBMS::myDelete(string tableName,string isWhere) {//刪除數據
if (!open) {
cout << "無選中數據庫!" << endl;
return;
}
int pos = inf;
for (int i = 0; i < tab.size(); i++)
if (tab[i]->name == tableName) {
pos = i; break;
}
if (pos == inf)
pos = posIsNos(tableName);
if (pos == -1)return;
stringstream ss(isWhere);
int wherePos = inf;
string typeName, toValue, whr, deng;
ss >> whr >> typeName >> deng >> toValue;
for (int i = 0; i < tab[pos]->colName.size(); i++) {
//cout << " " << tab[pos]->colName[i] << endl;
if (tab[pos]->colName[i] == typeName) {
wherePos = i;
break;
}
}
string pathName2 = prePath + "tmp.txt";
FILE* tmpfptr = fopen(pathName2.c_str(), "w");
char sentence[1024];
tab[pos]->fp = fopen(tab[pos]->pathName.c_str(), "r");
fgets(sentence, 1024, tab[pos]->fp);
fputs(sentence, tmpfptr);
bool flag = true;
if (toValue.length() == 3 && tolower(toValue[0]) == 'a' && tolower(toValue[1]) == 'l' && tolower(toValue[2]) == '1')
flag = false;
if (flag) {
while (!feof(tab[pos]->fp)) {
memset(sentence, 0, sizeof(sentence));
fgets(sentence, 1024, tab[pos]->fp);
stringstream myTmp(sentence);
//cout << "sentence " << sentence << endl;
string x;
for (int i = 0; i <= wherePos; i++)
myTmp >> x;
if (x == toValue) continue;
fputs(sentence, tmpfptr);
}
}
fclose(tmpfptr);
fclose(tab[pos]->fp);
remove(tab[pos]->pathName.c_str());
if (0 == rename(pathName2.c_str(), tab[pos]->pathName.c_str()))
cout << "刪除成功!" << endl;
else
cout << "刪除失敗!" << endl;
}
void myDBMS::myUpdate(string tableName, string toColName,string newValue, string isWhere) {//更新數據
if (!open) {
cout << "無選中數據庫!" << endl;
return;
}
int pos = inf;
for (int i = 0; i < tab.size(); i++)
if (tab[i]->name == tableName) {
pos = i; break;
}
if (pos == inf)
pos = posIsNos(tableName);
if (pos == -1)return;
stringstream ss(isWhere);
int wherePos = inf, updataPos = inf;
string typeName, toValue, whr, deng;
ss >> whr >> typeName >> deng >> toValue;
for (int i = 0; i < tab[pos]->colName.size(); i++) //找到範圍對應的colName下標
if (tab[pos]->colName[i] == typeName) {
wherePos = i;
break;
}
for (int i = 0; i < tab[pos]->colName.size(); i++) //找到需要修改的colName下標
if (tab[pos]->colName[i] == toColName) {
updataPos = i;
break;
}
string pathName2 = prePath + "tmp.txt";
FILE* tmpfptr = fopen(pathName2.c_str(), "w");
char sentence[1024];
tab[pos]->fp = fopen(tab[pos]->pathName.c_str(), "r");
fgets(sentence, 1024, tab[pos]->fp);
fputs(sentence, tmpfptr);
bool flag = true;
if (toValue.length() == 3 && tolower(toValue[0]) == 'a' && tolower(toValue[1]) == 'l' && tolower(toValue[2]) == 'l')
flag = false;
if (!flag) {//全部修改
while (!feof(tab[pos]->fp)) {
for (int i = 0; i < tab[pos]->type.size(); i++) {
string tmp = tab[pos]->type[i];
//cout << "tmp:" << tmp << endl;
if (tmp == "int") {
int x; fscanf(tab[pos]->fp, "%d", &x);
if (i == updataPos)
x = atoi(newValue.c_str());
fprintf(tmpfptr, "%d", x);
}
else if (tmp == "float") {
float x; fscanf(tab[pos]->fp, "%f", &x);
if (i == updataPos)
x = atof(newValue.c_str());
fprintf(tmpfptr, "%f", x);
}
else if (tmp == "double") {
double x; fscanf(tab[pos]->fp, "%lf", &x);
if (i == updataPos)
x = atof(newValue.c_str());
fprintf(tmpfptr, "%f ", x);
}
else if (tmp == "char") {
if (tab[pos]->size[i] == 1) {
char x; fscanf(tab[pos]->fp, "%c", &x);
if (i == updataPos)
x = newValue[0];
fprintf(tmpfptr, "%c", x);
}
else {
int cnt = tab[pos]->size[i];
char* x = new char[cnt];
fscanf(tab[pos]->fp, "%s", x);
if (i == updataPos) {
strcpy(x, newValue.c_str());
x[newValue.length()] = NULL;
}
fprintf(tmpfptr, "%s", x);
delete x;
}
}
if (i != tab[pos]->type.size() - 1)
fprintf(tmpfptr, "%c", ' ');
}
fprintf(tmpfptr, "%c", '\n');
}
}
else {//範圍內修改
while (!feof(tab[pos]->fp)) {
memset(sentence, 0, sizeof(sentence));
fgets(sentence, 1024, tab[pos]->fp);
stringstream myTmp(sentence);
string x;
for (int i = 0; i <= wherePos; i++)
myTmp >> x;
if (x == toValue) {
stringstream myTmp2(sentence);
string input;
input.clear();
for (int i = 0; i < tab[pos]->colName.size(); i++) {
myTmp2 >> x;
if (i == updataPos)
input += newValue;
else
input += x;
if (i != tab[pos]->colName.size() - 1)
input += " ";
else
input += "\n";
}
//cout << "input = " << input;
fputs(input.c_str(), tmpfptr);
}
else
fputs(sentence, tmpfptr);
}
}
fclose(tmpfptr);
fclose(tab[pos]->fp);
remove(tab[pos]->pathName.c_str());
if (0 == rename(pathName2.c_str(), tab[pos]->pathName.c_str()))
cout << "更新成功!" << endl;
else
cout << "更新失敗!" << endl;
}
void myDBMS::myQuery(string toColName, string tableName, string isWhere = "") {//查詢數據
if (!open) {
cout << "無選中數據庫!" << endl;
return;
}
int pos = inf;
for (int i = 0; i < tab.size(); i++)
if (tab[i]->name == tableName) {
pos = i; break;
}
if (pos == inf)
pos = posIsNos(tableName);
if (pos == -1)return;
tab[pos]->fp = fopen(tab[pos]->pathName.c_str(), "r");
char contant[1024];
//fscanf(tab[pos]->fp, "%s", contant);
fgets(contant, sizeof(contant), tab[pos]->fp);
if (isWhere == "") {//全輸出
int len = strlen(contant);
for (int i = 0; i < len; i++)
if (contant[i] == ';')
contant[i] = ' ';
stringstream ss(contant);
string x;
for (int i = 0; i < tab[pos]->size.size(); i++) {//先輸出colNames
int width = 15;
if (tab[pos]->size[i] != 1)
width = tab[pos]->size[i];
ss >> x;
cout << left << setw(width) << x;
ss >> x;
ss >> x;
}
cout << endl;
//fgets(contant, sizeof(contant), tab[pos]->fp);
while(!feof(tab[pos]->fp)) {
memset(contant, 0, sizeof(contant));
fgets(contant, sizeof(contant), tab[pos]->fp);
if (strlen(contant) == 0)break;
stringstream out(contant);
string x;
for (int i = 0; i < tab[pos]->type.size(); i++) {
out >> x;
int width = 15;
if (tab[pos]->size[i] != 1)
width = tab[pos]->size[i];
string tmp = tab[pos]->type[i];
if (tmp == "int")
cout << left << setw(width) << atoi(x.c_str());
else if (tmp == "float" || tmp == "double")
cout << left << setw(width) << atof(x.c_str());
else if (tmp == "char")
cout << left << setw(width) << x;
}
cout << endl;
}
}
else {
stringstream ss(isWhere);
int wherePos = inf, aimPos = inf;
string typeName, toValue, whr, deng;
ss >> whr >> typeName >> deng >> toValue;
for (int i = 0; i < tab[pos]->colName.size(); i++) //找到規定範圍colName下標
if (tab[pos]->colName[i] == typeName) {
wherePos = i;
break;
}
for (int i = 0; i < tab[pos]->colName.size(); i++) //找到規定範圍colName下標
if (tab[pos]->colName[i] == toColName) {
aimPos = i;
break;
}
while (!feof(tab[pos]->fp)) {
memset(contant, 0, sizeof(contant));
fgets(contant, sizeof(contant), tab[pos]->fp);
stringstream myTmp(contant);
string x, check, out;
for (int i = 0; i < tab[pos]->colName.size(); i++) {
myTmp >> x;
if (i == wherePos)check = x;
if (i == aimPos)out = x;
}
if (check == toValue) {
int width = 15;
if (tab[pos]->size[aimPos] != 1)
width = tab[pos]->size[aimPos];
string tmp = tab[pos]->type[aimPos];
if (tmp == "int")
cout << left << setw(width) << atoi(out.c_str()) << endl;
else if (tmp == "float")
cout << left << setw(width) << atof(out.c_str()) << endl;
else if (tmp == "double")
cout << left << setw(width) << atof(out.c_str()) << endl;
else if (tmp == "char")
cout << left << setw(width) << out << endl;
}
}
}
fclose(tab[pos]->fp);
}
int main(void) {
myDBMS db;
while (cin >> db.cmd) {
db.transfer();
//cout << "db.cmd = " << db.cmd << endl;
if (db.cmd == "exit")break;
if (db.cmd == "create") {
string name;
cin >> db.cmd >> name;
db.transfer();
//cout << "db.cmd:" << db.cmd << " name:" << name << endl;
if (db.cmd == "database")
db.myCreateDataBase(name);
else if (db.cmd == "table")
db.myCreateTable(name);
else cout << "命令語句有誤!" << endl;
}
else if (db.cmd == "drop") {
string name;
cin >> db.cmd >> name;
db.transfer();
if (db.cmd == "database")
db.myDropDataBase(name);
else if (db.cmd == "table")
db.myDropTable(name);
else cout << "命令語句有誤!" << endl;
}
else if (db.cmd == "open") {
string name;
cin >> db.cmd >> name;
db.openDataBase(name);
}
else if (db.cmd == "close") {
string name;
cin >> db.cmd >> name;
db.transfer();
if (db.cmd == "database")
db.closeDataBase();
else cout << "命令語句有誤!" << endl;
}
else if (db.cmd == "insert") {
//insert into 表名(field1,field2,…) values(value1,value2,…)"
string value, name;
cin >> db.cmd >> name >> value;
vector<string>colName;
int pos = name.find('(');
for (int i = 0; i < value.length(); i++)
if (value[i] == ',' || value[i] == '(' || value[i] == ')')
value[i] = ' ';
//cout << "value:" << value << endl;
db.myInsert(name.substr(0, pos), value);
}
else if (db.cmd == "delete") {
//delete from 表名 where 範圍
string name;
cin >> db.cmd >> name;
string isWhere;
getline(cin, isWhere);
db.myDelete(name, isWhere);
}
else if (db.cmd == "update") {
//update 列名 = 新值 from 表名 where 列名 = 值(值可爲all, 表全部範圍)
string toColName,deng, newValue, tableName, isWhere;
cin >> toColName >> deng >> newValue >> db.cmd >> tableName;
getline(cin, isWhere);
db.myUpdate(tableName, toColName, newValue, isWhere);
}
else if (db.cmd == "query") {
//"查看全表 : query all from 表名"
//"查詢單值 : query 列名 from 表名 where 列名 = 值(值可爲all,表全部範圍)"
string toColName, tableName;
cin >> toColName >> db.cmd >> tableName;
if (db.cmd.length() == 3 && tolower(db.cmd[0]) == 'a' && tolower(db.cmd[1]) == 'l' && tolower(db.cmd[2]) == 'l') {
db.myQuery(toColName, tableName);
}
else {
string isWhere;
getline(cin,isWhere);
db.myQuery(toColName, tableName, isWhere);
}
}
else {
string tmp;
getline(cin, tmp);
cout << "輸入命令錯誤,請檢查!" << endl;
}
}
return 0;
}