1. 程式人生 > >mysql命令詳解

mysql命令詳解

首先建立一個簡單的user表
CREATE TABLE `user` (
`id`  int NOT NULL AUTO_INCREMENT ,
`name`  varchar(255) NULL ,
`sex`  varchar(255) NULL ,
`age`  int NULL ,
`address`  varchar(255) NULL ,
PRIMARY KEY (`id`)
)
;
然後插入資料
insert into `user`(`name`,`sex`,`age`,`address`) values('張三','男',22,'北京') ;
insert into `user`(`name`,`sex`,`age`,`address`) values('李四','男',12,'河北') ;
insert into `user`(`name`,`sex`,`age`,`address`) values('王五','女',23,'江蘇') ;
insert into `user`(`name`,`sex`,`age`,`address`) values('趙六','男',21,'北京') ;


1.修改某一個欄位的名稱(例如修改地址)
alter table user modify address varchar(50) ;
2.把user表中某些欄位的值複製出來,變成另外一個表
create table user2 as select id,name from user ;
3.刪除user表
drop table user [restrict|cascade] ;
4.建立表的時候加上外來鍵約束
constraint ID_FK  foreign key(id) references user2(id) ;
修改表的外來鍵關係
alter table user add constraint ID_FK  foreign key(id) references user2(id) ;
5.新增表的檢查約束
alter table user add constraint CHK_SEX check(sex = '男') ;
alter table user add constraint CHK_SEX check(sex in ('男','女')) ;
6.從另一個表插入資料
insert into user (name) select name from user2 ;


事務
是對資料庫執行的一個操作單位。它是以邏輯順序完成的工作單元或工作序列,無論是使用者手工操作,還是由程式進行的自動操作。
控制事務的命令有3個
COMMIT  ROLLBACK  SAVEPOINT
首先把資料庫預設的提交模式改變
set autocommit=0 禁止自動提交
set autocommit=1 開啟自動提交


我們要從表user裡刪除剩餘的資料,在進行每次刪除之前都使用savepoint命令,這樣就可以在任何時候利用rollback命令
回退到任意一個儲存點,從而把適當的資料回覆到原始狀態。
下面是一個事務處理的完整例子:
**********************************
mysql> set autocommit=
0 ;
Query OK, 0 rows affected


mysql> delete from user where id=3 ;
Query OK, 1 row affected
mysql> select * from user ;
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  1 | 張三 | 男  |  22 | 北京    |
|  2 | 李四 | 男  |  12 | 河北    |
+----+------+-----+-----+---------+
2 rows in set


mysql> rollback ;
Query OK, 0 rows affected


mysql> select * from user ;
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  1 | 張三 | 男  |  22 | 北京    |
|  2 | 李四 | 男  |  12 | 河北    |
|  3 | 王五 | 女  |  23 | 江蘇    |
+----+------+-----+-----+---------+
3 rows in set


mysql> savepoint sp1 ;
Query OK, 0 rows affected


mysql> delete from user where id=2 ;
Query OK, 1 row affected
mysql> savepoint sp2 ;
Query OK, 0 rows affected


mysql> delete from user where id=3 ;
Query OK, 1 row affected
mysql> savepoint sp3 ;
Query OK, 0 rows affected


mysql> delete from user where id=1 ;
Query OK, 0 rows affected
mysql> select * from user ;
Empty set


mysql> rollback to sp1 ;
Query OK, 0 rows affected


mysql> select * from user ;
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  1 | 張三 | 男  |  22 | 北京    |
|  2 | 李四 | 男  |  12 | 河北    |
|  3 | 王五 | 女  |  23 | 江蘇    |
+----+------+-----+-----+---------+
3 rows in set
************************************


mysql> release savepoint sp1 ;
Query OK, 0 rows affected
這個命令用於刪除建立的儲存點
。在某個儲存點被釋放之後,就不能再利用rollback命令來撤銷這個儲存點之後的
事務操作了。利用這個命令可以避免意外的回退到某個不再需要的儲存點。


總結:commit用於把事務儲存到資料庫,rollback用於撤銷已經執行了的事務,而savepoint用於把事務劃分成組,
讓我們可以回退到事務過程中特定的邏輯位置。在執行大規模事務操作時,應該經常使用commit和rollback命令來保證
資料庫具有足夠的剩餘空間。另外還要記住,這些事務命令只用於3個DML命令:insert、update和delete。


查詢語句
select all name from user 和 select name from user 用法一樣,都是從表裡查詢出欄位名為name的所有值


mysql> select distinct sex from user ;
+-----+
| sex |
+-----+
| 男  |
| 女  |
+-----+
2 rows in set
查詢出不重複的欄位值distinct。


對查詢出來的內容進行排序order by
,預設是asc也就是升序。
mysql> select * from user order by age
 ; 
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  2 | 李四 | 男  |  12 | 河北    |
|  1 | 張三 | 男  |  22 | 北京    |
|  3 | 王五 | 女  |  23 | 江蘇    |
+----+------+-----+-----+---------+
3 rows in set


mysql> select * from user order by age asc

+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  2 | 李四 | 男  |  12 | 河北    |
|  1 | 張三 | 男  |  22 | 北京    |
|  3 | 王五 | 女  |  23 | 江蘇    |
+----+------+-----+-----+---------+
3 rows in set


mysql> select * from user order by age de
sc; 
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  3 | 王五 | 女  |  23 | 江蘇    |
|  1 | 張三 | 男  |  22 | 北京    |
|  2 | 李四 | 男  |  12 | 河北    |
+----+------+-----+-----+---------+
3 rows in set


排序還可以針對多個欄位,也就是第一個指定的排序欄位如果相等的話,比較第二個欄位的值。以此類推。
mysql> select * from user order by age ;
+----+---------+-----+-----+---------+
| id | name    | sex | age | address |
+----+---------+-----+-----+---------+
|  2 | 李四    | 男  |  12 | hebei   |
|  1 | 張三    | 男  |  22 | beijing |
|  3 | 王五    | 女  |  23 | jiangsu |
|  4 | wuhaixu | nan |  23 | hunan   |
+----+---------+-----+-----+---------+
4 rows in set


mysql> select * from user order by age,address ;
+----+---------+-----+-----+---------+
| id | name    | sex | age | address |
+----+---------+-----+-----+---------+
|  2 | 李四    | 男  |  12 | hebei   |
|  1 | 張三    | 男  |  22 | beijing |
|  4 | wuhaixu | nan |  23 | hunan   |
|  3 | 王五    | 女  |  23 | jiangsu |
+----+---------+-----+-----+---------+
4 rows in set


當然我們還可以用數字代替欄位名,如下所示:整數1代表id,2代表name...


mysql> select * from user order by 4
 ;
+----+---------+-----+-----+---------+
| id | name    | sex | age | address |
+----+---------+-----+-----+---------+
|  2 | 李四    | 男  |  12 | hebei   |
|  1 | 張三    | 男  |  22 | beijing |
|  3 | 王五    | 女  |  23 | jiangsu |
|  4 | wuhaixu | nan |  23 | hunan   |
+----+---------+-----+-----+---------+
4 rows in set


mysql> select * from user order by 4,5 ;
+----+---------+-----+-----+---------+
| id | name    | sex | age | address |
+----+---------+-----+-----+---------+
|  2 | 李四    | 男  |  12 | hebei   |
|  1 | 張三    | 男  |  22 | beijing |
|  4 | wuhaixu | nan |  23 | hunan   |
|  3 | 王五    | 女  |  23 | jiangsu |
+----+---------+-----+-----+---------+


count函式的用法:
mysql> select count(*) as '總數' from user ;
+------+
| 總數 |
+------+
|    4 |
+------+
1 row in set


mysql> select count(distinct sex) as `總數` from user ;
+------+
| 總數 |
+------+
|    3 |
+------+
1 row in set


邏輯操作符:is null、between、in、like、exists、unique、all和any
mysql> select * from user where sex is null ;
Empty set


mysql> select * from user where age between 20 and 22;
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  1 | 張三 | 男  |  22 | beijing |
+----+------+-----+-----+---------+
1 row in set


mysql> select * from user where age in(22,23);
+----+---------+-----+-----+---------+
| id | name    | sex | age | address |
+----+---------+-----+-----+---------+
|  1 | 張三    | 男  |  22 | beijing |
|  3 | 王五    | 女  |  23 | jiangsu |
|  4 | wuhaixu | nan |  23 | hunan   |
+----+---------+-----+-----+---------+
3 rows in set


操作符like利用萬用字元把一個值與類似的值進行比較,下劃線代表一個數字或字元,這些符號可以複合使用。
百分號%代表零個、一個或多個字元,下劃線代表一個數字或字元。這些符號可以複合使用。
mysql> select * from user where address like '%i%';
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  1 | 張三 | 男  |  22 | beijing |
|  2 | 李四 | 男  |  12 | hebei   |
|  3 | 王五 | 女  |  23 | jiangsu |
+----+------+-----+-----+---------+
3 rows in set


mysql> select * from user where address like '__i%';
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  1 | 張三 | 男  |  22 | beijing |
+----+------+-----+-----+---------+
1 row in set


mysql> select * from user where exists (select id from user where age <40) ;
+----+---------+-----+-----+---------+
| id | name    | sex | age | address |
+----+---------+-----+-----+---------+
|  1 | 張三    | 男  |  22 | beijing |
|  2 | 李四    | 男  |  12 | hebei   |
|  3 | 王五    | 女  |  23 | jiangsu |
|  4 | wuhaixu | nan |  23 | hunan   |
+----+---------+-----+-----+---------+
4 rows in set


彙總函式:count、sun、max、min、avg
mysql> select count(*
) from user ;
+----------+
| count(*) |
+----------+
|        5 |
+----------+
1 row in set
count函式配合all使用時,不包含為空的欄位。address有一條為空,所以count為4
mysql> select count(all address) from user ;
+--------------------+
| count(all address) |
+--------------------+
|                  4 |
+--------------------+
1 row in set


mysql> select count(distinct address) from user ;
+-------------------------+
| count(distinct address) |
+-------------------------+
|                       4 |
+-------------------------+
1 row in set


mysql> select sum(age) from user ;
+----------+
| sum(age) |
+----------+
| 102      |
+----------+
1 row in set


如果資料不能隱含地轉化為數值型別,其結果就是0.以name為例:
mysql> select sum(name) from user ;
+-----------+
| sum(name) |
+-----------+
|         0 |
+-----------+
1 row in set


mysql> select avg(name) from user ;
+-----------+
| avg(name) |
+-----------+
|         0 |
+-----------+
1 row in set


mysql> select avg(age) from user ;
+----------+
| avg(age) |
+----------+
| 20.4000  |
+----------+
1 row in set


mysql> select max(age) from user ;
+----------+
| max(age) |
+----------+
|       23 |
+----------+
1 row in set


mysql> select min(age) from user ;
+----------+
| min(age) |
+----------+
|       12 |
+----------+
1 row in set


資料的排序與分組:
mysql> select * from user group by age;
+----+------+-----+-----+---------+
| id | name | sex | age | address |
+----+------+-----+-----+---------+
|  2 | 李四 | 男  |  12 | hebei   |
|  1 | 張三 | 男  |  22 | beijing |
|  3 | 王五 | 女  |  23 | jiangsu |
+----+------+-----+-----+---------+
3 rows in set


mysql> select * from user group by age,address;
+----+---------+-----+-----+---------+
| id | name    | sex | age | address |
+----+---------+-----+-----+---------+
|  2 | 李四    | 男  |  12 | hebei   |
|  5 | aa      | nv  |  22 | NULL    |
|  1 | 張三    | 男  |  22 | beijing |
|  4 | wuhaixu | nan |  23 | hunan   |
|  3 | 王五    | 女  |  23 | jiangsu |
+----+---------+-----+-----+---------+
5 rows in set
上面的是先根據age進行分組,再對單個分組裡的address內容進行分組。


replace函式用於把某個字元或某個字串替換為指定的一個字元(或多個字元)


mysql> select address,replace(address,'ei','ab') from user ;
+---------+----------------------------+
| address | replace(address,'ei','ab') |
+---------+----------------------------+
| beijing | babjing                    |
| hebei   | hebab                      |
| jiangsu | jiangsu                    |
| hunan   | hunan                      |
| NULL    | NULL                       |
+---------+----------------------------+
5 rows in set


upper函式可以把字串裡的小寫字母轉化為大寫


mysql> select upper(address) from user ;


+----------------+
| upper(address) |
+----------------+
| BEIJING        |
| HEBEI          |
| JIANGSU        |
| HUNAN          |
| NULL           |
+----------------+
5 rows in set


lower把字串裡的大寫字元轉化為小寫


mysql> select lower
(address) from user ;
+----------------+
| lower(address) |
+----------------+
| beijing        |
| hebei          |
| jiangsu        |
| hunan          |
| NULL           |
+----------------+
5 rows in set


substr用來獲取字串子串的函式


mysql> select address,substr(address,1,2) from user ;


+---------+---------------------+
| address | substr(address,1,2) |
+---------+---------------------+
| beijing | be                  |
| hebei   | he                  |
| jiangsu | ji                  |
| hunan   | hu                  |
| NULL    | NULL                |
+---------+---------------------+
5 rows in set


選擇函式,相當與oracle裡的decode()
mysql> select case address when 'beijing' then '北京' else '其他' end as '地址' from user ;
+------+
| 地址 |
+------+
| 北京 |
| 其他 |
| 其他 |
| 其他 |
| 其他 |
+------+
5 rows in set


length函式用於得到字串。數字、日期或表示式的長度,單位是位元組。
mysql> select address,length(address) as '長度' from user ;
+---------+------+
| address | 長度 |
+---------+------+
| beijing |    7 |
| hebei   |    5 |
| jiangsu |    7 |
| hunan   |    5 |
| NULL    | NULL |
+---------+------+
5 rows in set


lpad函式用於在字串左側新增字元或空格。


mysql> select address,lpad(address,30,'.') from user ;


+---------+--------------------------------+
| address | lpad(address,30,'.')           |
+---------+--------------------------------+
| beijing | .......................beijing |
| hebei   | .........................hebei |
| jiangsu | .......................jiangsu |
| hunan   | .........................hunan |
| NULL    | NULL                           |
+---------+--------------------------------+
5 rows in set


rpad函式在字串右側新增字元或空格


mysql> select address,rpad(address,30,'.') from user ;
+---------+--------------------------------+
| address | rpad(address,30,'.')           |
+---------+--------------------------------+
| beijing | beijing....................... |
| hebei   | hebei......................... |
| jiangsu | jiangsu....................... |
| hunan   | hunan......................... |
| NULL    | NULL                           |
+---------+--------------------------------+
5 rows in set


ASCII函式返回字串最左側的‘美國資訊交換標準碼’。


mysql> select ascii('a') ;
+------------+
| ascii('a') |
+------------+
|         97 |
+------------+
1 row in set


mysql> select ascii('A') ;
+------------+
| ascii('A') |
+------------+
|         65 |
+------------+
1 row in set


最常見的算數函式有:絕對值(ABS)、舍入(ROUND)、平方根(SQRT)、符號(SIGN)、冪(POWER)、上限和下限(CEIL、FLOOR)、指數(EXP)、SIN、COS、TAN


日期和時間儲存的標準SQL資料型別有3種:
date:直接儲存日期。date的格式是YYYY-MM-DD,範圍是從0001-01-01到9999-12-31
time:直接儲存時間。time的格式是HH:MI:SS.nn...,範圍是從00:00:00...到23:59:61.999...
timestamp:直接儲存日期和時間。timestamp的格式是YYYY-MM-DD HH:Mi:SS.nn...,範圍是從0001-01-01 00:00:00...到9999-12-31 23:59:61.999...


mysql中使用now()來獲取當前時間


mysql> select now() ;
+---------------------+
| now()               |
+---------------------+
| 2014-07-07 14:51:56 |
+---------------------+

1 row in set

首先建立一個簡單的user表
CREATE TABLE `user` (
`id`  int NOT NULL AUTO_INCREMENT ,
`name`  varchar(255) NULL ,
`sex`  varchar(255) NULL ,
`age`  int NULL ,
`address`  varchar(255) NULL ,
PRIMARY KEY (`id`)
)
;
然後插入資料
insert into `user`(`name`,`sex`,`age`,`address`) values('張三','男',22,'北京') ;
insert into `user`(`name`,`sex`,`age`,`address`) values('李四','男',12,'河北') ;
insert into `user`(`name`,`sex`,`age`,`address`) values('王五','女',23,'江蘇') ;
insert into `user`(`name`,`sex`,`age`,`address`) values('趙六','男',21,'北京') ;


建立一張與user表關聯的表
CREATE TABLE `teacher` (
`id`  int NOT NULL AUTO_INCREMENT ,
`name`  varchar(255) NULL ,
`stu_id` int NOT NULL ,
PRIMARY KEY (`id`),
constraint ID_FK foreign key(stu_id) references user(id)
)
;
insert into `teacher`(name,stu_id) values('張老師',1) ;
insert into `teacher`(name,stu_id) values('王老師',4) ;
insert into `teacher`(name,stu_id) values('吳老師',2) ;
insert into `teacher`(name,stu_id) values('方老師',2) ;
insert into `teacher`(name,stu_id) values('林老師',3) ;


等值結合:
mysql> select t.name,u.name from user u,teacher t where u.id=t.stu_id ;
+--------+---------+
| name   | name    |
+--------+---------+
| 張老師 | 張三    |
| 吳老師 | 李四    |
| 方老師 | 李四    |
| 林老師 | 王五    |
| 王老師 | wuhaixu |
+--------+---------+
5 rows in set


mysql> select t.name,u.name from teacher t inner join user u on t.stu_id = u.id ;
+--------+---------+
| name   | name    |
+--------+---------+
| 張老師 | 張三    |
| 吳老師 | 李四    |
| 方老師 | 李四    |
| 林老師 | 王五    |
| 王老師 | wuhaixu |
+--------+---------+
5 rows in set
在這種方式裡,where子句裡的結合操作符被去掉了,取而代之的是關鍵字inner join。要被結合的表位於join之後,而結合操作符位於關鍵字on之後。
上面還使用了表的別名


union操作符可以組合兩個或多個select語句的結果,不包含重複的記錄。如果某行的輸出存在於一個查詢結果裡,那麼其他查詢結果同一行的記錄就不會
再輸出了。在使用union操作符時,每個select語句裡必須選擇同樣數量的欄位、同樣數量的欄位表示式、同樣的資料型別、同樣的次序--但長鬚不必一樣。



mysql> select id from user 
    -> union
    -> select id from teacher ;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
5 rows in set


union all操作符可以組合兩個select語句的結果,並且包涵重複的結果。其使用規則與union一樣,它與union基本上是一樣的,只是一個返回重複的結果,一個不返回。


mysql> select id from user 
    -> union all
    -> select id from teacher ;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  1 |
|  3 |
|  4 |
|  5 |
|  2 |
+----+
9 rows in set


索引是如何工作的呢?索引在建立之後,用於記錄與杯索引欄位相關聯的位置值。當表裡新增新資料時,索引裡也會新增新項,當資料庫執行查詢,而且where條件裡指定的欄位已經設定了
索引時,資料庫會首先在索引裡搜尋where子句裡指定的值。如果在索引裡找到了這個值,索引就可以返回被搜尋資料在表裡的實際位置。


建立單欄位索引:
create index index_id on user(id) ;
建立唯一索引:
create unique index index_id on user(id) ;
組合索引是基於一個表裡兩個或多個欄位的索引。在建立組合索引時,我們要考慮效能的問題,因為欄位在索引裡的次序對資料檢索速度有很大的影響。一般來說,最具有限制的值應該排在前面,
從而得到最好的效能。但是,總是會在查詢裡指定的欄位應該放在首位。
create index index_name on table_name (column1,column2) ;
隱含索引是資料庫服務程式在建立物件時自動建立的。比如,資料庫會為主鍵約束和唯一性約束自動建立索引。
什麼時候選擇用索引呢?唯一索引隱含地與主鍵共同實現主鍵的功能。外來鍵經常用於與父表的結合,所以也適合設定索引。一般來說,大多數用於表結合的欄位都應該設定索引。
經常在order by和group by裡引用的欄位也應該考慮設定索引。
何時應該避免使用索引?1、索引不應該用於小規模的表。2、當欄位用於where子句做為過濾器會返回表裡的大部分記錄時,該欄位就不適合設定索引。舉例來說,圖書裡的索引不會
包括像the或and這樣的單詞。3、經常會被批量更新的表可以具有索引,但批量操作的效能會由於索引而降低。對於經常會被載入或批量操作的表來說,可以在執行批量操作之前去掉索引,
在完成操作之後再重新建立索引,這是因為當表裡插入資料時,索引也會杯更新,從而增加了額外的開銷。4、不應該對包涵大量null值的欄位設定索引。索引對在不同記錄中包涵不同資料
的欄位特別有效,欄位中過多的null值會嚴重影響索引的執行效率。5、經常被操作的欄位不應該設定索引,因為對索引的維護會變得很繁重。


修改索引alter index INDEX_NAME
刪除索引drop index index_name on table_name


我們應該對只包含很少不同值的欄位建立索引,比如性別、州名等。
在讀取大規模的表時,應該避免進行全表掃描。舉例來說,當讀取沒有索引的表時,就會發生全表掃描,這通常會需要較長的時間才能返回資料。對於大多數大型表來說,應該考慮設定索引。
下面是應該被索引的資料;
  1、做為主鍵的欄位
  2、做為外來鍵的欄位
  3、在結合表裡經常使用的欄位
  4、經常在查詢裡做為條件的欄位
  5、大部分是唯一值的欄位
在調整sql語句裡還有其他一些效能考慮:
  1、使用like操作符和萬用字元
  2、避免or操作符
  3、避免having子句。
  4、避免大規模排序操作
  5、使用儲存過程
  6、在批載入時關閉索引


1、使用like操作符


mysql> select address from user where address like '%jing' ;
+---------+
| address |
+---------+
| beijing |
+---------+
1 row in set


mysql> select address from user where address like '___
jing' ;
+---------+
| address |
+---------+
| beijing |
+---------+
1 row in set