1. 程式人生 > >MySQL(二)------SQL基礎

MySQL(二)------SQL基礎

一、SQL簡介

       SQL(Structure Query Language) 是結構化查詢語言,是關係型資料庫的應用語言,大多數關係型資料庫都支援SQL作為底層會話語言。

二、SQL使用入門

       在介紹標準SQL語言的同時,我們會根據MySQL自身的特點進行擴充套件,這樣我們不僅掌握了標準SQL語言,也對MySQL的擴充套件有所瞭解。

2.1  SQL分類

       SQL語句主要分為三類:

  • DDL(資料定義語言):這些語句定義了不同的資料段、資料庫、表、列、索引等資料庫物件。常用關鍵字有create、drop、alter等。
  • DML(資料操縱語言):用於新增、刪除、更新和查詢資料庫記錄,並檢查資料完整性。常用關鍵字有insert、delete、update和select等。
  • DCL(資料控制語言):用於控制不同資料段直接的許可和訪問級別的語句。它定義了資料庫、表、欄位、使用者的訪問許可權和安全級別。主要關鍵字有grant、revoke等。

2.2  DDL語句

        DDL語句一般用於定義資料庫的框架結構,比如表的建立定義及框架修改,與DML最大區別就在於DML一般只涉及表內資料的增刪改查,不涉及表結構的變動,因此,一般DDL語言有資料庫管理員使用較多,DML語言右開發人員使用較多。

       下面將通過具體的例子來介紹MySQL中DDL語句的使用方法。

       1.  建立資料庫

          建立資料庫:

mysql> create database test1;
Query OK, 1 row affected (0.00 sec)

           解釋一下建立語句下面系統反饋回來的提示資訊:“Query ok”表示上面的語句執行成功;“ 1 row affected ”表示操作隻影響了資料庫中一行的記錄;“ 0.00sec ”則記錄了操作執行的時間,這裡由於太快,時間近乎為0 。

 如果再次執行該語句就會報錯,表示同名數據庫存在,不能建立:

mysql> create database test1;
ERROR 1007 (HY000): Can't create database 'test1'; database exists

          顯示當前系統中都有哪些資料庫:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| campus             |
| china              |
| magna              |
| mydb               |
| mysql              |
| performance_schema |
| student_score      |
| sys                |
| test1              |
| userinfo           |
| whatsmodel         |
+--------------------+
12 rows in set (0.00 sec)

解釋一下,除了information_schema , mysql , performance_schema , sys四個是系統自帶的資料庫外(根據版本不同,名字可能有差別,這裡是是5.7版本),其餘的都是自己建立的資料庫。

  • information_schema提供了訪問資料庫元資料的方式。(元資料是關於資料的資料,如資料庫名或表名,列的資料型別,或訪問許可權等。有時用於表述該資訊的其他術語包括“資料詞典”和“系統目錄”。) 換句換說,information_schema是一個資訊資料庫,它儲存著關於MySQL伺服器所維護的所有其他資料庫的資訊。(如資料庫名,資料庫的表,表欄的資料型別與訪問權 限等。)
  • mysql,核心資料庫,類似於sql server中的master表,主要負責儲存資料庫的使用者、許可權設定、關鍵字等mysql自己需要使用的控制和管理資訊。(常用的,在mysql.user表中修改root使用者的密碼)。
  • performance_schema主要用於收集資料庫伺服器效能引數。並且庫裡表的儲存引擎均為PERFORMANCE_SCHEMA,而使用者是不能建立儲存引擎為PERFORMANCE_SCHEMA的表。MySQL5.7預設是開啟的。
  • Sys庫所有的資料來源來自:performance_schema。目標是把performance_schema的把複雜度降低,讓DBA能更好的閱讀這個庫裡的內容。讓DBA更快的瞭解DB的執行情況。

選擇資料庫:use dbname

例如選擇資料庫test1:

mysql> use test1;
Database changed

檢視當前資料庫裡面的表:

mysql> show tables;
Empty set (0.00 sec)
由於test1是一個剛建立的資料庫,裡面還沒有表,因此展示的結果是一個空集合

       2.  刪除資料庫

          命令為 drop database dbname;   如刪掉剛才建立的test1:

mysql> drop database test1;
Query OK, 0 rows affected (0.01 sec)
執行成功,但是這個0行受影響可能有點費解,但是不用管,因為mysql裡面drop操作都是這個結果。

注意:刪除庫要非常慎重,一旦刪除裡面的內容全部丟失且不可恢復,常聽的程式設計師“刪庫跑路”就是這麼回事。

          3. 建立表

             基本語法: CREATE TABLE 表名(列1的名字 資料型別 約束條件,列2的名字 資料型別 約束條件,....),比如這裡在資料庫test1裡面建立一張名為emp的表:

查看錶結構:desc tablename;

用desc命令檢視的資訊不全面,用如下命令可以檢視到建立時的SQL語句及更多詳細資訊:

mysql> show create table emp \G;    \G使記錄按照欄位豎向排列,易於閱讀
*************************** 1. row ***************************
       Table: emp
Create Table: CREATE TABLE `emp` (
  `ename` varchar(10) DEFAULT NULL,
  `hiredate` date DEFAULT NULL,
  `sal` decimal(10,2) DEFAULT NULL,
  `deptno` int(2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8           表的儲存引擎和字符集等資訊
1 row in set (0.00 sec)

ERROR:
No query specified

mysql>

       4. 刪除表

          語句命令為:drop table tablename;

mysql> drop table emp;
Query OK, 0 rows affected (0.00sec)

     5. 修改表

       對於一開始建立的表可能不夠完整,後面有新的需求需要將表進行擴充,這時候就需要用到表結構修改語言,但如果你選擇刪除原來的表按要求建一個新表的話也可以,但是相應的資料需要重新載入,如果表正在使用對伺服器也會有影響。

       (1)修改表型別

          alter table tablename modify [column] column_definition [first | after col_name]

例如將emp表中的ename型別修改為20個位元組寬度:

mysql> alter table emp modify ename varchar(20);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql>

       (2)增加表字段

          alter table tablename add [column] column_definition [first | after col_name]

例如再表中新增欄位age,型別為int(3):

mysql> alter table emp add column age int(3);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age      | int(3)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

       (3)刪除表字段

          alter table tablename drop [column] col_name

例如將age欄位刪掉:

mysql> alter table emp drop column age;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

       (4)欄位改名

          alter table tablename change [column] old_col_name column_definition

例如將age改名為age1,同時修改欄位型別為int(4):

mysql> alter table emp add column age int(3);
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table emp change column age age1 int(4);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age1     | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

注意:change和modify都可以修改表的欄位型別,不同的是change需要寫兩次列名,不方便,但change可以修改列名而modify不能。

       (5)修改欄位的排列順序

          上面介紹的命令中有一個可選項 first | after column_name ,如果不使用的話ADD增加的欄位預設在表的最後,CHANGE/MODIFY修改不會改變欄位位置,但使用了這個可選項後就可以指定位置了;例如新增欄位birth date在ename之後:

mysql> alter table emp add birth date after ename;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age1     | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

修改age1為age int(3) 並放在最前:

mysql> alter table emp change age1 age int(3) first;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| age      | int(3)        | YES  |     | NULL    |       |
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

注意:CHANGE/FIRST|AFTER COLUMN 這些關鍵字屬於MySQL在SQL上的擴充套件,別的資料庫上不一定適用。

         (6)更改表名

           alter table tablename rename [to] new_tablename

如將表emp改為emp1:

mysql> alter table emp rename emp1;
Query OK, 0 rows affected (0.01 sec)

mysql> desc emp;
ERROR 1146 (42S02): Table 'test1.emp' doesn't exist
mysql> desc emp1;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| age      | int(3)        | YES  |     | NULL    |       |
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

2.3  DML語句

       DML操作是對資料庫中表記錄的操作,主要包括插入(insert)、更新(update)、刪除(delete)、查詢(select)。

     1. 插入記錄

        表的結構定義好之後就可往裡面插入記錄了,基本語法如下:

        INSERT INTO tablename ( field1, field2,...) VALUES (value1,value2,....);

例如向表emp中插入記錄:

mysql> insert into emp1 (age,ename,birth, hiredate, sal, deptno) values('22','zzx1','1992-10-11','2018-01-01','5000',1);
Query OK, 1 row affected (0.00 sec)

也可以不用指定欄位名稱,但此時後面的values應該與表的欄位順序保持一致:

mysql> insert into emp1 values('25','lisa','1990-05-11','2018-03-25','8000',2);
Query OK, 1 row affected (0.00 sec)

對於某些欄位允許空值、非空但是有指定的預設值、自增長等,這些欄位在insert時如果沒有指定value,那麼將會右系統自動配置,如:

mysql> insert into emp1 (ename,sal) values('dony',1000);
Query OK, 1 row affected (0.00 sec)

mysql> select * from emp1;
+------+-------+------------+------------+---------+--------+
| age  | ename | birth      | hiredate   | sal     | deptno |
+------+-------+------------+------------+---------+--------+
|   22 | zzx1  | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa  | 1990-05-11 | 2018-03-25 | 8000.00 |      2 |
| NULL | dony  | NULL       | NULL       | 1000.00 |   NULL |
+------+-------+------------+------------+---------+--------+
3 rows in set (0.00 sec)

insert還有一個較好的效能就是可以一次性插入多條記錄,語法如下:

INSERT INTO tablename ( field1, field2,...) VALUES (value1,value2,....),(value1,value2,....), ..... ;

這個效能使得MySQL在插入大量記錄時,節省很多網路開銷,大大提高插入效率。

     2. 更新記錄

       UPDATE tablename SET field1=value1,field2=value2,... [ WHERE CONDITION ]

例如將emp表中lisa的薪水改為4000:

mysql> update emp1 set sal=4000 where ename='lisa';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MySQL裡update命令允許對多個表同時進行更新:

        UPDATE t1, t2, ..tn SET t1.field1=expr1,... , tn.fieldn=exprn  [ WHERE CONDITION ]

比如下面這條語句:

update emp a, dept b set a.sal=a.sal*b.deptno, b.deptname=a.ename where a.deptno=b.deptno;

注意:多表更新的語法更多的用在根據一個表的欄位來動態更新另一個表的欄位。

     3. 刪除記錄

        DELETE FROM tablename [WHERE CONDITION ]

例如刪除emp中dony的那條記錄:

mysql> delete from emp1 where ename='dony';
Query OK, 1 row affected (0.00 sec)

MySQL中也可以一次刪除多個表的資料:

         DELETE t1, t2,...., tn FROM t1, t2,...., tn  [WHERE CONDITION ]

例如:

delete a,b from emp a, dept b where a.deptno=b.deptno and a.deptno=3;

注意:不管是刪單表還是多表,如果不加條件語句就會將整張表刪除,因此使用時要非常小心。

      4. 查詢記錄

        查詢語句SELECT是用得最多同時也是最複雜的語句,它的多種條件組合可以使我們查到想要的資訊。

最簡單的查詢語句:查表內的所有內容     SELECT * FROM tablename [ WHERE CONDITION ]

mysql> select * from emp1;        * 表示將表內的所有行和列都查找出來
+------+-------+------------+------------+---------+--------+
| age  | ename | birth      | hiredate   | sal     | deptno |
+------+-------+------------+------------+---------+--------+
|   22 | zzx1  | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa  | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
+------+-------+------------+------------+---------+--------+
2 rows in set (0.00 sec)


mysql> select age,ename,birth,hiredate,sal, deptno from emp1;  將*替換為表內的所有欄位效果一樣
+------+-------+------------+------------+---------+--------+
| age  | ename | birth      | hiredate   | sal     | deptno |
+------+-------+------------+------------+---------+--------+
|   22 | zzx1  | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa  | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
+------+-------+------------+------------+---------+--------+
2 rows in set (0.00 sec)

注意:*號有好處有壞處,好處在於寫法簡單不用將所有欄位都列出來,壞處在於一次性查所有內容使得查詢速度較慢。

    (1) 查詢不重複的記錄

      使用distinct關鍵字標記要查詢的內容,這樣就會將查詢的結果去掉重複值後顯示出來

例如下面的語句:

mysql> insert into emp1 values('28','bjguan','1987-07-12','2014-06-08','8000',1); 加一條記錄使deptno有重複值
Query OK, 1 row affected (0.00 sec)

mysql> select * from emp1;
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
+------+--------+------------+------------+---------+--------+
3 rows in set (0.00 sec)

mysql> select distinct deptno from emp1;       加distinct關鍵字使得查出的結果中去掉了重複記錄
+--------+
| deptno |
+--------+
|      1 |
|      2 |
+--------+
2 rows in set (0.00 sec)

    (2) 條件查詢

        關鍵字WHERE實現根據不同的條件來查詢所需結果

例如查詢deptno=1的所有記錄:

mysql> select * from emp1 where deptno=1;
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
+------+--------+------------+------------+---------+--------+
2 rows in set (0.00 sec)

判斷條件可以使用=、>、<、>=、<=、!=等等,同時多個條件還可以使用and、or等進行連線,例如下面的例子:

mysql> select * from emp1 where deptno=1 and sal<6000;
+------+-------+------------+------------+---------+--------+
| age  | ename | birth      | hiredate   | sal     | deptno |
+------+-------+------------+------------+---------+--------+
|   22 | zzx1  | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
+------+-------+------------+------------+---------+--------+
1 row in set (0.00 sec)

    (3) 排序和限制

      使用關鍵字ORDER BY來實現對查找出來的結果按某一欄位進行排序,語法如下:

      SELECT * FROM tablename [ WHERE CONDITION ] [ ORDER BY field1 [ DESC\ASC ], field2 [ DESC\ASC], ..]

DESC表示降序,ASC表示升序,如果都沒有指定的話預設為升序。

mysql> select * from emp1 order by sal;         預設按薪水升序排列
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
+------+--------+------------+------------+---------+--------+
3 rows in set (0.00 sec)

排序的欄位可以是一個,也可以是多個;當排序欄位只有一個且記錄中有相同值時,此時這兩個相同值的排序位置不確定,但當排序欄位有多個時遇到這種情況就會根據第二欄位來排序,如果第二欄位中也有這種問題存在就會根據第三欄位排,以此類推。

mysql> select * from emp1 order by deptno,sal desc;   按deptno升序排列,如遇到相同值則按對應的sal降序排列
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
+------+--------+------------+------------+---------+--------+
3 rows in set (0.00 sec)

        LIMIT關鍵字設定查詢出來的記錄從第幾條開始顯示,一共顯示多少條;基本語法如下:

        SELECT ... [ LIMIT offset_start, row_count ]

例如:

mysql> insert into emp1 values('30','bzshen','1990-04-06','2016-06-07','7000',3); 增加一條記錄
Query OK, 1 row affected (0.00 sec)
 
mysql> select * from emp1 order by sal limit 1,3;     按薪水排序後,從第二條開始一共取三條記錄顯示,這裡的1由於是從0開始數,因此表示第二條記錄
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   30 | bzshen | 1990-04-06 | 2016-06-07 | 7000.00 |      3 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
+------+--------+------------+------------+---------+--------+
3 rows in set (0.00 sec)

limit經常和order by一起配合使用來進行記錄的分頁顯示;

注意:limit屬於MySQL對SQL語句的擴充套件,在其它資料庫上並不適用。

    (4) 聚合

      該操作主要是對資料進行統計彙總,主要語法如下:

      SELECT [ field1, field2,...,fieldn] fun_name FROM tablename [ WHERE CONDITION ] 

      [ GROUP BY field1, field2,..., fieldn  [ WITH ROLLUP ] ]  [ HAVING  condition ]

引數說明:fun_name 聚合函式,表示要做的聚合操作,常用的有sum(求和)、count(*)(計數)、max、min等。

                  GROUP BY  表示對後面的欄位進行分類聚合(也常叫分組);

                  WITH ROLLUP 可選語法,在ORDER BY 語句內出現,表示是否對分類聚合後的結果進行再彙總;

                  HAVING 表示對分類後的結果再進行條件過濾;

      注意:同樣是條件過濾,having合where的區別在於,having是對聚合後的結果進行條件過濾,而where是在聚合前就對記錄進行過濾。因此,為了提高聚合效率,一般先用where過濾不相干的記錄後,在進行聚合,最後再用having進行二次過濾。

下面看具體的例子:

mysql> select count(*) from emp1;       統計公司總人數(因為一條記錄代表一個人)
+----------+
| count(*) |
+----------+
|        4 |
+----------+
1 row in set (0.00 sec)

mysql> select deptno,count(*) from emp1 group by deptno;    統計各部門的人數
+--------+----------+
| deptno | count(*) |
+--------+----------+
|      1 |        2 |
|      2 |        1 |
|      3 |        1 |
+--------+----------+
3 rows in set (0.00 sec)

mysql> select deptno,count(*) from emp1 group by deptno with rollup;   統計各部門的人數並且要彙總得到總人數
+--------+----------+
| deptno | count(*) |
+--------+----------+
|      1 |        2 |
|      2 |        1 |
|      3 |        1 |
|   NULL |        4 |
+--------+----------+
4 rows in set (0.00 sec)

mysql> select deptno,count(*) from emp1 group by deptno having count(*) > 1;  統計人數大於1的部門
+--------+----------+
| deptno | count(*) |
+--------+----------+
|      1 |        2 |
+--------+----------+
1 row in set (0.00 sec)

mysql> select sum(sal),max(sal),min(sal) from emp1;  統計公司的薪水總額及最高、最低薪水
+----------+----------+----------+
| sum(sal) | max(sal) | min(sal) |
+----------+----------+----------+
| 24000.00 |  8000.00 |  4000.00 |
+----------+----------+----------+
1 row in set (0.00 sec)

        (5) 表連線

           當需要同時顯示多個表中的欄位時,就可以用表連線來實現這樣的功能。

           表連線主要有內連線和外連線,內連線僅選出兩張表中相互匹配的部分,而外連線又分為左連線和右連線,左連線包含所有的左表中的記錄哪怕右表中沒有和它匹配的記錄;右連線包含所有的右表中的記錄哪怕左表中沒有和它匹配的記錄;

mysql> create table dept(deptno int(2),deptname varchar(10));   建立一個新的部門表
Query OK, 0 rows affected (0.03 sec)

mysql> insert into dept values(1,'tech'),(2,'scale'),(3,'hr');   為部門表中插入3條記錄
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from dept;
+--------+----------+
| deptno | deptname |
+--------+----------+
|      1 | tech     |
|      2 | scale    |
|      3 | hr       |
+--------+----------+
3 rows in set (0.00 sec)

mysql> select * from emp1;
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
|   30 | bzshen | 1990-04-06 | 2016-06-07 | 7000.00 |      3 |
|   24 | dony   | 1989-11-14 | 2014-06-26 | 6000.00 |      4 |
+------+--------+------------+------------+---------+--------+
5 rows in set (0.00 sec)

現在表連線的方法來查出所有僱員的名字和所在部門:

使用兩個表中的相同欄位deptno作為條件連線兩個表
mysql> select ename,deptname from emp1,dept where emp1.deptno=dept.deptno;
+--------+----------+
| ename  | deptname |
+--------+----------+
| zzx1   | tech     |
| lisa   | scale    |
| bjguan | tech     |
| bzshen | hr       |
+--------+----------+
4 rows in set (0.00 sec)


使用內連線關鍵字inner join 
mysql> select ename,deptname from emp1 inner join dept on emp1.deptno=dept.deptno;
+--------+----------+
| ename  | deptname |
+--------+----------+
| zzx1   | tech     |
| lisa   | scale    |
| bjguan | tech     |
| bzshen | hr       |
+--------+----------+
4 rows in set (0.00 sec)

mysql> select * from emp1 inner join dept on emp1.deptno=dept.deptno;
+------+--------+------------+------------+---------+--------+--------+----------+
| age  | ename  | birth      | hiredate   | sal     | deptno | deptno | deptname |
+------+--------+------------+------------+---------+--------+--------+----------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |      1 | tech     |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |      2 | scale    |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |      1 | tech     |
|   30 | bzshen | 1990-04-06 | 2016-06-07 | 7000.00 |      3 |      3 | hr       |
+------+--------+------------+------------+---------+--------+--------+----------+
4 rows in set (0.00 sec)

從上面的兩條inner join語句我們可以看出,內連線是將兩張表中的共同欄位作為條件進行合併得到一張兩表交集的大表,然後就可以選擇這張大表中的具體欄位來進行顯示,比如*號選擇全部欄位。

使用左連線:可以看出左表的內容全部保留,右表中不存在的置為NULL,若有超過的則不顯示。

mysql> select ename,deptname from emp1 left join dept on emp1.deptno=dept.deptno;
+--------+----------+
| ename  | deptname |
+--------+----------+
| zzx1   | tech     |
| bjguan | tech     |
| lisa   | scale    |
| bzshen | hr       |
| dony   | NULL     |
+--------+----------+
5 rows in set (0.00 sec)

mysql> select * from emp1 left join dept on emp1.deptno=dept.deptno;
+------+--------+------------+------------+---------+--------+--------+----------+
| age  | ename  | birth      | hiredate   | sal     | deptno | deptno | deptname |
+------+--------+------------+------------+---------+--------+--------+----------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |      1 | tech     |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |      1 | tech     |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |      2 | scale    |
|   30 | bzshen | 1990-04-06 | 2016-06-07 | 7000.00 |      3 |      3 | hr       |
|   24 | dony   | 1989-11-14 | 2014-06-26 | 6000.00 |      4 |   NULL | NULL     |
+------+--------+------------+------------+---------+--------+--------+----------+
5 rows in set (0.00 sec)

使用右連線:與左連線相似,只需要更改兩個表的位置,左連線就可以作為右連線;

mysql> select ename,deptname from dept right join emp1 on dept.deptno=emp1.deptno;
+--------+----------+
| ename  | deptname |
+--------+----------+
| zzx1   | tech     |
| bjguan | tech     |
| lisa   | scale    |
| bzshen | hr       |
| dony   | NULL     |
+--------+----------+
5 rows in set (0.00 sec)

      (6) 子查詢

         在某些情況下,在進行查詢的時候需要的條件是另外一個select語句的結果時,往往用到子查詢,它的關鍵字主要有in、not in、=、!=、exists、not exists等。

例如在emp表中查出在dept表中有記錄的所有資訊:

mysql> select * from emp1 where deptno in (select deptno from dept);
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
|   30 | bzshen | 1990-04-06 | 2016-06-07 | 7000.00 |      3 |
+------+--------+------------+------------+---------+--------+
4 rows in set (0.00 sec)

當子查詢中查出的記錄只有一條時,in可以用 = 代替
mysql> select * from emp1 where deptno=(select deptno from dept);
ERROR 1242 (21000): Subquery returns more than 1 row
mysql> select * from emp1 where deptno=(select deptno from dept limit 1);
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
+------+--------+------------+------------+---------+--------+
2 rows in set (0.00 sec)

在某些特殊的情況下,子查詢可以轉化為表連線:

mysql> select * from emp1 where deptno in (select deptno from dept);
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
|   30 | bzshen | 1990-04-06 | 2016-06-07 | 7000.00 |      3 |
+------+--------+------------+------------+---------+--------+
4 rows in set (0.00 sec)

mysql> select emp1.* from emp1,dept where emp1.deptno=dept.deptno;
+------+--------+------------+------------+---------+--------+
| age  | ename  | birth      | hiredate   | sal     | deptno |
+------+--------+------------+------------+---------+--------+
|   22 | zzx1   | 1992-10-11 | 2018-01-01 | 5000.00 |      1 |
|   25 | lisa   | 1990-05-11 | 2018-03-25 | 4000.00 |      2 |
|   28 | bjguan | 1987-07-12 | 2014-06-08 | 8000.00 |      1 |
|   30 | bzshen | 1990-04-06 | 2016-06-07 | 7000.00 |      3 |
+------+--------+------------+------------+---------+--------+

注意:在以下兩種情況下會用到子查詢和表連線之間的轉化。

  •   MySQL4.1 之前的版本不支援子查詢,因此在使用老版資料庫時需要用表連線;
  •  表連線查詢效能優於子查詢,因此往往用來優化子查詢語句。

    (7) 記錄聯合

       有時候我們需要將兩個表的資料按照一定的查詢條件查詢出來後,將結果合併到一起顯示出來(這裡的合併是豎向合併而不是表連線那樣的橫向合併);使用關鍵字union、union all來實現。語法如下:

        SELECT * FROM t1  UNION | UNION ALL  SELECT * FROM t2 ......(一直寫一直連)

例如下面的例子,將emp1表和dept表中部門標號的集合顯示出來:

mysql> select deptno from emp1 union all select deptno from dept;
+--------+
| deptno |
+--------+
|      1 |
|      2 |
|      1 |
|      3 |
|      4 |
|      1 |
|      2 |
|      3 |
+--------+
8 rows in set (0.01 sec)

mysql> select deptno from emp1 union select deptno from dept;
+--------+
| deptno |
+--------+
|      1 |
|      2 |
|      3 |
|      4 |
+--------+
4 rows in set (0.00 sec)

可以看到union all 是將結果集直接合並在一起,而union 則是進行了去重。

2.4  DCL語句

          DCL語句主要是DBA用來管理系統中的物件許可權時使用,一般開發人員用的較少。下面通過一個例子簡單說明一下:

建立z1使用者,密碼為123,對資料庫test1裡的所有表具有查詢和插入許可權
mysql> grant select,insert on test1.* to 'z1'@'localhost' identified by '123';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> exit
Bye

使用者z1登陸,這裡提示密碼最好不要直接寫在在命令列,會有風險
C:\Users\15330>mysql -u z1 -p123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 5.7.17-log MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use test1;      登陸後該使用者對test1庫內的表插入操作都是成功的
Database changed
mysql> insert into emp1 values('24','hwtong','1989-07-24','2017-08-16','10000',5);
Query OK, 1 row affected (0.01 sec)

當用戶許可權有變更時,比如需要收回使用者z1的插入許可權:

首先我們需要登陸最高許可權賬戶來進行修改
mysql> revoke insert on test1.* from 'z1'@'localhost';   該命令就收回了使用者z1的插入許可權
Query OK, 0 rows affected (0.00 sec)

mysql> exit
Bye


此時z1使用者登陸再執行插入命令就會出錯:
C:\Users\15330>mysql -u z1 -p123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 5.7.17-log MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use test1;
Database changed
mysql> insert into emp1 values('24','hwtong','1989-07-24','2017-08-16','10000',5);
ERROR 1142 (42000): INSERT command denied to user 'z1'@'localhost' for table 'emp1'
mysql>

            這裡只是簡單的介紹一下,後面會更詳細的介紹相關內容。

三、幫助命令的使用

          再實際使用MySQL時,經常會遇到以下問題:

  • 某個操作語法忘記了,如何快速查詢?
  • 如何快速知道當前版本上某個欄位型別的取值範圍?
  • 當前版本都支援哪些函式?有沒有例子?
  • 當前版本是否支援某個功能?

           對於這些疑問MySQL的官方文件都有詳細說明,但是每次都去查文件太費時間,MySQL有一些快捷的方法來幫你快速的查到相關內容。

3.1  按照層次看幫助

        如果不太確定具體查什麼可以用 “ ?contents ”命令來顯示所有可供查詢的分類:

mysql> ? contents
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following
categories:
   Account Management
   Administration
   Compound Statements
   Data Definition
   Data Manipulation
   Data Types
   Functions
   Functions and Modifiers for Use with GROUP BY
   Geographic Features
   Help Metadata
   Language Structure
   Plugins
   Procedures
   Storage Engines
   Table Maintenance
   Transactions
   User-Defined Functions
   Utility

根據分類列出的類別名稱我們可以使用“ ? 類別名 ” 來做進一步檢視:

mysql> ? data types           檢視當前版本資料庫支援的所有資料型別
You asked for help about help category: "Data Types"
For more information, type 'help <item>', where <item> is one of the following
topics:
   AUTO_INCREMENT
   BIGINT
   BINARY
   BIT
   BLOB
   BLOB DATA TYPE
   BOOLEAN
   CHAR
   CHAR BYTE
   DATE
   DATETIME
   DEC
   DECIMAL
   DOUBLE
   DOUBLE PRECISION
   ENUM
   FLOAT
   INT
   INTEGER
   LONGBLOB
   LONGTEXT
   MEDIUMBLOB
   MEDIUMINT
   MEDIUMTEXT
   SET DATA TYPE
   SMALLINT
   TEXT
   TIME
   TIMESTAMP
   TINYBLOB
   TINYINT
   TINYTEXT
   VARBINARY
   VARCHAR
   YEAR DATA TYPE

也可以繼續檢視某一資料型別的詳細資訊:

mysql> ? int
Name: 'INT'
Description:
INT[(M)] [UNSIGNED] [ZEROFILL]

A normal-size integer. The signed range is -2147483648 to 2147483647.
The unsigned range is 0 to 4294967295.

URL: http://dev.mysql.com/doc/refman/5.7/en/numeric-type-overview.html

           這就是層次化的查詢方式。

3.2 快速查閱幫助

           使用關鍵子快速查閱:

mysql> ? show        可以查到show的所有用法
Name: 'SHOW'
Description:
SHOW has many forms that provide information about databases, tables,
columns, or status information about the server. This section describes
those following:

SHOW {BINARY | MASTER} LOGS
SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
SHOW CHARACTER SET [like_or_where]
SHOW COLLATION [like_or_where]
SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [like_or_where]
SHOW CREATE DATABASE db_name
SHOW CREATE EVENT event_name
SHOW CREATE FUNCTION func_name
。。。。。
mysql> ? create table        可以查到該語法的相關命令
Name: 'CREATE TABLE'
Description:
Syntax:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    (create_definition,...)
    [table_options]
    [partition_options]

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(create_definition,...)]
    [table_options]
    [partition_options]
    [IGNORE | REPLACE]
    [AS] query_expression

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    { LIKE old_tbl_name | (LIKE old_tbl_name) }
...........

3.3  MySQL的相關資源

       http://dev.mysql.com/downloads             官方網站,可下載MySQL資料庫

       http://dev.mysql.com/doc                         官方文件

       http://bugs.mysql.com                              已釋出的bug列表,也可以報告你發現的bug

       http://www.mysql.com/news-and-events/newsletter       MySQL的最新訊息都在這裡面

四、查詢元資料資訊

         元資料指的是資料的資料,比如表名,列名,列型別,索引名等表的各種屬性名稱;MySQL5.0之後有一個數據庫information_schema,用來記錄元資料資訊。

         有了這些資訊我們可以實現很多操作,比如刪除資料庫裡有某個指定字首的表,修改表的儲存引擎等等;作用很多,後面遇到再慢慢記錄吧。