TrivialDB-miskcooC++ 編寫的 SQL 數(shù)據(jù)庫引擎
TrivialDB 是一個簡單的數(shù)據(jù)庫管理系統(tǒng),實現(xiàn)了大部分常見的 SQL 語句和類型。同時支持多表連接、復(fù)雜表達(dá)式運算、多主鍵約束、外鍵約束、CHECK 約束、UNIQUE 和 DEFAULT 約束、聚集查詢、利用 B+ 樹索引的查詢優(yōu)化,同時,支持任意長度的 VARCHAR 類型。
系統(tǒng)功能
數(shù)據(jù)類型
數(shù)據(jù)庫支持的基本類型有:
- 整型(INT)
- 浮點型(FLOAT)
- 字符串型(VARCHAR)
- 日期型(DATE),日期格式
YYYY-MM-dd
日期類型的字面值和字符串相同,在實現(xiàn)中如果必要可以轉(zhuǎn)換為字符串。
SQL語句
支持的 SQL 語句一共有如下幾種
- 插入語句:
INSERT INTO ... VALUES ... - 刪除語句:
DELETE FROM ... WHERE ... - 查詢語句:
SELECT ... FROM ... WHERE ... - 更新語句:
UPDATE ... SET ... WHERE ... - 創(chuàng)建數(shù)據(jù)庫:
CREATE DATABASE ... - 刪除數(shù)據(jù)庫:
DROP DATABASE ... - 切換數(shù)據(jù)庫:
USE ... - 顯示數(shù)據(jù)庫信息:
SHOW DATABASE ... - 創(chuàng)建表:
CREATE TABLE ... - 刪除表:
DROP TABLE ... - 顯示表信息:
SHOW TABLE ... - 創(chuàng)建索引:
CREATE INDEX ... - 刪除索引:
DROP INDEX ...
復(fù)雜表達(dá)式處理
表達(dá)式大致可以分為兩種:算術(shù)表達(dá)式和條件表達(dá)式。由于采用 Bison 進(jìn)行解析,可以支持任意深度嵌套的復(fù)雜表達(dá)式。TrivialDB 支持的基本運算主要如下
- 四則運算,針對整數(shù)和浮點數(shù)進(jìn)行。
- 比較運算符,即 <=、<、=、>、>= 與 <>。
- 模糊匹配運算符,即 LIKE,其實現(xiàn)采用 C++11 的正則表達(dá)式庫。
- 范圍匹配運算符,即 IN,可以在表的 CHECK 約束中以及 WHERE 子句中使用。
- 空值判定運算符,即 IS NULL 和 IS NOT NULL 兩種。
- 邏輯運算,包含 NOT、AND 和 OR 三種。
以下是一些復(fù)雜表達(dá)式運算的例子
UPDATE customer SET age = age + 1 WHERE age < 18 AND gender = 'F';
SELECT * FROM customer WHERE name LIKE 'John %son';
SELECT * FROM students WHERE grades IN ('A', 'B', 'C');
SELECT * FROM students WHERE name IS NOT NULL;
聚集查詢
實現(xiàn)了五種聚集查詢函數(shù) COUNT、SUM、AVG、MIN 和 MAX。其中 COUNT 不支持 DISTINCT 關(guān)鍵字。例如
SELECT COUNT(*) FROM customer WHERE age > 18; SELECT AVG(age) FROM customer WHERE age <= 18;
屬性完整性約束
支持多種屬性完整性約束,分別是
- 主鍵約束。一個表可以有多個列聯(lián)合起來作為主鍵,只有在所有主鍵都相同時才認(rèn)為兩條記錄有沖突,即這種情況下主鍵是一個元組。
- 外鍵約束,每個域都可以有外鍵約束,引用另外一個表的主鍵。
- UNIQUE 約束,該約束限制某一列的值不能重復(fù)。
- NOT NULL 約束,該約束限制某一列不能有空值。
- DEFAULT 約束,該約束可以在 INSERT 語句不指定值是給某列賦予一個默認(rèn)值。
- CHECK 約束,該約束可以對表中元素的值添加條件表達(dá)式的檢查。
下面是一個簡單的例子,注意如果在多個列都指定了 PRIMARY KEY,那么就認(rèn)為主鍵是一個元組,而不是有多個主鍵。例如 Infos 表的主鍵為(PersonID, InfoID)。
CREATE TABLE Persons (
PersonID int PRIMARY KEY NOT NULL,
Name varchar(20),
Age int DEFAULT 1,
Gender varchar(1),
CHECK (Age >= 1 AND Age <= 100),
CHECK (Gender IN ('F', 'M'))
);
CREATE TABLE Infos (
PersonID int PRIMARY KEY,
InfoID int PRIMARY KEY,
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);
多表連接查詢
在 SELECT 語句中,我們支持任意多表的連接操作,例如
SELECT * FROM A, B, C WHERE A.ID = B.ID AND C.Name = A.Name
并且,對于多個表的連接中形如 A.Col1 = B.Col2 的條件,那么如果這兩個列的某一個擁有索引,會利用索引進(jìn)行查詢優(yōu)化。例如如下查詢就可以優(yōu)化
SELECT * FROM Persons, Infos WHERE Persons.PersonID = Infos.PersonID; SELECT * FROM Persons, Infos, Datas WHERE Persons.PersonID = Infos.PersonID AND Datas.N IS NOT NULL; SELECT * FROM Persons, Infos, Datas WHERE Persons.PersonID = Infos.PersonID AND Datas.ID = Infos.PersonID;
具體的優(yōu)化方法以及何種查詢可以優(yōu)化見文檔中"查詢優(yōu)化"部分。
表別名
我們在多表連接查詢時支持通過別名(alias)的方式對一個表進(jìn)行連接,例如
SELECT * FROM Persons AS P1, Persons AS P2 WHERE P1.PersonID = P2.PersonID;
