基本 SQL 之資料庫及表管理

YangAM發表於2019-02-19

上篇文章,我們基於『資料庫』做了一個巨集觀上的介紹,你應當瞭解到資料庫是在何種背景下,為了解決什麼樣的問題而誕生的,以及在具體實現下又可以劃分哪些中型別。

非關係型資料庫的種類很多,我們會在後續的篇章中進行介紹,資料庫這塊我們還是以目前當下主流的關係型資料庫進行學習。

SQL 是什麼

我們看看

SQL(結構化查詢語言)是一種特定目的程式語言,用於管理關聯式資料庫管理系統(RDBMS),或在關係流資料管理系統(RDSMS)中進行流處理

簡而言之,SQL 是一門程式語言,它很特殊,它是一門幫助我們管理資料的標準語言

為什麼強調標準語言?

關係型資料的主要三大實現者分別是,Mysql,MS SQLServer,Oracle。

它們實現資料儲存的底層引擎或許不同,但提供出來管理資料的程式語言必須遵循 SQL 規範,但可以定製新增屬於自己的額外語法,這些額外的、SQL 之外的語法又被稱作它們各自的『SQL方言』。

記得遇到過很多新手,拿著 SqlServer 的方言跑到 Mysql 裡去執行,怎麼都報錯,怎麼都解決不了。其實還是沒了解到這一層。

資料庫管理

一個資料庫系統裡是可以同時存在多個資料庫的,也就是說一個資料庫引擎可以服務多個資料庫。

當你成功登陸資料庫系統之後,你可以通過這麼一個命令檢視系統中存在的資料庫集合。

SHOW DATABASES;

除此之外,你也可以建立資料庫,使用以下這個命令。

CREATE DATABASE [DATABASENAEM];

如果你想要刪除某個資料庫:

DROP DATABASE [DATABASENAEM];

如果你需要選中某個資料庫,這裡說明一下,資料庫由多張資料表構成,如果你想要運算元據表,你就必須先選中某個資料庫,不然系統怎麼知道你這一頓猛如虎的操作是基於的哪個資料庫下的表呢。

USE[DATABASENAEM];

資料庫的管理其實沒什麼太複雜的,它就像一個容器一樣,建立後就意味著佔有了一塊磁碟空間,具體的資料儲存還是在表結構中,所以接下來我們來看看資料庫表管理情況。

表管理

關係型資料庫中對於資料的儲存採用一種符合人的思維邏輯的結構進行儲存,那就是表格結構。

表格是一個二維的結構,有行和列,我們管一行資料叫做『一條記錄』或是『一條資料』,每一列都是一條資料的一部分,我們管某一列的資料叫做『欄位』,在資料庫中它們可以具有不同的資料型別。

SQL 規範了以下一些通用的資料型別:

image

image

但是實際上,SQLServer,Oracle,MySQL 等資料庫的具體實現上也大多都支援這些型別,只不過在不同的資料庫中,同一種資料型別可能有不同的名稱。

舉個例子吧,資料型別 Integer,在 Oracle 裡使用 Number 描述,SQLServer 裡使用 int 來描述,而 MySQL 裡既可以使用 int 也可以使用 Integer 進行描述。

所以,在我看來,既然大家都不是那麼遵守規範,那麼就沒必要謹記規範,你用到哪個資料庫,你去了解他的資料型別就是了

我以 MySQL 來說,他主要的資料型別大致可以分為三類,Text(文字)、Number(數字)和 Date/Time(日期/時間)。

==Text 型別:==

image

==Number 型別:==

image

==Date 型別:==

image

有了資料型別,我們的列也就有了型別約束了,也即限定了每一列該存放什麼型別的資料,那麼我們的表結構也就由此確定了。

現在我們來看看如何在一個資料庫中建立一張表:

CREATE TABLE table_name(
       column1 datatype,
       column2 datatype,
       column3 datatype,
       .....
       columnN datatype
    );
複製程式碼

這是最基本的建立表語句,例如我們可以這樣建立一張表:

CREATE TABLE person(
       id int,
       name varchar(16),
       phone char(11),
    );
複製程式碼

當然,這種方式建立的表結構還是太簡單了,現實中我們的欄位往往具有更加嚴格的約束。

1、NULL 非空約束

NULL 約束用來指定當前欄位的值是否允許為空,這裡的空並不是空字串,空格字串,而是未對該欄位賦值就判定為空。

create table person(
    id,int NOT NULL,
    uName,varchar(16) NOT NULL,
    phone,char(11) NUll
)
複製程式碼

NULL 則指定該欄位的值可以為空,NOT NULL 指定該欄位不可以為空。

2、DEFAULT 預設約束

DEFAULT 約束用於指定某一列在允許為 NULL 的前提下,如果在插入資料時未賦值該欄位時,資料庫統一賦的預設值。

create table person(
	id int DEFAULT 12,
	uName VARCHAR(16)
)
複製程式碼

當我們向表 person 插入資料時,如果你不為 id 欄位賦值,那麼該條資料記錄的 id 值就會是 12 。

3、UNIQUE 唯一約束

UNIQUE 約束用於限制表的某一欄位不可重複,也即唯一,一張表中可以有很多記錄,每條記錄的該欄位的值必須各不相同。

create table person(
	id int,
	uName VARCHAR(16) UNIQUE
)
複製程式碼

這樣,無論你向 person 表中插入多少條資料記錄,uName 這個欄位的是必須各不相同,也即當你嘗試向 person 表插入一條資料時,如果檢測到你將要插入的這條資料的 uName 欄位的值在表中已知記錄中存在,你將不能成功插入。

4、PRIMARY KEY 主鍵約束

『主鍵』就是能夠唯一確定一條具體資料記錄的一個或多個欄位的組合,也就是說,主鍵是表資料中一行記錄的標記,通過它可以唯一定位到一行資料記錄。

它與我們的 UNIQUE 看起來是一樣的,我們可以通過 UNIQUE 指定表的一個或多個欄位唯一不可重複,看似 UNIQUE 也可以唯一確定一行資料?

但時,UNIQUE 是不能唯一確定一行資料的,那是因為 UNIQUE 對空值無法約束。

你不讓我將欄位的值賦值為表中已知行資料的該欄位值,那我可以不賦值,該欄位的值為空。

所以,存在一種情況就是,已經對錶的某一欄位進行了 UNIQUE 約束,但時表中大量行資料的該欄位值為空,你還能通過該欄位唯一確定一行嗎?

有人認為我們的主鍵約束就等同於 UNIQUE + NOT NULL 兩個約束的集合,但其實我認為這並不準確,因為有時我們的主鍵可以由多個欄位共同構成,只要他們組合起來能夠唯一確定一行資料,單個欄位是否遵守上述兩個約束就成為非必要條件了。

例如:我有一張 person 表,裡面儲存了很多資料,已知可以通過姓名的手機號碼唯一確定一條資料,那麼我們的主鍵就是姓名和手機號碼兩個欄位的組合,而至於姓名是否唯一,是否允許為空,我們不需要關心。

這其實就是主鍵約束和 UNIQUE 約束的一個主要的區別所在,你只要記住主鍵是用於唯一確定一行資料的,UNIQUE 用於約束某一欄位的值不可重複出現。

關於主鍵約束的語法,

create table person(
    id int primary key,
    uName varchar(16)
)
複製程式碼

如果需要多個欄位組合構成主鍵,語法是這樣的:

create table person(
    id int,
    uName varchar(16),
    primary key(id,uName)
)
複製程式碼

5、FOREIGN KEY 約束

最後我們講講外來鍵約束,關係型資料庫的一個核心特點就是表與表之間可以存在關係,而如何關聯到另外一張表呢?這就用到一個鍵叫『外來鍵』,兩張表之間的微妙關係我們可以叫做外來鍵約束。

舉個例子吧,自己畫圖太醜,網上隨便找的表結構示意圖:

image

image

這裡涉及到兩張表,第一張訂單表記錄交易記錄資料,其中也需要記錄下建立這筆訂單的消費者,一種做法是把 persons 表中的所有欄位重新定義一遍,追加到 Orders 表中,這顯然繁瑣、欄位冗餘。

另一種做法就是我只增加一個欄位,該欄位儲存的值是 persons 表的主鍵,也就是當我需要關聯到某一個具體的 person 時,我只儲存它的主鍵值,而不去儲存它所有的欄位資訊,因為我是可以通過主鍵值定位到 persons 表的某條具體資料的。

上述示例中,我們管訂單表中的 Id_P 欄位叫做『外來鍵』,它其實又是 persons 表的『主鍵』。

因此,構建一個外來鍵約束,可以使用如下語法:

CREATE TABLE Orders
(
    Id_O int NOT NULL,
    OrderNo int NOT NULL,
    Id_P int,
    PRIMARY KEY (Id_O),
    FOREIGN KEY (Id_P) REFERENCES Persons(Id_P)
)
複製程式碼

前提是,Persons 表已經存在,否則將建立 Orders 表失敗。

以上,我們講了建立表所涉及到的一些基本的內容,包括基本的欄位型別、約束限制等,

但有的時候,表結構已經建立出來了,由於一些需求變更需要更改表結構,我們總不能 drop table 再重新定義一遍吧,SQL 規範中也提供了動態修改表結構的語句語法,我們一起來看看:

1、為表新增列

ALTER TABLE [tableName] ADD [columName] [列資料型別]
複製程式碼

例如:

alter table person add email varchar(24)
複製程式碼

為 person 表新增一列 email,varchar 型別。

2、修改表列屬性

列屬性包括,列名、列資料型別,我們分別來看下修改它們的 SQL 語法。

修改列名

alter table 表名 change column 舊列名 新列名  新列名格式;
複製程式碼

例如:

alter table person change column uName userName varchar(123)
複製程式碼

修改列資料型別:

MySQL:

alter table 表名 modify column 列名 列型別
複製程式碼

例如:

alter table person modify column userName varchar(16)
複製程式碼

SQLServer:

alter table 表名 alter column 列名 列型別
複製程式碼

修改資料型別這塊,各個應用資料庫實現語法稍有差異,但僅限於關鍵字不同,格式上大體相似。

3、刪除列

alter table 表名 drop column 列名
複製程式碼

例如:

ALTER TABLE person DROP COLUMN email
複製程式碼

刪除 person 表列 email。

關於表的刪除,就更加簡單了:

drop table 表名
複製程式碼

注意,這裡的表刪除是連同表結構加表資料全部刪除,謹慎使用。

關於表管理,大體上就介紹到這,看似很多,但實際上並沒有什麼特別複雜的點,無非是建立、刪除、修改表。

建立表的時候可以同時指定約束,修改表結構又分為修改列名和修改列的資料型別,而同時我們要小心謹慎使用 drop 刪除表。

雖然本篇寫很多,但並未涉及到複雜的 SQL 語句,僅限於簡單的建立 DDL 語句,下一篇我們看較為複雜的 DML 語句,進一步瞭解 SQL 對錶的增刪改查。


關注公眾不迷路,一個愛分享的程式設計師。
公眾號回覆「1024」加作者微信一起探討學習!
每篇文章用到的所有案例程式碼素材都會上傳我個人 github
github.com/SingleYam/o…
歡迎來踩!

YangAM 公眾號

相關文章