MySQL是一款流行的關係型數據庫, 結構化查詢語言SQL(Structured Query Language)是關係型數據庫通用的操做語言, 可是不一樣數據庫系統的行爲仍是有着細微的不一樣, 本文將以MySQL爲例進行介紹.sql
一個MySql服務實例下能夠維護多個database, 其中部分數據庫用於維護用戶和權限信息. Mysql提供了一些數據庫管理語句:數據庫
SHOW DATABASES;
顯示當前實例所擁有的數據庫函數
DROP DATABASES db_name;
刪除指定數據庫工具
CREATE DATABASE [IF NOT EXISTS] db_name;
建立數據庫post
use db_name;
進入數據庫ui
MySQL將數據存儲在數據表中, 數據表由數據庫來管理. 此外, 有一些命令能夠查看數據表的元信息:code
SHOW TABLES
顯示當前數據庫全部數據表對象
DESC <table_name>
或 DESCRIBE <table_name>
顯示錶結構排序
數據定義語言DDL(Data Definition Language)用於操做數據表等數據庫對象,對數據表、索引等進行定義。索引
數據表table是行列的邏輯結構, 每行是一條記錄, 每列是記錄的一個字段. 同一張表的全部記錄擁有相同的結構, 建立表時最重要的信息就是表的結構信息.
CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(20) DEFAULT "", `password` CHAR(20) DEFAULT "", `gender` CHAR(1), `age` INT );
SQL語句不區分大小寫, 一般咱們將SQL關鍵字大寫, 自定義標識符小寫. 用反點號包括自定義標識符能夠避免它們被認爲是SQL關鍵字.
SQL標識符以字母開頭, 可使用字母, 數字或三個特殊符號#
, _
, $
.標識符用於表示表, 列和其它對象的名稱.
全部DDL語句中的DEFAULT
項都是能夠省略的.
MySQL中經常使用的數據類型有:
INT
: 32位有符號整數DOUBLE
雙精度浮點數DECIMAL
精確小數CHAR(limit)
, 定長字符串VARCHAR(limit)
變長字符串TEXT
長文本數據DATE
日期DATETIME
日期和時間TIMESTAMP
UNIX時間戳使用drop
語句來刪除數據表:
DROP TABLE `user`;
表在建立完成後仍能夠修改其結構, 不過要注意對其中數據的影響:
ALTER TABLE `user` DROP `age`;
ALTER TABLE `user` ADD `age` INT DEFAULT 0;
ALTER TABLE `user` CHANGE `gender` `sex` CHAR(1) DEFAULT "M"; ALTER TABLE `user` MODIFY `gender` INT DEFAULT 0;
數據操做語言DML(Data Manipulation Language), 用於操做表中的數據。
插入一條記錄:
INSERT INTO `user` (`username`, `password`) VALUES ("abcd", "1234"); INSERT INTO `user` VALUES ("abcd", "1234");
要向全部沒有默認值且不容許爲空的列插入數據.
更新已存在的記錄:
UPTATE `user` SET `username`="abc" WHERE `id`=1;
update
能夠更新全部符合WHERE
子句的記錄, 當沒有WHERE
子句時更新該表全部記錄.
當鍵重複時更新記錄, 不然插入記錄:
INSERT INTO `user` VALUES ("a", "2") ON DUPLICATE KEY UPDATE `username`="a", "password"=2;
刪除記錄:
DELETE FROM `user` WHERE `id`=1;
刪除全部符合WHERE
子句的記錄, 當沒有WHERE
子句時刪除該表全部記錄.
查詢語句SELECT是最靈活最複雜也是最重要的SQL語句.
咱們建立用戶user
和文章post
兩張表作爲示例:
CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(20) DEFAULT "", `password` CHAR(20) DEFAULT "", `gender` CHAR(1), `age` INT ); CREATE TABLE `post` ( id INT PRIMARY KEY AUTO_INCREMENT, uid INT, title TEXT, CONTENT TEXT );
查詢user
表中全部記錄的全部字段.
SELECT * FROM `user`;
SELECT能夠能夠查詢某個表中符合條件記錄的某些字段.如全部男性用戶的username:
SELECT `username` FROM `user` WHERE `gender`='M';
咱們可使用LIMIT限制返回結果的數量:
SELECT * FROM `user` LIMIT 10 OFFSET 10;
上述查詢跳過前10個(OFFSET 10)結果, 並返回最多10條記錄(LIMIT 10)。
在多表查詢時可能須要指定列的所在的表:
SELECT `user`.`username` FROM `user` WHERE `user`.`gender`='M';
爲了簡化表達式能夠爲列和表指定別名:
SELECT u.`username` AS name FROM `user` u WHERE u.`gender`='M';
表中可能出現用戶名相同的狀況, 使用DISTINCT
函數去除重複的用戶名:
SELECT DISTINCT(`username`) FROM `user`;
MySQL能夠進行取平均值, 求和等彙集操做.
SELECT AVG(`age`) FROM `user`;
上述語句查詢user
表中全部記錄age
字段的平均值. 可使用GROUP BY
子句指定分組彙集方式.
SELECT AVG(`age`) FROM `user` GROUP BY `gender`;
上述語句將gender
字段相同的記錄視做一組, 求出age
字段的平均值. 咱們能夠附加where子句查詢男性用戶的平均年齡:
SELECT gender, AVG(`age`) FROM `user` WHERE gender=`M` GROUP BY gender;
WHERE
子句中沒法使用匯集函數, 可使用HAVING
子句完成該功能, 好比查詢發表文章超過3篇的做者:
SELECT uid FROM `post` HAVING count(id) > 3 GROUP BY uid;
經常使用的彙集函數有:
SUM
求和
AVG
求平均值
MIN
求最小值
MAX
求最大值
COUNT
求記錄數
此外還有一些工具函數也順便介紹:
LENGETH(txt)
, LEN(txt)
: 求文本長度
REPLACE(txt, from, to)
替換文本
UCASE(txt)
, LCASE(txt)
: 轉爲大寫 / 小寫
mid(txt, start, len)
: 提取子串
ORDER BY 語句能夠根據結果中某一列進行排序:
SELECT * FROM user ORDER BY age DESC LIMIT 10;
把user表中的記錄根據age字段進行降序排列, 並返回前10條記錄。
SELECT * FROM user ORDER BY age ASC LIMIT 10;
把user表中的記錄根據age字段進行升序排列, 並返回前10條記錄。
ORDER BY 語句能夠進行多列排序:
SELECT * FROM user ORDER BY age DESC, username ASC;
把user表中的記錄根據age字段進行升序排列,age相同的根據username字典序升序排列。
ORDER BY 語句能夠根據彙集函數進行排序:
SELECT post_id, count(*) as comment_count FROM comment GROUP BY post_id ORDER BY count(*) DESC;
根據文章的評論數進行降序排列。
如今查詢全部女性用戶發表的文章:
SELECT p.`id` AS post_id, `title`, `content`, u.`username` AS author FROM `user` u, `post` p WHERE p.`uid`=u.`id` AND u.`gender`='F';
字符串可使用單引號
'
或雙引號"
表示.
上述查詢將搜索user
和post
表中記錄全部組合, 知足條件p.uid=u.id
的user
記錄和post
記錄將組合爲同一條記錄. 而後查詢組合記錄中符合條件u.
gender='F'
的記錄.
使用等價的join
操做來代替上述查詢:
SELECT p.`id` AS post_id, title, content, u.`username` AS author FROM `post` p JOIN `user` u ON p.`uid`=u.`id` WHERE u.`gender`='F';
join
操做有3種:
INNER JOIN
, JOIN
: 查詢出的記錄必須知足ON
條件,若左表或右表中沒有對應的記錄,查詢結果中均不會包含相應記錄。
LEFT JOIN
: 查詢左表post
中全部記錄, 即便右表中沒有對應的記錄. 當沒有右表記錄時, 查詢結果中右表的字段爲空值.
REIGHT JOIN
查詢右表user
中全部記錄, 即便左表中沒有對應記錄. 當沒有左表記錄時, 查詢結果中左表的字段爲空值.
OUTER JOIN
: LEFT JOIN
和 RIGHT JOIN
結果的並集,即左右表只有一個表中有記錄便可。
注意若user
表中有m條記錄, post
表中有n條記錄則鏈接查詢將會掃描m*n
條記錄. 這在表中數據量較大時會很是耗時.
使用IN
和EXISTS
子查詢能夠完成鏈接查詢的任務.
SELECT * FROM `post` WHERE `uid` IN ( SELECT `user`.`id` FROM `user` WHERE `gender`='F' );
IN
運算符將匹配uid
和子查詢的結果, 若記錄的uid
在結果集中則IN
條件爲真.
IN
運算符後能夠直接書寫列表:
SELECT * FROM user WHERE username in ('a', 'b');
查詢username爲'a'或'b'的用戶。
EXISTS
運算符能夠起到相似的做用:
SELECT * FROM `post` WHERE EXISTS ( SELECT `user`.`id` FROM `user` WHERE `gender`='F' AND `user`.`id`=`post`.`uid` );
在EXISTS子查詢中能夠訪問外表,如上例exists子查詢中訪問了post
表。
上述SQL語句查詢使EXISTS子查詢SELECT user.id FROM user WHERE gender='F' AND user.id=post.uid
結果不爲空集的post
記錄。即查詢女性做者發表的全部文章,與本節開頭的IN查詢做用相同。
IN
和EXISTS
都有對應的否認形式:
SELECT * FROM `post` WHERE `uid` NOT IN ( SELECT `user`.`id` FROM `user` WHERE `gender`='F' );
SELECT * FROM `post` WHERE NOT EXISTS ( SELECT `user`.`id` FROM `user` WHERE `gender`='F' AND `user`.`id`=`post`.`uid` );
SELECT * FROM
語句能夠把另一個查詢結果做爲數據源。
添加兩張表:
CREATE TABLE `likes` ( `uid` INT, `post_id` INT, PRIMARY KEY (`uid`, `post_id`) ); CREATE TABLE `comment` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `uid` INT, `post_id` INT, `content` TEXT, );
咱們要搜索全部文章的點贊like
數和評論comment
數:
SELECT lc.post_id, lc.like_count, cc.comment_count FROM ( SELECT `post_id`, count(*) AS like_count FROM `likes` GROUP BY `post_id` ) lc OUTER JOIN ( SELECT `post_id`, count(*) AS comment_count FROM `comment` GROUP BY `post_id` ) cc ON lc.post_id = cc.post_id;
上述語句中咱們將查詢語句SELECT post_id, count(*) AS like_count FROM likes GROUP BY post_id
的結果做爲一個數據表, 並給它一個別名lc
。
相似地,咱們將另外一個查詢的結果做爲數據表cc
, 而後將兩個數據表進行JOIN。
MySQL能夠根據查詢建立視圖view
對象, 能夠用訪問數據表的方式訪問視圖. 視圖只保存查詢操做不保存數據, 視圖在被訪問時從數據表中取出數據.
CREATE VIEW `post_detail` AS SELECT p.`id` AS post_id, title, content, p.`uid` AS author_id, u.`username` AS author_name FROM `post` p JOIN `user` u ON p.`uid`=u.`id` WHERE u.`gender`='F';
SELECT * FROM `post_detail`;
約束是在表上強制執行的校驗規則, 用於保證數據的完整性. 約束分爲對單列的約束和對多個列集合的約束.
MySQL中全部數據類型均可以使用null, 一般使用field IS NULL
來判斷某個字段是否爲空.
非空約束限制某一列不容許出現null值, 在建表時添加非空約束:
CREATE TABLE `user` { `username` VARCHAR(20) NOT NULL }
也能夠隨時添加或刪除非空約束:
ALTER TABLE `user` modify `username` VARCHAR(20) NULL;
ALTER TABLE `user` modify `username` VARCHAR(20) NOT NULL;
惟一約束要求單列或列的集合不容許出現多個相同的非NULL值, 不容許username
列出現重複值:
CREATE TABLE `user` { `username` VARCHAR(20) UNIQUE }
容許username
或email
重複, 但不容許任意兩條記錄在username
相同時email
也相同.
CREATE TABLE `user` { `username` VARCHAR(20), `email` VARCHAR(20), UNIQUE(`username`, `email`) }
爲了便於後續操做, 最好使用命名約束:
CREATE TABLE `user` { username VARCHAR(20), email VARCHAR(20), CONSTRAINT uc_user UNIQUE(username, email) }
使用ALTER
添加惟一約束:
ALTER TABLE `user` ADD UNIQUE(`username`);
ALTER TABLE `user` ADD CONSTRAINT uc_user UNIQUE(`username`, `email`);
撤銷惟一約束:
ALTER TABLE `user` DROP CONSTRAINT uc_user;
主鍵是表上的一列或幾列的集合, 主鍵列必須非空且惟一. 主鍵必須能夠惟一肯定表中的記錄, 即不存在主鍵列相同的兩條記錄.
每一個表最多包含一個主鍵約束:
CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(20) DEFAULT "", );
CREATE TABLE `user` { username VARCHAR(20), email VARCHAR(20), CONSTRAINT user_key PRIMARY KEY(username, email) }
使用ALTER
修改主鍵約束:
ALTER TABLE `user` ADD PRIMARY KEY(`id`);
ALTER TABLE `user` ADD CONSTRAINT user_key PRIMARY KEY(`username`, `email`);
由於最多有一個主鍵約束, 因此刪除時不用指定約束對象:
ALTER TABLE `user` DROP PRIMARY KEY;
外鍵約束將數據表B上的某列或列集合與數據表A的主鍵關聯, 外鍵列的結構必須與被參照主鍵的結構一致, 但容許外鍵列的值重複. 數據表B上每條記錄的外鍵列必須與被參照表A的某條記錄的主鍵相同.
CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(20) DEFAULT "", `password` CHAR(20) DEFAULT "", `gender` CHAR(1), `age` INT ); CREATE TABLE `post` ( id INT PRIMARY KEY AUTO_INCREMENT, uid INT, title TEXT, CONTENT TEXT, FOREIGN KEY(uid) REFERENCES user(`id`) );
創建在post
表上的外鍵能夠保證post
表中每條記錄的uid都指向user
表中一條記錄. 避免存在找不到做者的文章.
當刪除被參照表上的某條記錄時, 必須刪除全部參照它的記錄. 即刪除用戶前必須前必須刪除他發表的全部文章, 以保證外鍵約束不被破壞.
在擁有外鍵約束的表post
上添加數據時必須掃描一遍被參照的user
, 這可能消耗不少時間, 在使用外鍵時必需要考慮到這一點.