MySQL快速入門

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

數據定義語言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

數據操做語言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

查詢語句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';

字符串可使用單引號'或雙引號"表示.

上述查詢將搜索userpost表中記錄全部組合, 知足條件p.uid=u.iduser記錄和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 JOINRIGHT JOIN 結果的並集,即左右表只有一個表中有記錄便可。

注意若user表中有m條記錄, post表中有n條記錄則鏈接查詢將會掃描m*n條記錄. 這在表中數據量較大時會很是耗時.

IN 和 EXISTS 查詢

使用INEXISTS子查詢能夠完成鏈接查詢的任務.

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查詢做用相同。

INEXISTS都有對應的否認形式:

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
}

容許usernameemail重複, 但不容許任意兩條記錄在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, 這可能消耗不少時間, 在使用外鍵時必需要考慮到這一點.

相關文章
相關標籤/搜索