c++实现迷你数据库(miniSQL)DDL部分的功能模拟

引言

这个项目的来源是由于在电科参加了一门CPP的选修课,老师的期末大作业要求是设计一个mini数据库,我作为小组成员,主要任务是负责DDL部分的代码书写,详细任务如下:

对数据库的操作:

  • 创建库(createDatabase)
  • 删除库(dropDatabase)
  • 切换库(useDatabase)
  • 显示库(showDatabases)

对表的操作:

  • 创建表(createTable)
  • 删除表(dropTable)
  • 显示表头信息(descTable)
  • 显示表(showTables)

故写此博客以做学习记录,由于cpp和数据库相关知识都是本学期才开始了解,如有谬误或不足欢迎批评指正。

学习历程

了解数据库

由于答主此时(2023.11)正处大二上学期,还未进行数据库相关知识的学习,故我先是简单了解了一下数据库的相关知识,掌握了我需要编写的几个基本指令的使用效果:

关于库的操作

create database;

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

drop database;

mysql> drop database db1;
Query OK, 1 row affected (0.05 sec)

 show databases;

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| db1                |
| db2                |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.02 sec)
use database;
mysql> use test;
Database changed

关于表的操作

create table;

mysql> create table tb1(
    -> id int,
    -> name varchar(10)
    -> );
Query OK, 0 rows affected (0.02 sec)

desc table;

mysql> desc tb1;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

show tables;

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| tb1            |
+----------------+
1 row in set (0.01 sec)

drop table

mysql> drop table tb1;
Query OK, 0 rows affected (0.01 sec)

下面将该期间查阅过的资料分享给大家:

MySQL 有这一篇就够(呕心狂敲37k字,只为博君一点赞!!!)_mysql 有这一篇就够(呕心狂敲37k字,只为博君一点赞!!!)-CSDN博客

Mac安装MySQL详细教程_mac mysql安装_普通网友的博客-CSDN博客

代码书写

大致了解数据库的基本使用后,我开始了代码书写

分析

总的来说,我的任务不算复杂,只需要将相关的函数用cpp实现并封装好,交给负责前端的同学调用即可。故我将所有函数的返回类型都设置成了bool型。

代码实现

关于库的操作

头文件
// Database.h

#ifndef MINISQL_DATABASE_H
#define MINISQL_DATABASE_H

#include <iostream>
#include <sys/stat.h>
#include <cerrno>
#include <cstring>  // 用于 strerror 函数
#include <unistd.h>  // 用于 rmdir 函数
#include <string>
#include <filesystem>
#include <vector>
using namespace std;

class Database {

public:
    Database();
    ~Database();

    static string currentDbFilename;//标明当前所在的databaseFile名,建议初始化时将其置为空
    static string currentDbname;//标明当前所在的database名,建议初始化时将其置为空
    static vector<pair<string,vector<pair<string,vector<pair<string, string>>>>>> miniSqlVector;
    bool createDatabase(const string& dbName);
    bool dropDatabase(const string& dbName);
    bool useDatabase(const string& dbName);
    bool isDirectoryExists(const string& path);
    bool showDatabases(vector<string> &databaseVector);
};



#endif // MINISQL_DATABASE_H
创建库
/**
 * @brief 创建数据库
 * @param 数据库的名称
 * @return 成功则为true,失败则为false
 */
bool Database:: createDatabase(const string& dbName)
{
    if(dbName.empty())
    {
        return false;
    }
    // 拼接数据库目录路径
    string dbPath = fatherPath + dbName;  // 注意配置说明 这里的路径一定要正确

    // 创建数据库目录
    int status = mkdir(dbPath.c_str(), 0755);//后面的参数表示所有人都有读、写、执行权限

    if (status == 0) {
        vector<pair<string,vector<pair<string, string>>>> dbVector = {};
        miniSqlVector.push_back(make_pair(dbName, dbVector));
        return true;
    } else {
        cerr << "Error creating directory: " << strerror(errno) << endl;//查看错误码
        return false;
    }
}
删除库
/**
 * @brief 删除数据库
 * @param 数据库的名称
 * @return 成功则为true,失败则为false
 */

bool Database:: dropDatabase(const string& dbName)
{
    if(dbName.empty())
    {
        return false;
    }
    string dbPath = fatherPath + dbName;  // 注意配置说明 这里的路径一定要正确
    int status = rmdir(dbPath.c_str());

    if (status == 0) {
        return true;
    } else {
        cerr << "Error removing directory: " << strerror(errno) << endl;
        return false;
    }

}
切换库
/**
 * @brief 切换数据库
 * @param 数据库的名称
 * @return 成功则为true,失败则为false
 */
bool Database:: useDatabase(const string& dbName)
{
    if(dbName.empty())
    {
        return false;
    }
    string dbPath = fatherPath + dbName + '/';  // 注意配置说明 这里的路径一定要正确
    if(!isDirectoryExists(dbPath))
    {
        return false;
    }
    Database::currentDbname = dbName;
    Database::currentDbFilename = dbPath;
    return true;
}

/**
 * @brief 查找数据库
 * @param 数据库的路径
 * @return 成功则为true,失败则为false
 */
namespace fs = filesystem;
bool Database:: isDirectoryExists(const string& path) {
    return fs::is_directory(path);
}
显示库
/**
 * @brief 显示数据库
 * @param 存放所有库名称的vector
 * @return 成功则为true,失败则为false
 */

bool Database::showDatabases(vector<string>&databaseVector)
{
    for (int i = 0; i < Database::miniSqlVector.size(); ++i) {
        databaseVector.push_back(Database::miniSqlVector[i].first);
    }
    return true;
}
database类全部代码 

#include "Database.h"


Database::Database() = default;
Database::~Database() = default;

string fatherPath = "../src/data/";//此处声明要存放database的父文件夹地址
string Database::currentDbname;  // 静态变量的实际的定义,用于标记当前所在的库名
string Database::currentDbFilename;  // 静态变量的实际的定义,用于标记当前所在库的文件路径
vector<pair<string,vector<pair<string,vector<pair<string, string>>>>>> Database:: miniSqlVector;//静态变量的实际定义

/**
 * @brief 创建数据库
 * @param 数据库的名称
 * @return 成功则为true,失败则为false
 */
bool Database:: createDatabase(const string& dbName)
{
    if(dbName.empty())
    {
        return false;
    }
    // 拼接数据库目录路径
    string dbPath = fatherPath + dbName;  // 注意配置说明 这里的路径一定要正确

    // 创建数据库目录
    int status = mkdir(dbPath.c_str(), 0755);//后面的参数表示所有人都有读、写、执行权限

    if (status == 0) {
        vector<pair<string,vector<pair<string, string>>>> dbVector = {};
        miniSqlVector.push_back(make_pair(dbName, dbVector));
        return true;
    } else {
        cerr << "Error creating directory: " << strerror(errno) << endl;//查看错误码
        return false;
    }
}

/**
 * @brief 删除数据库
 * @param 数据库的名称
 * @return 成功则为true,失败则为false
 */


bool Database:: dropDatabase(const string& dbName)
{
    if(dbName.empty())
    {
        return false;
    }
    string dbPath = fatherPath + dbName;  // 注意配置说明 这里的路径一定要正确
    int status = rmdir(dbPath.c_str());

    if (status == 0) {
        return true;
    } else {
        cerr << "Error removing directory: " << strerror(errno) << endl;
        return false;
    }

}

/**
 * @brief 切换数据库
 * @param 数据库的名称
 * @return 成功则为true,失败则为false
 */
bool Database:: useDatabase(const string& dbName)
{
    if(dbName.empty())
    {
        return false;
    }
    string dbPath = fatherPath + dbName + '/';  // 注意配置说明 这里的路径一定要正确
    if(!isDirectoryExists(dbPath))
    {
        return false;
    }
    Database::currentDbname = dbName;
    Database::currentDbFilename = dbPath;
    return true;
}

/**
 * @brief 查找数据库
 * @param 数据库的路径
 * @return 成功则为true,失败则为false
 */
namespace fs = filesystem;
bool Database:: isDirectoryExists(const string& path) {
    return fs::is_directory(path);
}

/**
 * @brief 显示数据库
 * @param 存放所有库名称的vector
 * @return 成功则为true,失败则为false
 */

bool Database::showDatabases(vector<string>&databaseVector)
{
    for (int i = 0; i < Database::miniSqlVector.size(); ++i) {
        databaseVector.push_back(Database::miniSqlVector[i].first);
    }
    return true;
}

关于表的操作

头文件


#ifndef MINISQL_TABLE_H
#define MINISQL_TABLE_H

#include <vector>
#include <iostream>
#include <sys/stat.h>
#include <cerrno>
#include <cstring>  // 用于 strerror 函数
#include <unistd.h>  // 用于 rmdir 函数
#include <string>
#include <filesystem>
#include <iostream>
#include <fstream>
#include <map>
using namespace std;

using InnerPair = pair<string, vector<pair<string, string>>>;
using OuterPair = pair<string, vector<InnerPair>>;
using DatabaseVector = vector<OuterPair>;

class Table {
public:
    Table();
    ~Table();
    bool createTable(const std::string& tableName, const std::vector<std::pair<std::string, std::string>>& columns);
    bool dropTable(const std::string &tableName);
    int creatFile_txt(const std::string& fileName);
    int dropTxt(const std::string filename);
    OuterPair findMatchingPair(const DatabaseVector& miniSqlVector, const string& dbName);
    vector<pair<string, string>> findMatchingInnerVector(const string &inputString);
    bool descTable(multimap<string, string> &tableHeadMap, const string &tbNeme);

    bool showTables(vector<string> &tableVector);
};


#endif //MINISQL_TABLE_H
创建表
/**
 * @brief 创建表
 * @param 表的名称
 * @param 一个vector数组的引用,数组单元内容为两个string的pair,这里需要前端将类似于
 * create table tb1(
    -> id int,
    -> name char,
    -> age int
    -> );
    这样的语句解析为{{"id","int"},{"name","char"},{"age","int"}}这样的数组
 * @return 成功则为true,失败则为false
 */
bool Table::createTable(const string& tableName, const vector<pair<string, string>>& columns)
{
    string currentDbFilename = Database::currentDbFilename;
    string currentDbname = Database::currentDbname;
    vector<pair<string, vector<pair<string, vector<pair<string, string>>>>>>& miniSqlVector = Database::miniSqlVector;

    if(currentDbFilename == "")
    {
        return false;
    }
    if(tableName.empty() || columns.empty())
    {
        return false;
    } else {
        string tbPath = currentDbFilename + tableName;  // 注意配置说明 这里的路径一定要正确
        // 创建表目录
        int status = creatFile_txt(tbPath);//后面的参数表示所有人都有读、写、执行权限

        if (status == 0) {
            // 要查找的数据库名称
            string dbNameToFind = currentDbname;
            // 查找匹配的最外层的 pair
            OuterPair matchingPair = findMatchingPair(miniSqlVector, dbNameToFind);
            matchingPair.second.push_back(make_pair(tableName,columns));
            miniSqlVector[miniSqlVector.size()-1].second = matchingPair.second;
            return true;
        } else {
            cerr << "Error creating table: " << strerror(errno) << endl;//查看错误码
            return false;
        }
    }
}


/**
 * @brief 根据database的name找到minisql中当前的database
 * @param minisql
 * @param database名
 * @return 成功则为true,失败则为false
 */
OuterPair Table::findMatchingPair(const DatabaseVector& miniSqlVector, const string& dbName) {
    auto it = find_if(miniSqlVector.begin(), miniSqlVector.end(),
                      [&dbName](const OuterPair& entry) { return entry.first == dbName; });

    if (it != miniSqlVector.end()) {
        return *it;
    } else {
        // 如果没有找到匹配项,可以返回一个默认构造的 pair
        return make_pair("", vector<InnerPair>());
    }
}

/**
 * @brief 封装了一个创建.txt文件的函数
 * @param 文件名称
 * @return 成功则为true,失败则为false
 */
int Table::creatFile_txt(const string& fileName){
    // 创建 ofstream 对象并打开文件
    ofstream outFile(fileName);

    // 检查文件是否成功打开
    if (!outFile.is_open()) {
        std::cerr << "无法打开文件: " << fileName << std::endl;
        return -1; // 返回非零表示出现错误
    }

    // 向文件写入内容
//    outFile << "Hello, World!" << std::endl;

    // 关闭文件
    outFile.close();

//    std::cout << "文件创建成功: " << fileName << std::endl;
    return 0;
}
删除表
/**
 * @brief 删除表
 * @param 表的名称
 * @return 成功则为true,失败则为false
 */
bool Table::dropTable(const string& tableName)
{
    if(tableName.empty())
    {
        return false;
    }
    string currentDbFilename = Database::currentDbFilename;
    string tbPath = currentDbFilename + tableName;  // 注意配置说明 这里的路径一定要正确
    int status = dropTxt(tbPath);

    if (status == 0) {
        return true;
    } else {
        cerr << "Error removing table: " << strerror(errno) << endl;
        return false;
    }
}

/**
 * @brief 删除txt文件的函数
 * @param txt文件的名称
 * @return 成功则为true,失败则为false
 */
int Table::dropTxt(const string filename) {

    // 删除文件
    if (std::remove(filename.c_str()) != 0) {
        std::cerr << "无法删除文件: " << filename << std::endl;
        return 1; // 返回非零表示出现错误
    }


    return 0;
}
显示表头
/**
 * @brief 根据table名显示表头及其数据类型
 * @param 存放表头信息的mutimap(一定注意是muti),后续操作针对该map即可
 * @param table名
 * @return 成功则为true,失败则为false
 */

bool Table::descTable( multimap<string,string> &tableHeadMap,const string& tbNeme)//必须用mutimap,map的键不允许重复
{

    vector<pair<string, string>> vectorFound = findMatchingInnerVector(tbNeme);
    if(vectorFound.size() == 0)
    {
        return false;
    } else{
        for (int i = 0; i < vectorFound.size(); ++i) {
            tableHeadMap.insert(make_pair(vectorFound[i].first,vectorFound[i].second));
        }
        return true;
    }

}
/**
 * @brief 根据table的name找到存放表头信息的vector
 * @param table名
 * @return 存放表头信息的vector
 */
vector<pair<string, string>>Table:: findMatchingInnerVector(const string& inputString) {
    string currentDbname = Database::currentDbname;
    string dbNameToFind = currentDbname;
    // 查找匹配的最外层的 pair
    OuterPair matchingPair = findMatchingPair(Database::miniSqlVector, dbNameToFind);
    for (const auto& outerPair : matchingPair.second) {
        if (outerPair.first == inputString) {
            return outerPair.second;
        }
    }
    // 如果没有找到匹配项,返回一个空的 vector
    return vector<pair<string, string>>();
}
显示所有表
/**
 * @brief 显示表
 * @param 存放所有表名称的vector
 * @return 成功则为true,失败则为false
 */
bool Table::showTables(vector<string>&tableVector)
{
    OuterPair outerPair = findMatchingPair(Database::miniSqlVector,Database::currentDbname);
    for (int i = 0; i < outerPair.second.size(); ++i) {
        tableVector.push_back(outerPair.second[i].first);
    }
    return true;
}
table类全部代码

#include "Table.h"
#include "../database/Database.h"

Table::Table() = default;
Table::~Table() = default;
// 假设这是你的数据库结构

/**
 * @brief 创建表
 * @param 表的名称
 * @param 一个vector数组的引用,数组单元内容为两个string的pair,这里需要前端将类似于
 * create table tb1(
    -> id int,
    -> name char,
    -> age int
    -> );
    这样的语句解析为{{"id","int"},{"name","char"},{"age","int"}}这样的数组
 * @return 成功则为true,失败则为false
 */
bool Table::createTable(const string& tableName, const vector<pair<string, string>>& columns)
{
    string currentDbFilename = Database::currentDbFilename;
    string currentDbname = Database::currentDbname;
    vector<pair<string, vector<pair<string, vector<pair<string, string>>>>>>& miniSqlVector = Database::miniSqlVector;

    if(currentDbFilename == "")
    {
        return false;
    }
    if(tableName.empty() || columns.empty())
    {
        return false;
    } else {
        string tbPath = currentDbFilename + tableName;  // 注意配置说明 这里的路径一定要正确
        // 创建表目录
        int status = creatFile_txt(tbPath);//后面的参数表示所有人都有读、写、执行权限

        if (status == 0) {
            // 要查找的数据库名称
            string dbNameToFind = currentDbname;
            // 查找匹配的最外层的 pair
            OuterPair matchingPair = findMatchingPair(miniSqlVector, dbNameToFind);
            matchingPair.second.push_back(make_pair(tableName,columns));

            miniSqlVector[miniSqlVector.size()-1].second = matchingPair.second;

            return true;
        } else {
            cerr << "Error creating table: " << strerror(errno) << endl;//查看错误码
            return false;
        }
    }
}

//抄的gpt

/**
 * @brief 根据database的name找到minisql中当前的database
 * @param minisql
 * @param database名
 * @return 成功则为true,失败则为false
 */
// 查找并返回匹配的最外层的 pair
OuterPair Table::findMatchingPair(const DatabaseVector& miniSqlVector, const string& dbName) {
    auto it = find_if(miniSqlVector.begin(), miniSqlVector.end(),
                      [&dbName](const OuterPair& entry) { return entry.first == dbName; });

    if (it != miniSqlVector.end()) {
        return *it;
    } else {
        // 如果没有找到匹配项,可以返回一个默认构造的 pair
        return make_pair("", vector<InnerPair>());
    }
}

/**
 * @brief 封装了一个创建.txt文件的函数
 * @param 文件名称
 * @return 成功则为true,失败则为false
 */
int Table::creatFile_txt(const string& fileName){
    // 创建 ofstream 对象并打开文件
    ofstream outFile(fileName);

    // 检查文件是否成功打开
    if (!outFile.is_open()) {
        std::cerr << "无法打开文件: " << fileName << std::endl;
        return -1; // 返回非零表示出现错误
    }

    return 0;
}


/**
 * @brief 删除表
 * @param 表的名称
 * @return 成功则为true,失败则为false
 */
bool Table::dropTable(const string& tableName)
{
    if(tableName.empty())
    {
        return false;
    }
    string currentDbFilename = Database::currentDbFilename;
    string tbPath = currentDbFilename + tableName;  // 注意配置说明 这里的路径一定要正确
    int status = dropTxt(tbPath);

    if (status == 0) {
        return true;
    } else {
        cerr << "Error removing table: " << strerror(errno) << endl;
        return false;
    }
}

/**
 * @brief 删除txt文件的函数
 * @param txt文件的名称
 * @return 成功则为true,失败则为false
 */
int Table::dropTxt(const string filename) {

    // 删除文件
    if (std::remove(filename.c_str()) != 0) {
        std::cerr << "无法删除文件: " << filename << std::endl;
        return 1; // 返回非零表示出现错误
    }


    return 0;
}

/**
 * @brief 根据table名显示表头及其数据类型
 * @param 存放表头信息的mutimap(一定注意是muti),后续操作针对该map即可
 * @param table名
 * @return 成功则为true,失败则为false
 */

bool Table::descTable( multimap<string,string> &tableHeadMap,const string& tbNeme)//必须用mutimap,map的键不允许重复
{

    vector<pair<string, string>> vectorFound = findMatchingInnerVector(tbNeme);
    if(vectorFound.size() == 0)
    {
        return false;
    } else{
        for (int i = 0; i < vectorFound.size(); ++i) {
            tableHeadMap.insert(make_pair(vectorFound[i].first,vectorFound[i].second));
        }
        return true;
    }

}
/**
 * @brief 根据table的name找到存放表头信息的vector
 * @param table名
 * @return 存放表头信息的vector
 */
vector<pair<string, string>>Table:: findMatchingInnerVector(const string& inputString) {
    string currentDbname = Database::currentDbname;
    string dbNameToFind = currentDbname;
    // 查找匹配的最外层的 pair
    OuterPair matchingPair = findMatchingPair(Database::miniSqlVector, dbNameToFind);
    for (const auto& outerPair : matchingPair.second) {
        if (outerPair.first == inputString) {
            return outerPair.second;
        }
    }
    // 如果没有找到匹配项,返回一个空的 vector
    return vector<pair<string, string>>();
}

/**
 * @brief 显示表
 * @param 存放所有表名称的vector
 * @return 成功则为true,失败则为false
 */
bool Table::showTables(vector<string>&tableVector)
{
    OuterPair outerPair = findMatchingPair(Database::miniSqlVector,Database::currentDbname);
    for (int i = 0; i < outerPair.second.size(); ++i) {
        tableVector.push_back(outerPair.second[i].first);
    }
    return true;
}

附:

附上文件目录结构,方便各位对路径上的理解

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
【SA默认密码:593106】 使用环境: Windows OS(vista/win7/win8/xp/2000/2003) 不支持Windows 9x 软件功能: 1、MSSQL2000数据库服务开启、关闭控制; 2、基本数据库操作(改密码、数据库新建、删除、分离、附加、备份、恢复); 3、日志和连接信息,简易防火墙,自启动设置,计划任务(自动备份与执行)等。 注意事项: 1、本软件必须定义实例名和端口,本软件中的数据库无目录限制; 2、新建、附加和恢复数据库,这几项操作会将数据库保存或转移到本软件所在目录的DATA目录下,同时也会将数据库文件的物理文件名和逻辑名进行调整; 3、删除、分离数据库时,会自动清除目标数据库的用户连接; 4、防火墙仅仅是实现根据连入PC的网卡地址进行连接断开的操作,没啥用^_^; 5、计划任务只有在勾选时才会写入配置文件,在开启服务后才会读取并开启任务,如果计划任务中定义的数据库被删除或分离,任务会自动取消; 6、如果需要使用默认实例,请千万不要发布到有安装MSSQL且使用默认实例的机子上去,会造成目标机子上的MSSQL无法正常使用; 7、管理员帐号SA的默认密码是593106,第一次解锁时请输入这一密码,然后自行在数据库页修改密码。 使用方法: 运行程序》设置实例名》设置端口》开启。 如果需要让程序自动开启服务,请勾选自动开启,开机启动表示随OS启动。 与您的软件一起分发的方法: 1、运行本程序; 2、勾选 自动开启、开机启动和服务守护; 3、将本软件及附属文件一起打包进您的安装程序中。 您也可以将您需要分发的软件所用数据库直接附加或恢复到本软件中,从而省去恢复数据库的操作。 关于vista/win7/win8中UAC未禁用时无法开机自启动的情况,请按以下步骤解决: 1、运行本程序,设置好 实例名称和服务端口,勾选自动开启和服务守护; 2、打开 开始》控制面板》系统和安全》计划任务; 3、创建任务》常规》输入名称》勾选下面的 使用最高权限运行; 触发器》开始任务 选择 登录时》设置 选择 所有用户》高级设置 勾选 启用; 操作》操作 选择 启动程序》程序或脚本 选择 迷你SQL2000目录下的sql2k.exe; 4、以上设置完成后,点击 确定 进行保存,然后就可以重启win7进行测试了。 分发时请不要包含本说明文件,增加您自定义的说明文本即可。 更新日志: *修正 +增加 -去除 ^调整 1.2.6 *还原数据库时,修正输入库名时点取消后没有中止还原等错误; +查询分析器添加语法高亮支持; *修正关闭服务时,有机率卡顿的现象,进行了优化处理; +在操作系统关闭时,自动停止服务,防止数据丢失。 1.2.5 +数据库页增加查看我的表功能菜单项,可管理视图、存储过程及自定义函数和查看表结构等; ^部分菜单及按钮增加图标,增加美观度; +内存管理页增加AWE开关,以解决部分电脑内存不足造成运行缓慢的问题,AWE功能也占内存。 1.2.4 ^选择开机启动时,会自动删除与软件关联的注册表项,防止变更实例名造成注册表残留,对于已登记开机启动,又直接删除了软件的,请手工删除注册表Run项中的残留; *修正部分win7系统下无法正常解锁的问题(系统无法访问127.0.0.1造成); *修正部分文字描述内容错误(漏字或多打字等)。 1.2.3 +数据库页面,集成外部工具“查询分析器”与“事件探查器”,系SQL自带程序,方便使用; -删除内置“查询分析”功能页; ^数据库页面,密码修改,允许任意字符,不再限制只能为0~9a~z了,但不允许为空; ^数据库内核升级至8.00.2305,开启AWE,支持大内存(超2G)及修复漏洞; +增加SQL Tips页,记录一些常用的SQL语句,方便查阅; ^标题栏解锁界面和密码修改页面进行调整,增加多语言支持。 1.2.2 *附加数据库时,修正输入库名时点取消后没有中止附加等错误; +增加面板锁,点击左上角的金锁,输入SA用户密码,输入正确则打开面板,否则隐藏面板,不限制开、关服务; +数据库页面,右键菜单增加打开文件目录,方便用户操作; +增加内存管理页,控制SQL Server内存占用,与企业管理器相同。 1.2.1 ^未开启服务时,关闭窗口会退出程序,开启服务时,关窗窗口则是隐藏; *附加数据库时,修正目标目录与源目录相同时无法附加的问题。 1.2.0 +增加托盘区菜单项“重启”,方便重启SQL服务; ^附加数据库文件时,将移动改为复制,原文件不会被删除; +计划任务在备份数据库后,自动清除旧备份,只保留最后5个备份(按文件,不按时间); *修正计划任务无法正确执行的问题,由皮肤引起的。 1.1.9 +增加win8的支持,增加皮肤以美化界面; +增加查询分析器,方便使用SQL操作数据库; +增加简体、繁体语言切换,方便港台及深圳用户使用。 1.1.8 ^计划任务中执行SQL语句变更为执行SQL脚本文件,支持GO分隔,方便执行复杂任务。 1.1.7 +配置文件中增加AppTitle字符串项,如果有输入内容,则在启动时会以该项的值为窗口标题;繁体用户请将配置文件保存为Unicode格式; *修正没有清除默认实例注册表项的问题。 1.1.6 +控制程序增加对指定消息的处理,方便用户控制迷你数据库,详见包内的“控制demo”例程。 1.1.5 +同目录下只允许启动一个EXE,互斥对象,不影响启用多实例; ^原“恢复”变更为“还原”,还原时显示默认的数据库名称; +显示数据库状态,在数据库页的右键菜单项上增加修复置疑和联机数据库功能项; +勾选默认实例时,先进行检测,如安装了MSSQL服务,则禁止勾选默认实例; +计划任务,备份计划处增加选择目录的图片按钮,方便操作。 1.1.4 ^调整关闭服务过程,等待所有SQL任务执行完毕后才会关闭服务,确保用户操的作完整性; +增加服务进程窗口的显示选项,可即可查看服务日志; ^优化启动时的部分设置,提高效率,减少资源占用。 1.1.3 *修正内存释放问题,旧版会造成内存递增。 1.1.2 ^计划任务、执行脚本、恢复和备份数据库时,不限制指令执行等待时间,以免超时; *修正部分文字内容的显示错误; +增加按计算机名和IP地址访问实例的参考连接字提示; *修正启动时的一个参数错误,解决日志勾选切换造成启动失败的问题。 1.1.1 ^优化提示信息,更加人性化,执行脚本时会显示正在执行第几个脚本文件; ^优化启动服务的代码,默认实例或指定实例运行时更加稳定; ^优化数据库页右键菜单显示,允许对系统库进行操作。 1.1.0 +增加同个目录只允许运行一个实例的自动处理; *修正开启服务过程中碰到异常时,没有修改实例状态的错误; +支持强制使用默认实例,也就是使用1433端口和空实例名。 ps:升级了tools目录下的makesql和runsql,均支持unicode,与MSSQL配合使用效果非常 不错的(makesql在2ccc.com上有源码可下载,增加表内容较多时自动添加GO分隔, 以免执行时报内存不足的错误) 1.0.9 *修正被部分杀软报毒的问题; *修正停止服务时没有清除标识,造成提示无法运行相同实例的错误。 1.0.8 ^调整窗口关闭事件,用户必须用托盘区的右键菜单退出程序; +加入vista/win7的UAC签名,运行程序时会自动请求提权; +开启服务前自动验证下有没有相同的实例在运行。 1.0.7 +数据库页增加收缩数据库和清除日志文件内容的右键功能项; +增加版本号显示,优化部分代码; +增加启动前自检,缺少文件时会有提示。 1.0.6 *修正附加和恢复数据库时,逻辑名处理不正确的问题。 1.0.5 ^备份数据库时使用完整备份,不再自动使用增量备份; *修正部分错误,优化代码以提高处理速度。 1.0.4 +增加服务守护,在服务被异常终止时,自动开启服务。 1.0.3 *连接与防火墙,防火墙列表增加与减少时的空数据项错误; *修正托盘区无法激活主窗口的问题; +增加多实例启动支持(复制多份,设置不同的实例名和端口即可启动多个实例); ^运行日志调整为50行滚动提示,供参考。 1.0.2 *附加数据库,日志文件路径未修改的错误; ^数据库列表,数据和日志文件的路径显示为绝对路径; +计划任务,增加自动备份和执行SQL语句的功能
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值