目錄mysql
一、SQL語句分類sql
二、DDL語句數據庫
三、DML語句bash
四、DCL語句服務器
五、事務相關語句ide
六、mysql查詢函數
6.一、單表簡單查詢優化
6.二、多表組合查詢ui
6.2.一、聯結查詢(交叉聯結,內聯結,外聯結(左外聯結、右外聯結))spa
6.2.二、聯合查詢(UNION)
6.2.三、內聯結
6.三、子查詢
6.3.一、WHERE子查詢
6.3.二、FROM子查詢
一、SQL語句分類
DDL:數據定義語言,用來定義數據庫對象,包括數據庫、表、索引、存儲過程、存儲函數、約束、觸發器、事件調度器等
DML:數據操做語言,包括CRUD(Insert,Select,Replace,Update,Delete)
DCL:數據控制語言,包括grant,revoke
與事務相關的語言:start transaction,commit,rollback,save point
二、DDL語句
2.一、數據庫操做
a)、建立數據庫:
語法:mysql> create {database | schema} [if not exists] 數據庫名; #「if not exists」是用來做條件判斷
舉例:
mysql> create database if not exists mydb; #建立一個mydb數據庫 Query OK, 1 row affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) mysql> create schema if not exists mydb; #嘗試再次創建mydb數據庫 Query OK, 1 row affected, 1 warning (0.00 sec) mysql> show warnings; #查看警告信息 +-------+------+-----------------------------------------------+ | Level | Code | Message | +-------+------+-----------------------------------------------+ | Note | 1007 | Can't create database 'mydb'; database exists | +-------+------+-----------------------------------------------+ 1 row in set (0.00 sec)
b)、刪除數據庫:
語法:
mysql> drop {database | schema} [if exists] 數據庫名;
舉例:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) mysql> drop schema if exists mydb; Query OK, 0 rows affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.00 sec)
c)、修改數據庫
語法:
mysql> alter {database | schema} 數據庫名 [DEFAULT] CHARACTER SET [=] charset_name |[DEFAULT] COLLATE [=] collation_name
mysql> alter {database | schema} 數據庫名 upgrade data directory name; #此語句用在數據進行升級後用來升級數據字典
2.二、數據表操做
a)、建立字段自定義表
語法:
mysql> create table [if not exists] 表名 (字段1 字段定義,字段2 字段定義, ...) 衆多選項
mysql> help create table; #獲取表建立的幫助。
舉例:
mysql> use test; mysql> create table if not exists tb1 (id int unsigned auto_increment primary key,name char(30) not null,age tinyint unsigned,class char(20) not null ) character set = utf8 engine = innodb;
如下三個sql語句均可查數據庫中的表狀態:
mysql> show table status from test\G mysql> show table status in test\G mysql> show table status like 'tb1';
b)、以select語句查詢到的數據爲結果來建立一張表
mysql> use mydb1; mysql> create table if not exists tb2 select user,host,password from mysql.user; Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from tb2; +------+------------+-------------------------------------------+ | user | host | password | +------+------------+-------------------------------------------+ | root | localhost | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 | | root | db\_server | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 | | root | 127.0.0.1 | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 | +------+------------+-------------------------------------------+ 3 rows in set (0.00 sec) 注:這種方式建立出來的表,表的表結構與源表的表結構是不一樣的,也就是說字段中的定義和修飾符不會所有在新表中都有
c)、模仿一張表的表結構來建立一張只有表結構的表
mysql> create table if not exists tb3 like tb2; Query OK, 0 rows affected (0.03 sec) mysql> desc tb3; +----------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+----------+------+-----+---------+-------+ | user | char(16) | NO | | | | | host | char(60) | NO | | | | | password | char(41) | NO | | | | +----------+----------+------+-----+---------+-------+ 3 rows in set (0.03 sec) mysql> desc tb2; +----------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+----------+------+-----+---------+-------+ | user | char(16) | NO | | | | | host | char(60) | NO | | | | | password | char(41) | NO | | | | +----------+----------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> select * from tb3; #tb3中是沒有數據的 Empty set (0.02 sec)
開動腦筋:
怎樣從一個表中挑選一些數據生成一張新表,且新表的表結構(字段定義、修飾符等)與源表是完成相同的。
實現方式分兩部來完成,先建立和源表同樣表結構的表,再以select的方式插入數據到此表。
實現:
mysql> DESC tb1; +-------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(20) | NO | | NULL | | | age | tinyint(3) unsigned | NO | | NULL | | +-------+---------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM tb1; +----+-------+-----+ | id | name | age | +----+-------+-----+ | 1 | jack | 29 | | 2 | jason | 39 | | 3 | tom | 37 | | 4 | luck | 22 | | 7 | root | 0 | | 8 | root | 0 | | 9 | root | 0 | +----+-------+-----+ 7 rows in set (0.01 sec) mysql> CREATE TABLE IF NOT EXISTS tb2 LIKE tb1; #建立tb2以tb1的表結構爲源 Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> DESC tb2; #tb2的表結構和tb1的表結構是完成相同的 +-------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(20) | NO | | NULL | | | age | tinyint(3) unsigned | NO | | NULL | | +-------+---------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> INSERT INTO tb2 SELECT * FROM tb1 WHERE age>30; #只把tb1中年齡大於30的數據插入到新表中 Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM tb2; #驗證數據 +----+-------+-----+ | id | name | age | +----+-------+-----+ | 2 | jason | 39 | | 3 | tom | 37 | +----+-------+-----+ 2 rows in set (0.00 sec) 這樣就可實現保持源表的表結構提取所需數據。
d)、刪除表
mysql> drop table [if exists] 表名;
e)、修改表名稱、字段、定義、修飾符等
用help alter table來獲取幫助
新增字段,刪除字段
modify 修改指定字段定義:
change 修改字段名
rename 新表名
舉例:
mysql> SELECT * FROM tb2; +------+------+ | id | name | +------+------+ | 1 | Zcj | | 2 | Tom | +------+------+ 2 rows in set (0.00 sec) mysql> DESC tb2; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | char(30) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ mysql> ALTER TABLE tb2 ADD Age TINYINT UNSIGNED AFTER id; #增長「Age」字段 Query OK, 2 rows affected (0.04 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM tb2; +------+------+------+ | id | Age | name | +------+------+------+ | 1 | NULL | Zcj | | 2 | NULL | Tom | +------+------+------+ mysql> ALTER TABLE tb2 DROP Age; #刪除字段「Age」 Query OK, 2 rows affected (0.06 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM tb2; +------+------+ | id | name | +------+------+ | 1 | Zcj | | 2 | Tom | +------+------+ mysql> ALTER TABLE tb2 MODIFY id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY; #修改id字段的定義 Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> DESC tb2; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(30) | YES | | NULL | | +-------+------------------+------+-----+---------+----------------+ mysql> ALTER TABLE tb2 CHANGE name fullname CHAR(50) NOT NULL; #修改字段name的名稱及定義 Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> DESC tb2; +----------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | fullname | char(50) | NO | | NULL | | +----------+------------------+------+-----+---------+----------------+ mysql> ALTER TABLE tb2 RENAME newtb2; #修改表名 Query OK, 0 rows affected (0.00 sec) mysql> DESC newtb2; +----------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | fullname | char(50) | NO | | NULL | | +----------+------------------+------+-----+---------+----------------+
三、DML語句
3.一、insert:用來插入數據
語法:
mysql> insert into 表名 [(字段名,...)] {values | value} (值,...)
mysql> insert into 表名 set 字段名=值,...
舉例:
mysql> CREATE TABLE IF NOT EXISTS tb1 (id int unsigned auto_increment primary key,name char(20) not null,age tinyint unsigned not null); #先建立一張表
a)、插入多行數據
mysql> INSERT INTO tb1 (name,age) VALUES ('jack',29),('jason',39),('tom',37);
b)、插入一行數據
mysql> INSERT INTO tb1 SET name='luck',age=22; mysql> SELECT * FROM tb1; #查看錶數據 +----+-------+-----+ | id | name | age | +----+-------+-----+ | 1 | jack | 29 | | 2 | jason | 39 | | 3 | tom | 37 | | 4 | luck | 22 | +----+-------+-----+ 4 rows in set (0.00 sec)
c)、以select結果插入數據
mysql> INSERT INTO tb1 (name) SELECT user FROM mysql.user; #把user表中的用戶信息檢索出來填充到tb1表中的name字段 Query OK, 3 rows affected, 1 warning (0.08 sec) Records: 3 Duplicates: 0 Warnings: 1 mysql> SHOW WARNINGS; #有個警告信息,由於建立表時age字段是not null的,只填充了name字段,沒有age字段的相應數據 +---------+------+------------------------------------------+ | Level | Code | Message | +---------+------+------------------------------------------+ | Warning | 1364 | Field 'age' doesn't have a default value | +---------+------+------------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT * FROM tb1; #自動把age字段填充爲0 +----+-------+-----+ | id | name | age | +----+-------+-----+ | 1 | jack | 29 | | 2 | jason | 39 | | 3 | tom | 37 | | 4 | luck | 22 | | 7 | root | 0 | | 8 | root | 0 | | 9 | root | 0 | +----+-------+-----+ 7 rows in set (0.08 sec)
3.二、replace:用來替換表的數據,若是源表中沒有此數據則增長數據
mysql> DESC tb2; #name字段是惟一鍵索引 +-------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(20) | NO | UNI | NULL | | | age | tinyint(3) unsigned | NO | | NULL | | +-------+---------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM tb2; +----+-------+-----+ | id | name | age | +----+-------+-----+ | 1 | jack | 29 | | 2 | jason | 39 | | 3 | tom | 37 | | 4 | luck | 22 | +----+-------+-----+ 4 rows in set (0.00 sec) mysql> REPLACE INTO tb2 SET name='jack',age=33; #因原表中有jack這個用戶,replace這個命令會先刪除原來的那一行,再新增長一行,因此會有兩行受到影響 Query OK, 2 rows affected (0.04 sec) mysql> REPLACE INTO tb2 SET name='zhaochj',age=29; #因原表中沒有zhaochj這個用戶,因此直接在最後增長 Query OK, 1 row affected (0.03 sec) mysql> SELECT * FROM tb2; +----+---------+-----+ | id | name | age | +----+---------+-----+ | 2 | jason | 39 | | 3 | tom | 37 | | 4 | luck | 22 | | 5 | jack | 33 | | 6 | zhaochj | 29 | +----+---------+-----+ 5 rows in set (0.02 sec)
3.三、update:修改表中的數據
mysql> SELECT * FROM tb2; +----+---------+-----+ | id | name | age | +----+---------+-----+ | 2 | jason | 39 | | 3 | tom | 37 | | 4 | luck | 22 | | 5 | jack | 33 | | 6 | zhaochj | 29 | +----+---------+-----+ 5 rows in set (0.02 sec) mysql> UPDATE tb2 SET age=33 WHERE name='zhaochj'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> UPDATE tb2 SET age=11 LIMIT 2; #修改前兩行的年齡爲11 Query OK, 2 rows affected (0.01 sec) Rows matched: 2 Changed: 2 Warnings: 0 mysql> SELECT * FROM tb2; +----+---------+-----+ | id | name | age | +----+---------+-----+ | 2 | jason | 11 | | 3 | tom | 11 | | 4 | luck | 22 | | 5 | jack | 33 | | 6 | zhaochj | 33 | +----+---------+-----+ 5 rows in set (0.02 sec)
3.四、delete 刪除表中數據
mysql> SELECT * FROM tb2; +----+---------+-----+ | id | name | age | +----+---------+-----+ | 2 | jason | 11 | | 3 | tom | 11 | | 4 | luck | 22 | | 5 | jack | 33 | | 6 | zhaochj | 33 | +----+---------+-----+ 5 rows in set (0.02 sec) mysql> mysql> DELETE FROM tb2 WHERE name='zhaochj'; #加上where子句限定刪除的範圍 Query OK, 1 row affected (0.38 sec) mysql> SELECT * FROM tb2; +----+-------+-----+ | id | name | age | +----+-------+-----+ | 2 | jason | 11 | | 3 | tom | 11 | | 4 | luck | 22 | | 5 | jack | 33 | +----+-------+-----+ 4 rows in set (0.00 sec) mysql> DELETE FROM tb2; #這樣直接把表中的數據所有刪除 Query OK, 4 rows affected (0.01 sec) mysql> SELECT * FROM tb2; Empty set (0.00 sec) mysql> INSERT INTO tb2 (name,age) VALUES ('zcj',29); #試着插入一行數據 Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM tb2; #查看數據發現id號不是從"1"開始的,這是由於字段「id」被定義成了「auto_increment」了 +----+------+-----+ | id | name | age | +----+------+-----+ | 7 | zcj | 29 | +----+------+-----+ 1 row in set (0.03 sec) mysql> TRUNCATE TABLE tb2; #清空一張表,應該用這個命令,表示重置表,會清空「auto_increment」的計數器 Query OK, 0 rows affected (0.05 sec) mysql> INSERT INTO tb2 (name,age) VALUES ('zcj',29); Query OK, 1 row affected (0.03 sec) mysql> SELECT * FROM tb2; #id號又從「1」開始 +----+------+-----+ | id | name | age | +----+------+-----+ | 1 | zcj | 29 | +----+------+-----+ 1 row in set (0.00 sec)
四、DCL語句
4.一、權限賦予
mysql> GRANT select ON mydb2.tb1 TO 'mydb2user1'@'%' IDENTIFIED BY '111111'; #對mydb2數據庫中的tb1表授予mydb2user1用戶可在任意主機以6個1爲密碼登錄,但權限只有select mysql> SHOW GRANTS FOR mydb2user1; #顯示mydb2user1用戶的權限信息 +-----------------------------------------------------------------------------------------------------------+ | Grants for mydb2user1@% | +-----------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'mydb2user1'@'%' IDENTIFIED BY PASSWORD '*FD571203974BA9AFE270FE62151AE967ECA5E0AA' | | GRANT SELECT ON `mydb2`.`tb1` TO 'mydb2user1'@'%' | +-----------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) 驗證權限是否生效: [root@mariadb ~]# mysql -umydb2user1 -p111111 #以mydb2user1登錄 mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mydb2 | | test | +--------------------+ mysql> USE mydb2; Database changed mysql> SHOW TABLES; +-----------------+ | Tables_in_mydb2 | +-----------------+ | tb1 | +-----------------+ mysql> SELECT * FROM tb1; +------+------+ | id | name | +------+------+ | 1 | Zcj | | 2 | Tom | | 3 | Jack | +------+------+ mysql> INSERT INTO tb1 (id,name) VALUES (4,'Cora'); #沒有權限插入數據 ERROR 1142 (42000): INSERT command denied to user 'mydb2user1'@'localhost' for table 'tb1' mysql> GRANT insert ON mydb2.tb1 TO 'mydb2user1'@'%'; #再賦予insert權限 Query OK, 0 rows affected (0.00 sec) mysql> SHOW GRANTS FOR mydb2user1; +-----------------------------------------------------------------------------------------------------------+ | Grants for mydb2user1@% | +-----------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'mydb2user1'@'%' IDENTIFIED BY PASSWORD '*FD571203974BA9AFE270FE62151AE967ECA5E0AA' | | GRANT SELECT, INSERT ON `mydb2`.`tb1` TO 'mydb2user1'@'%' | +-----------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) [root@mariadb ~]# mysql -umydb2user1 -p111111 #再以mydb2user1登錄 mysql> INSERT INTO tb1 (id,name) VALUES (4,'Cora'); Query OK, 1 row affected (0.07 sec) mysql> SELECT * FROM tb1; #數據已插入 +------+------+ | id | name | +------+------+ | 1 | Zcj | | 2 | Tom | | 3 | Jack | | 4 | Cora | +------+------+ 4 rows in set (0.00 sec)
4.二、回收權限
[root@mariadb ~]# mysql -uroot -p123456 #以root登錄 mysql> REVOKE insert ON mydb2.tb1 FROM mydb2user1; Query OK, 0 rows affected (0.00 sec) [root@mariadb ~]# mysql -umydb2user1 -p111111 #以mydb2user1登錄 mysql> INSERT INTO mydb2.tb1 (id,name) VALUES (5,'Lucky'); #沒法插入數據,insert權限已被回收 ERROR 1142 (42000): INSERT command denied to user 'mydb2user1'@'localhost' for table 'tb1'
五、事務相關語句
mysql> START TRANSACTION; #開始事務
mysql> SAVEPOINT point_name; #保存一個事務的位置,以方便撤銷事務
mysql> ROLLBACK TO point_name; #回滾到一個點
mysql> ROLLBACK; #回滾到開始事務時的狀態
mysql> COMMIT; #提交事務
舉例:
mysql> START TRANSACTION; #開始事務 Query OK, 0 rows affected (0.02 sec) mysql> SELECT * FROM tb1; +------+------+ | id | name | +------+------+ | 1 | Zcj | | 2 | Tom | | 3 | Jack | | 4 | Cora | +------+------+ 4 rows in set (0.00 sec) mysql> INSERT INTO tb1 (id,name) VALUES (5,'Lucky'); #插入一行數據 Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM tb1; +------+-------+ | id | name | +------+-------+ | 1 | Zcj | | 2 | Tom | | 3 | Jack | | 4 | Cora | | 5 | Lucky | +------+-------+ 5 rows in set (0.00 sec) mysql> SAVEPOINT p1; #在有id爲5這行數據時建立一個保存點 Query OK, 0 rows affected (0.01 sec) mysql> DELETE FROM tb1 WHERE id = 2; #刪除一行數據 Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM tb1; +------+-------+ | id | name | +------+-------+ | 1 | Zcj | | 3 | Jack | | 4 | Cora | | 5 | Lucky | +------+-------+ 4 rows in set (0.00 sec) mysql> ROLLBACK TO p1; #回滾到保存點p1的狀態 Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM tb1; +------+-------+ | id | name | +------+-------+ | 1 | Zcj | | 2 | Tom | | 3 | Jack | | 4 | Cora | | 5 | Lucky | +------+-------+ 5 rows in set (0.00 sec) mysql> ROLLBACK; #回滾到事務開始時的狀態 Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM tb1; +------+------+ | id | name | +------+------+ | 1 | Zcj | | 2 | Tom | | 3 | Jack | | 4 | Cora | +------+------+ 4 rows in set (0.00 sec) mysql> COMMIT; #提交事務 Query OK, 0 rows affected (0.00 sec)
六、mysql查詢
爲演示各類SELECT語句,創建如下幾個表:
一)、表名爲「students_tb」,字段爲:StudentID,Name,Age,Gender,ClassID,分別存放學生的名字、年齡、性別、有班級的ID號,具體的班級存放在另外一張表中
二)、表名爲「classes_tb」,字段爲:ClassID,Class,TeacherID,分別存放班級的ID號,具體的班級名,這個班級是哪一個老師負責的ID號,具體的負責的老師存放在另外一張表中
三)、表名爲「teacher_tb」,字段爲:TeacheID,Name,Age,Gender,分別存放老師的ID號,老師的名字,年齡,性別
mysql> USE mydb1; mysql> CREATE TABLE IF NOT EXISTS students_tb (StudentID SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,Name CHAR(30) NOT NULL,Age TINYINT UNSIGNED,Gender ENUM('M','F'),ClassID TINYINT UNSIGNED NOT NULL); mysql> INSERT INTO students_tb (Name,Age,Gender,ClassID) VALUES ('Tom',17,'M',1),('Jack',18,'M',3),('Lucy',21,'F',6),('Jimima',15,'F',4),('Jimmy',30,'M',9),('Jim',26,'M',7); mysql> SELECT * FROM students_tb; +-----------+--------+------+--------+---------+ | StudentID | Name | Age | Gender | ClassID | +-----------+--------+------+--------+---------+ | 1 | Tom | 17 | M | 1 | | 2 | Jack | 18 | M | 3 | | 3 | Lucy | 21 | F | 6 | | 4 | Jimima | 15 | F | 4 | | 5 | Jimmy | 30 | M | 9 | | 6 | Jim | 26 | M | 7 | +-----------+--------+------+--------+---------+ mysql> CREATE TABLE IF NOT EXISTS classes_tb (ClassID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,Class CHAR(20) NOT NULL,TeacherID TINYINT UNSIGNED NOT NULL); mysql> ALTER TABLE classes_tb ADD UNIQUE KEY (Class); #這個表中的班別應該是惟一的,因此用此sql語句來修改 Query OK, 0 rows affected (0.08 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> DESC classes_tb; +-----------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+---------------------+------+-----+---------+----------------+ | ClassID | tinyint(3) unsigned | NO | PRI | NULL | auto_increment | | Class | char(20) | NO | UNI | NULL | | | TeacherID | tinyint(3) unsigned | NO | | NULL | | +-----------+---------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> INSERT INTO classes_tb (Class,TeacherID) VALUES ('class1',5),('class2',2),('class3',5),('class4',2),('class5',4),('class6',1); mysql> SELECT * FROM classes_tb; +---------+--------+-----------+ | ClassID | Class | TeacherID | +---------+--------+-----------+ | 1 | class1 | 5 | | 2 | class2 | 2 | | 3 | class3 | 5 | | 4 | class4 | 2 | | 5 | class5 | 4 | | 6 | class6 | 1 | +---------+--------+-----------+ mysql> CREATE TABLE IF NOT EXISTS teacher_tb (TeacherID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,Name CHAR(30) NOT NULL,Age TINYINT UNSIGNED,Gender ENUM('M','F')); mysql> INSERT INTO teacher_tb (Name,Age,Gender) VALUES ('Wang baoqiang',30,'M'),('Zhang shanfeng',32,'F'),('Zhao qiang',40,'M'),('Ying hui',50,'M'),('Feng bing',46,'M'),('Qian qiang',37,'M'),('Shun bin',68,'M'); mysql> SELECT * FROM teacher_tb; +-----------+----------------+------+--------+ | TeacherID | Name | Age | Gender | +-----------+----------------+------+--------+ | 1 | Wang baoqiang | 30 | M | | 2 | Zhang shanfeng | 32 | F | | 3 | Zhao qiang | 40 | M | | 4 | Ying hui | 50 | M | | 5 | Feng bing | 46 | M | | 6 | Qian qiang | 37 | M | | 7 | Shun bin | 68 | M | +-----------+----------------+------+--------+ 三個表建立及數據插入完成。
6.一、單表簡單查詢
語法:
SELECT 字段,字段,... FROM 表名 WHERE 子句;
舉例:
查詢students_tb表中前5個學生的姓名和年齡
mysql> SELECT Name,Age FROM students_tb LIMIT 5; +--------+------+ | Name | Age | +--------+------+ | Tom | 17 | | Jack | 18 | | Lucy | 21 | | Jimima | 15 | | Jimmy | 30 | +--------+------+
a)、比較運算:>,<,>=,<=,!=,<>,<=>
在students_tb表中查詢年齡大於20的學生有哪些:
mysql> SELECT Name,Age FROM students_tb WHERE Age>20; +-------+------+ | Name | Age | +-------+------+ | Lucy | 21 | | Jimmy | 30 | | Jim | 26 | +-------+------+
在students_tb表中查詢年齡不等於30的學生有哪些:
mysql> SELECT Name,Age FROM students_tb WHERE Age!=30; +--------+------+ | Name | Age | +--------+------+ | Tom | 17 | | Jack | 18 | | Lucy | 21 | | Jimima | 15 | | Jim | 26 | +--------+------+
在students_tb表中查詢年齡不等於30和不等於15的學生有哪些:
mysql> SELECT Name,Age FROM students_tb WHERE Age!=30 and Age!=15; +------+------+ | Name | Age | +------+------+ | Tom | 17 | | Jack | 18 | | Lucy | 21 | | Jim | 26 | +------+------+
b)、BETWEEN...AND..表示在一個範圍內的數據
在students_tb表中查詢年齡在20到30之間的學生:
mysql> SELECT Name,Age FROM students_tb WHERE Age BETWEEN 20 AND 30; +-------+------+ | Name | Age | +-------+------+ | Lucy | 21 | | Jimmy | 30 | | Jim | 26 | +-------+------+
c)、IN (元素,...),表示在一個範圍內匹配
在students_tb表中查詢年齡是18或26或30的學生:
mysql> SELECT Name,Age FROM students_tb WHERE Age IN (18,26,30); #表示查詢一個集合內的數據 +-------+------+ | Name | Age | +-------+------+ | Jack | 18 | | Jimmy | 30 | | Jim | 26 | +-------+------+
d)、LIKE子句與RLIKE子句
在students_tb表中查詢姓名中有字母「J」,且在後邊跟了任意個字符的用戶:
mysql> SELECT Name,Age FROM students_tb WHERE Name LIKE 'J%'; +--------+------+ | Name | Age | +--------+------+ | Jack | 18 | | Jimima | 15 | | Jimmy | 30 | | Jim | 26 | +--------+------+ #通配符匹配有「%」,「_」 ,「%」表示匹配任意個任意字符,「_」表示匹配任意單個字符
在students_tb表中查詢姓名以「J」開頭,後接任意字符,再接有一個m或多個m,再後接任意個字符,而且以y結尾的學生:
mysql> SELECT Name,Age FROM students_tb WHERE Name RLIKE '^J.*m+.*y$'; #正則匹配 +-------+------+ | Name | Age | +-------+------+ | Jimmy | 30 | +-------+------+
e)、邏輯運算符(NOT,AND,OR),優先級依次下降
在students_tb表中查詢學生姓名以「J」開頭,而且年齡大於20的信息:
mysql> SELECT Name,Age FROM students_tb WHERE Name RLIKE '^J' && Age>20; #「&&」=「AND」 +-------+------+ | Name | Age | +-------+------+ | Jimmy | 30 | | Jim | 26 | +-------+------+
在students_tb表中查詢年齡是30或者是15的學生:
mysql> SELECT Name,Age FROM students_tb WHERE Age=30 OR Age=15; #「OR」="||" +--------+------+ | Name | Age | +--------+------+ | Jimima | 15 | | Jimmy | 30 | +--------+------+
在students_tb表中查詢性別不是「F」的學生:
mysql> SELECT Name,Gender FROM students_tb WHERE NOT Gender='F'; +-------+--------+ | Name | Gender | +-------+--------+ | Tom | M | | Jack | M | | Jimmy | M | | Jim | M | +-------+--------+
在students_tb表中查詢年齡在10到26之間,姓名以「J」或「L」開頭的女生:
mysql> SELECT Name,Age,Gender FROM students_tb WHERE Age>=10 AND Age<=26 AND (Name LIKE 'J%' OR Name LIKE '%L') AND Gender='F'; +--------+------+--------+ | Name | Age | Gender | +--------+------+--------+ | Jimima | 15 | F | +--------+------+--------+ 注:邏輯運算是有優先級的,若是不用括號那獲得的結果與預想的不同。
f)、聚合函數:MAX(),MIN(),AVG(),SUM(),COUNT()
在students_tb表中查詢年齡最大的學生是誰:
mysql> SELECT Name,Age FROM students_tb WHERE Age = (SELECT MAX(Age) FROM students_tb); +-------+------+ | Name | Age | +-------+------+ | Jimmy | 30 | +-------+------+
在students_tb表中查詢年齡最小的學生是誰:
mysql> SELECT Name,Age FROM students_tb WHERE Age = (SELECT MIN(Age) FROM students_tb); +--------+------+ | Name | Age | +--------+------+ | Jimima | 15 | +--------+------+
在students_tb表中求全部學生年齡的平均值
mysql> SELECT AVG(Age) FROM students_tb; +----------+ | AVG(Age) | +----------+ | 21.1667 | +----------+
g)、GROUP BY 分組,及HAVING子句
在students_tb表中求男生、女生年齡分別的平均值:
mysql> SELECT Gender,AVG(Age) FROM students_tb GROUP BY Gender; +--------+----------+ | Gender | AVG(Age) | +--------+----------+ | M | 22.7500 | | F | 18.0000 | +--------+----------+
顯示students_tb表中分別顯示男生,女生的最大年齡:
mysql> SELECT Gender,MAX(Age) FROM students_tb GROUP BY Gender; +--------+----------+ | Gender | MAX(Age) | +--------+----------+ | M | 30 | | F | 21 | +--------+----------+
爲了演示HAVING子句,如今加入如下數據:
mysql> INSERT INTO students_tb (Name,Age,Gender,ClassID) VALUES ('Cora',25,'F',6),('Echo',58,'F',7),('張三',47,'M',3); mysql> SELECT * FROM students_tb; +-----------+--------+------+--------+---------+ | StudentID | Name | Age | Gender | ClassID | +-----------+--------+------+--------+---------+ | 1 | Tom | 17 | M | 1 | | 2 | Jack | 18 | M | 3 | | 3 | Lucy | 21 | F | 6 | | 4 | Jimima | 15 | F | 4 | | 5 | Jimmy | 30 | M | 9 | | 6 | Jim | 26 | M | 7 | | 7 | Cora | 25 | F | 6 | | 8 | Echo | 58 | F | 7 | | 9 | 張三 | 47 | M | 3 | +-----------+--------+------+--------+---------+
以班級排序,顯示students_tb表中各個班級中年齡最小的同窗,只顯示年齡小於20的的班級:
mysql> SELECT ClassID,Name,MIN(Age) FROM students_tb GROUP BY ClassID; +---------+--------+----------+ | ClassID | Name | MIN(Age) | +---------+--------+----------+ | 1 | Tom | 17 | | 3 | Jack | 18 | | 4 | Jimima | 15 | | 6 | Lucy | 21 | | 7 | Jim | 26 | | 9 | Jimmy | 30 | +---------+--------+----------+ mysql> SELECT ClassID,Name,MIN(Age) FROM students_tb GROUP BY ClassID HAVING MIN(Age)<20; +---------+--------+----------+ | ClassID | Name | MIN(Age) | +---------+--------+----------+ | 1 | Tom | 17 | | 3 | Jack | 18 | | 4 | Jimima | 15 | +---------+--------+----------+
h)、ORDER BY排序
以性別分組,分別計算男女生的年齡之和,並逆序排列:
mysql> SELECT Gender,SUM(Age) FROM students_tb GROUP BY Gender ORDER BY SUM(Age) DESC; +--------+----------+ | Gender | SUM(Age) | +--------+----------+ | M | 138 | | F | 119 | +--------+----------+
查看students_tb表中男女生各是多少:
mysql> SELECT Gender,COUNT(Name) FROM students_tb GROUP BY Gender; +--------+-------------+ | Gender | COUNT(Name) | +--------+-------------+ | M | 5 | | F | 4 | +--------+-------------+
6.二、多表組合查詢
6.2.一、聯結查詢(交叉聯結,內聯結,外聯結(左外聯結、右外聯結))
a)、交叉聯結(返回笛卡爾集)
關鍵字:CROSS JOIN
mysql> SELECT * FROM students_tb CROSS JOIN classes_tb; #結果略,相似數學裏的多項式相乘,這種對服務器的開銷特別大,極少使用。
b)、天然聯結:讓兩張表的某個相同字段進行等值關係聯結,是左右外聯結的交集
關鍵字:NATURAL...JOIN
mysql> SELECT * FROM students_tb NATURAL JOIN classes_tb; +---------+-----------+--------+------+--------+--------+-----------+ | ClassID | StudentID | Name | Age | Gender | Class | TeacherID | +---------+-----------+--------+------+--------+--------+-----------+ | 1 | 1 | Tom | 17 | M | class1 | 5 | | 3 | 2 | Jack | 18 | M | class3 | 5 | | 3 | 12 | 張三 | 47 | M | class3 | 5 | | 4 | 4 | Jimima | 15 | F | class4 | 2 | | 6 | 3 | Lucy | 21 | F | class6 | 1 | | 6 | 10 | Cora | 25 | F | class6 | 1 | +---------+-----------+--------+------+--------+--------+-----------+ 注意:在表students_tb中有些有的ClassID,而在classed_tb中沒有相對應的值,採用內聯結裏是不顯示出來的。
顯示學生的信息,所在的班級也要顯示出來:
mysql> SELECT * FROM students_tb,classes_tb WHERE students_tb.ClassID=classes_tb.ClassID; #其實也是交叉聯結過慮後的結果 +-----------+--------+------+--------+---------+---------+--------+-----------+ | StudentID | Name | Age | Gender | ClassID | ClassID | Class | TeacherID | +-----------+--------+------+--------+---------+---------+--------+-----------+ | 1 | Tom | 17 | M | 1 | 1 | class1 | 5 | | 2 | Jack | 18 | M | 3 | 3 | class3 | 5 | | 9 | 張三 | 47 | M | 3 | 3 | class3 | 5 | | 4 | Jimima | 15 | F | 4 | 4 | class4 | 2 | | 3 | Lucy | 21 | F | 6 | 6 | class6 | 1 | | 7 | Cora | 25 | F | 6 | 6 | class6 | 1 | +-----------+--------+------+--------+---------+---------+--------+-----------+
c)、外聯結
左外聯結(語法:左表 LEFT JOIN 右表 ON 條件)
顯示各個同窗是哪一個班級的,若是此同窗尚未給定班級,則留空:
mysql> SELECT * FROM students_tb LEFT JOIN classes_tb ON students_tb.ClassID=classes_tb.ClassID; +-----------+--------+------+--------+---------+---------+--------+-----------+ | StudentID | Name | Age | Gender | ClassID | ClassID | Class | TeacherID | +-----------+--------+------+--------+---------+---------+--------+-----------+ | 1 | Tom | 17 | M | 1 | 1 | class1 | 5 | | 2 | Jack | 18 | M | 3 | 3 | class3 | 5 | | 3 | Lucy | 21 | F | 6 | 6 | class6 | 1 | | 4 | Jimima | 15 | F | 4 | 4 | class4 | 2 | | 5 | Jimmy | 30 | M | 9 | NULL | NULL | NULL | | 6 | Jim | 26 | M | 7 | NULL | NULL | NULL | | 7 | Cora | 25 | F | 6 | 6 | class6 | 1 | | 8 | Echo | 58 | F | 7 | NULL | NULL | NULL | | 9 | 張三 | 47 | M | 3 | 3 | class3 | 5 | +-----------+--------+------+--------+---------+---------+--------+-----------+
右外聯結(語法:左表 RIGHT JION 右表 ON 條件)
顯示各個班級有哪些同窗,若是這個班級沒有同窗就留空:
mysql> SELECT * FROM students_tb RIGHT JOIN classes_tb ON students_tb.ClassID=classes_tb.ClassID; +-----------+--------+------+--------+---------+---------+--------+-----------+ | StudentID | Name | Age | Gender | ClassID | ClassID | Class | TeacherID | +-----------+--------+------+--------+---------+---------+--------+-----------+ | 1 | Tom | 17 | M | 1 | 1 | class1 | 5 | | NULL | NULL | NULL | NULL | NULL | 2 | class2 | 2 | | 2 | Jack | 18 | M | 3 | 3 | class3 | 5 | | 9 | 張三 | 47 | M | 3 | 3 | class3 | 5 | | 4 | Jimima | 15 | F | 4 | 4 | class4 | 2 | | NULL | NULL | NULL | NULL | NULL | 5 | class5 | 4 | | 3 | Lucy | 21 | F | 6 | 6 | class6 | 1 | | 7 | Cora | 25 | F | 6 | 6 | class6 | 1 | +-----------+--------+------+--------+---------+---------+--------+-----------+
全外聯結:
mysql無全外聯結
6.2.二、聯合查詢:UNION
mysql> SELECT Name,Age FROM teacher_tb WHERE Age > 40 UNION SELECT Name,Age FROM students_tb WHERE Age > 30; +-----------+------+ | Name | Age | +-----------+------+ | Ying hui | 50 | | Feng bing | 46 | | Shun bin | 68 | | Echo | 58 | | 張三 | 47 | +-----------+------+
查詢同窗所對應的負責老師:
mysql> SELECT students_tb.Name AS student_name,teacher_tb.Name AS teacher_name FROM students_tb,classes_tb,teacher_tb WHERE students_tb.ClassID=classes_tb.ClassID AND classes_tb.TeacherID=teacher_tb.TeacherID; +--------------+----------------+ | student_name | teacher_name | +--------------+----------------+ | Tom | Feng bing | | Jack | Feng bing | | 張三 | Feng bing | | Jimima | Zhang shanfeng | | Lucy | Wang baoqiang | | Cora | Wang baoqiang | +--------------+----------------+
6.2.三、內聯結:INNER JON...ON
語法:
表1 AS 別名1 INNER JOIN 表1 AS 別名2 ON 別名1.字段=別名2.字段
mysql> SELECT * FROM students_tb AS s INNER JOIN classes_tb AS c ON s.ClassID = c.ClassID; +-----------+--------+------+--------+---------+---------+--------+-----------+ | StudentID | Name | Age | Gender | ClassID | ClassID | Class | TeacherID | +-----------+--------+------+--------+---------+---------+--------+-----------+ | 1 | Tom | 17 | M | 1 | 1 | class1 | 5 | | 2 | Jack | 18 | M | 3 | 3 | class3 | 5 | | 12 | 張三 | 47 | M | 3 | 3 | class3 | 5 | | 4 | Jimima | 15 | F | 4 | 4 | class4 | 2 | | 3 | Lucy | 21 | F | 6 | 6 | class6 | 1 | | 10 | Cora | 25 | F | 6 | 6 | class6 | 1 | +-----------+--------+------+--------+---------+---------+--------+-----------+
6.三、子查詢
6.3.一、WHERE子查詢
顯示年齡大於平均年齡的學生:
mysql> SELECT Name,Age FROM students_tb WHERE Age > (SELECT AVG(Age) FROM students_tb); +--------+------+ | Name | Age | +--------+------+ | Jimmy | 30 | | Echo | 58 | | 張三 | 47 | +--------+------+
查詢學生表中給定來存在的班級的學生信息:
mysql> SELECT * FROM classes_tb; +---------+--------+-----------+ | ClassID | Class | TeacherID | +---------+--------+-----------+ | 1 | class1 | 5 | | 2 | class2 | 2 | | 3 | class3 | 5 | | 4 | class4 | 2 | | 5 | class5 | 4 | | 6 | class6 | 1 | +---------+--------+-----------+ #只有6個班級 mysql> SELECT Name,ClassID FROM students_tb WHERE ClassID NOT IN (SELECT ClassID FROM classes_tb); +-------+---------+ | Name | ClassID | +-------+---------+ | Jimmy | 9 | | Jim | 7 | | Echo | 7 | +-------+---------+ #7和9這兩個班級是不存在的
查詢各個班級中同窗年齡大於全校平均年齡的同窗的個數:
mysql> SELECT ClassID,COUNT(Name) FROM students_tb WHERE Age > (SELECT AVG(Age) FROM students_tb) GROUP BY ClassID; +---------+-------------+ | ClassID | COUNT(Name) | +---------+-------------+ | 3 | 1 | | 7 | 1 | | 9 | 1 | +---------+-------------+ mysql> SELECT Name,Age,ClassID FROM students_tb WHERE Age > (SELECT AVG(Age) FROM students_tb); #驗證上邊的結果 +--------+------+---------+ | Name | Age | ClassID | +--------+------+---------+ | Jimmy | 30 | 9 | | Echo | 58 | 7 | | 張三 | 47 | 3 | +--------+------+---------+
6.3.二、FROM子查詢:
查詢表中男性同窗中年齡大於20的:
mysql> SELECT * FROM (SELECT Name,Age,Gender FROM students_tb WHERE Gender='M') AS S WHERE Age > 20; +--------+------+--------+ | Name | Age | Gender | +--------+------+--------+ | Jimmy | 30 | M | | Jim | 26 | M | | 張三 | 47 | M | +--------+------+--------+
mysql中對子查詢優化頗有限,建議不要使用子查詢,可改成其餘的簡單查詢或聯合查詢。