慢談MYSQL經常使用SQL語句

目錄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中對子查詢優化頗有限,建議不要使用子查詢,可改成其餘的簡單查詢或聯合查詢。

相關文章
相關標籤/搜索