MySQL資料庫詳解(上)
MySQL(一)
1.登陸
mysql -uroot -pMyPassword
使用預設的root使用者名稱登陸,將MyPassword改成自己的密碼
2.基本操作
--註釋 updata mysql .user set authentication_string=password('123456') where user = 'root' and Host='localhost'; --修改使用者密碼 flush privileges; --重新整理許可權 show databases; --顯示所有庫 use dataBaseName; --切換資料庫名 show tables; --顯示所有表名 describe tableName; --顯示所有表資訊 create database newDatabase --建立一個新庫 exit --退出連線 drop database databaseName --刪除k
3.資料型別
1.數值
型別 | 大小 | 描述 |
---|---|---|
tinyint | 1位元組 | 十分小的資料 |
smallint | 2位元組 | 較小的資料 |
mediumint | 3位元組 | 中等大小的資料 |
int | 4位元組 | 標準的整數(常用) |
bigint | 8位元組 | 較大的資料 |
型別 | 大小 | 描述 |
---|---|---|
float | 4位元組 | 浮點數 |
double | 8位元組 | 浮點數 |
decimal | 8個位元組 | 字串形浮點數 |
文字
型別 | 大小 | 描述 |
---|---|---|
char | 0~255 | 大小固定的字串 |
varchar | 0~65535 | 常用的字串 String (常用) |
tinytext | 2^8-1 | 微型文字 |
text | 2^16-1 | 文字串(常用) |
日期型別
型別 | 大小 | 描述 |
---|---|---|
data | YYYY-MM-DD | 日期格式 |
time | HH:mm:ss | 時間格式 |
datatime | YYYY-MM-DD HH:mm:ss | 常用的時間格式 |
timestamp | 1970到現在的毫秒數 | 時間戳(常用) |
null
無數不介意使用
4.資料庫的欄位型別
unsigned:只有整數能用,不能申明為負數
zerofill:不足的位數用0填充
auto_increment:自增,在上一條基礎上自增必須是整數型別
NULL or NOT NULL:空或者非空
default:預設值
5.建立表
根據上面的資訊可以通過Mysql語句建立如下表
CREATE TABLE IF NOT EXISTS `teacher`(
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` VARCHAR(10) DEFAULT('匿名') COMMENT 'name',
`user` VARCHAR(20) NOT NULL COMMENT 'USER',
`pwd` VARCHAR(15) NOT NULL COMMENT 'PASSWORD',
`sex` VARCHAR(2) DEFAULT('男') COMMENT 'SEX',
`birthday` DATETIME DEFAULT(NULL) COMMENT 'Birthday',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
通過總結,可以獲得一條建立表的公式
"--"代表空格 [ ]代表可選 最後一條語句不加,
#`keyName`--型別--[不可空?--預設值--自動遞增--鍵值--備註]
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT 'id'
#可以在最後設定剪紙,也可以直接在最後設定
PRIMARY KEY(`id`)
#設定表的引擎
ENGINE=INNODB
6.表引擎
- INNODB 預設使用
- MYISAM 早些年使用
功能 | MYISAM | INNODB |
---|---|---|
事務支援 | 不支援 | 支援 |
資料行鎖定 | 不支援 | 支援 |
全文索引 | 支援 | 不支援 |
表空間大小 | 較小 | 較大 |
總結:MYISAM節約空間,速度較快;INNODB安全性高、事務的處理、多表多使用者操作。
7.修改和刪除欄位
mysql語句中可以通過ALTER命令來修改表名、新增欄位、修改表的欄位
ALTER TABLE #修改表元素
引數 | 描述 |
---|---|
RENAME AS | 重命名錶名 |
ADD | 新增欄位 |
MODIFY | 修改約束 |
CHANG | 修改欄位名 |
DROP | 刪除表中欄位 |
#ALTER TABLE 表名 RENAME 舊錶名 RENAME AS 新表名
ALTER TABLE teacher RENAME AS student; #修改表名
#ALTER TABLE 表名 ADD 欄位名 新屬性
ALTER TABLE student ADD age INT(11); #新增欄位
#ALTER TABLE 表名 MODIFY 欄位名 列屬性[...]
ALTER TABLE student MODIFY age VARCHAR(11); #修改約束
#ALTER TABLE 表名 CHANGE 舊名字 新名字 列屬性
ALTER TABLE student CHANGE age age1 INT(1); #修改欄位名
#刪除表的欄位:ALTER TABLE 表名 DROP 欄位名
ALTER TABLE student DROP age1;
DESC student; #查詢結果
DROP #刪除表
引數 | 描述 |
---|---|
TABLE | 指定表 |
DROP TABLE IF EXISTS student;
DELETE #刪除單個數據
引數 | 描述 |
---|---|
FROM | 指定表 |
WHRER | 篩選資料 |
#DELETE FROM 表名 WHERE 條件
DELETE FROM `film` WHERE title ='127小時10.0';
8.MySQL管理
在簡單的操作MySQL資料庫之後,要學會更好的管理MySQL資料庫
8.1新增外來鍵
MySQL 外來鍵約束(FOREIGN KEY)用來在兩個表的資料之間建立連結,它可以是一列或者多列。 一個表可以有一個或多個外來鍵。 外來鍵對應的是參照完整性,一個表的外來鍵可以為空值,若不為空值,則每一個外來鍵的值必須等於另一個表中主鍵的某個值
新增外來鍵的方法很多,只講最簡單最好理解的
分別執行以下兩個MySQL語句,建立兩個表
#建立年級表
CREATE TABLE IF NOT EXISTS `graded`(
`gradeParId` INT(4) NOT NULL COMMENT "年級id",
`gradeName` VARCHAR(3) NOT NULL COMMENT "年級名稱",
PRIMARY KEY(`gradeParId`)
)
#建立學生表
CREATE TABLE IF NOT EXISTS `student`(
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '學號',
`name` VARCHAR(5) NOT NULL COMMENT '姓名',
`sex` VARCHAR(2) DEFAULT('男') COMMENT '性別',
`gradeId` INT(10) NOT NULL COMMENT '年級id',
PRIMARY KEY(`id`)
)DEFAULT CHARSET=utf8
給表新增外來鍵,使得兩個表的某項值相互關聯,可以理解為新增一個欄位,使得這個欄位等於另外一張表的某個值
在上一節通過ALTER來給表新增新的欄位並且設定欄位的屬性,以同樣的方式,在建立完兩個表之後,通過ALTER來新增一個欄位
#ALTER TABLE 表名 ADD CONSTRAINT 外來鍵名稱 FOREIGN KEY(被關聯的外來鍵欄位) references 外表名(關聯的欄位)
ALTER TABLE `student` ADD CONSTRAINT `FK_gradeId` FOREIGN KEY(`gradeId`) REFERENCES `graded`(`gradeParId`);
- CONSTRAINT:約束
- FOREIGN:外界
- REFERENCES:引用
8.2 DML語言
Data Manipulation Language(DML):資料庫操縱語言
Insert
通過Insert語句INTO引數對可以選中某個表插入其中一條資料
#INSERT INTO 表名([欄位1],[欄位2],[欄位3]...) VALUES (資料1,資料2,資料3.....);
INSERT INTO `student`(`name`,`sex`,`gradeId`) VALUES ("李四","男",1803);
注意點:插入的資料的型別要與表中的欄位一一對應,比如欄位1是varchar因此VALUES後面括號第一個欄位應該是String型別而不是數值
省略:可以省略欄位1,欄位2,欄位3然後寫VALUE後面的資料,MySQL將預設自己匹配,但不介意這麼寫
也可以插入多條資料
INSERT INTO `student`(`name`,`sex`,`gradeId`) VALUES ("小明","男",1804),("小張","男",1804),("小龍","男",1804);
Update
通過Update可以對錶中欄位就行一個修改
#UPDATE 表名 SET 要修改的欄位=要修改的資料 WHERE 條件;
UPDATE `student` SET `name`= "李明" WHERE `name`="張三"; #把name叫張三的修改為李明
WHERE:篩選條件,可以是被修改欄位的任何值,比如....WHERE id
=1
;修改id為1的欄位
同樣的方式可以修改多個值
UPDATE `student` SET `name`= "李明",`gradeId`=1804 WHERE `name`="張三";
注意:如果不加WHERE將會修改所有欄位,切勿如此操作,如此操作後請立即刪庫跑路
Delete
通過delete語句刪除一個欄位 以及 清空表
#DELETE FROM 表名 WHERE 條件 //刪除欄位
DELETE FROM `student` WHERE `name`="李明";
#TRUNCATE 表名 //清空表
TRUNCATE student;
注意:如果不加WHERE將會刪除所有欄位,切勿如此操作,如此操作後請立即跑路
DELETE 和 TRUNCATE 的區別:
- DELETE不會重置自增的計數器,TRUNCATE會
- TRUNCATE不會影響事務,DELETE會
8.3 DQL 語言
Data Query Language(DQL):資料庫查詢語言
- 本節的關鍵主要圍繞Select展開
- 查詢語句有點多
8.3.1 SELECT的簡單查詢
先從最簡單的查詢開始
#SELECT 欄位/* from 表明;
SELECT * FROM `film`;
SELECT `title`,`time` FROM `film` #查詢多個欄位
SELECT後面可以跟要查詢的欄位,老規矩查詢多個欄位逗號隔開,所有要查詢所有欄位可填*
除此之外,可以通過AS來對欄位或者表做別名
SELECT `title` AS 標題,`time` AS 時間 FROM `film` #查詢多個欄位 輸出時title變為了標題 time變為時間
#對錶命名
SELECT `title`,`time` FROM `film` AS flim;
拓展:concat(a,b) //拼接a和b字串為一個完整的字串
SELECT CONCAT("標題",title) AS 標題 FROM `film`; #輸出後給每條查詢結果加上標題這個欄位
如果查詢的欄位有許多重複的資料,那麼可以使用DISTINCT來去重
SELECT DISTINCT `id` FROM Result;
還能對查詢的結果就行一系列的運算處理,比如把要查詢的ID+1
SELECT DISTINCT `id`+1 AS newId FROM Result;
8.3.2 SELECT配合WHERE進行模糊查詢
模糊查詢,是一種很方便的查詢方式,用來查詢符合某種指定格式的資料,比如想查詢所有包含a字元的資料,就可以使用模糊查詢。 2. 模糊查詢語法 模糊查詢是利用“_”表示單個字元和“%”表示任意個字元進行匹配的。
MySQL允許使用Like語句進行模糊查詢
- %代表某個字元前或後的所有字元
- _代表字元前或後的單個字元
比如說:
#查詢title中包含“天”字的電影
SELECT `title` AS 影名,`time` AS 時間 FROM `film` WHERE `title` LIKE "%天%";
#查詢title中包含“天”字且三個字的電影名
SELECT `title` AS 電影名,`time` AS 時間 FROM `film` WHERE `title` LIKE "天__" OR `title` LIKE "_天_" OR `title` LIKE "__天";
MySQL允許使用In語句進行範圍的搜尋
- In後面括號跟具體多個值 不能使用Like的%和_
- 只要條件滿足括號內的值就返回真
比如說:
#查詢型別為科幻片、紀錄片、恐怖片的電影
SELECT `title` AS 電影名,`class` AS 型別 FROM `film` WHERE `class` IN ("科幻片","紀錄片","恐怖片");
IS NULL or IS NOT NULL
比如:
#查詢指定欄位為NULL或者不是NULL的記錄
SELECT `title` AS 電影名,`class` AS 型別 FROM `film` WHERE `class` IS NULL;
8.3.3 連表查詢
(個人理解)
概念引入:能查A表資料,能查B表資料,但有時候需要得到的資料是需要把A表和B表結合起來的資料,此時就需要運用連表查詢
知難而退(?):連表查詢是MySQL的重難點,也是最常用的查詢方式,是新手和入門級大佬的分水嶺
圖1
從簡單的開始講,連表查詢需要有一個集合的框架,如上圖所示,有A集合和B集合兩個集合
- 其中資料根據集合可分為三大板塊(以A集合為例):A集合、B集合、AB集合公共部分
- 在根據1中互相組合可以組合成上圖的七個部分
在學習語句之前,得先有一個術語的概念,在上圖中A為左表,B為右表
(由於是個人建立的假資料學習,所以各方面演示都比較籠統,建議自己動手測試)
下面開始學習MySQL的四種查詢方式:
- LEFT JOIN
- RIGHT JOIN
- UNION
- INNER JOIN
為了方便理解建立如下兩張表
a表:
b表:
8.3.3.1 INNER JOIN
INNER JOIN:查詢左表與右表的公共部分
SELECT a.*,b.* FROM `afrom` AS a
INNER JOIN `bfrom` AS b
on a.name=b.id;
現在還沒用的知識:FROM後面跟著的被定義為左表(即圖1的A集合),INNER JOIN後面跟的被定義為右表(即圖1的B集合)
查詢A表的name與b表id相等的結果
8.3.3.2 RIGHT JOIN
LEFT JOIN:以右表為主,當遇到右表有左表沒有的時候,相對應欄位用NULL填充
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b
on a.name=b.id;
在如上查詢中,右表為主,可以理解為先列出右表的所有內容,在根據右表的id與左表的name一一對應的查詢顯示,遇到如id為1050在左表存在,右表不存在的情況下,對應欄位使用null填充
8.3.3.3 LEFT JOIN
LEFT JOIN:以左表為主,當遇到左表有右表沒有的時候,相對應欄位用NULL填充
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id
;
同RIGHT JOIN差不多不多講了看結果
8.3.3.4 union == full JOIN
union:將兩個查詢結果,重複的記錄會合並
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id #記錄1
UNION
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b #記錄B
on a.name=b.id;
8.3.3.5 JOIN & WHERE
在掌握了上述的連表查詢方法之後,已經學會了圖1中1、2、3三種查詢方式
剩下的四種需要配合WHERE語句就行進階的查詢,先要理清楚LEFT JOIN 和RIGHT JOIN
LEFT JOIN是以左表為主,RIGHT JOIN是以右表為主
假設A表+B表為一個全集U,利用MySQL語句查詢CuB,即A表有中B沒有的集合,因此可以根據查詢結果後加WHERE對其就行處理
思路:在以A表為左表使用LEFT JOIN查詢,肯定會列出了所有A表的資料,如果發現A表存在B表不存在的資料,對應的欄位用NULL填充,則對查詢LEFT JOIN查詢的結果後使用WHERE語句篩選出B表字段為null的結果,那麼就是查詢A表有中B沒有的資料(圖1中的4)
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id
WHERE b.id IS NULL;
如果你理解了上述講的不是很好的概念,那麼使用RIGHT JOIN查詢表1中第六種情況也很簡單
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b
on a.name=b.id
WHERE a.name IS NULL;
那麼兩種結果使用union連起來就是,第七種情況
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id
WHERE b.id IS NULL
UNION
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b
on a.name=b.id
WHERE a.name IS NULL;
總結&練習
在原有的基礎上完善一下資料
改變a表的班級,建立規則如下,十位數代表幾,個位數代表班級,如下:
通過以下MySQL建立班級的id表
INSERT INTO `gradetest`(`id`,`name`) VALUES
(11,"大一一班"),(12,"大一二班"),(13,"大一三班"),(14,"大一四班"),(15,"大一五班"),
(16,"大一六班"),(17,"大一七班"),(18,"大一八班"),(19,"大一九班"),
(21,"大二一班"),(22,"大二二班"),(23,"大二三班"),(24,"大二四班"),(25,"大二五班"),
(26,"大二六班"),(27,"大二七班"),(28,"大二八班"),(29,"大二九班"),
(31,"大三一班"),(32,"大三二班"),(33,"大三三班"),(34,"大三四班"),(35,"大三五班"),
(36,"大三六班"),(37,"大三七班"),(38,"大三八班"),(39,"大三九班"),
(41,"大四一班"),(42,"大四二班"),(43,"大四三班"),(44,"大四四班"),(45,"大四五班"),
(46,"大四六班"),(47,"大四七班"),(48,"大四八班"),(49,"大四九班")
接下來開始練習:
-- 查詢成績高於60同學的詳細資訊(資訊完全的同學)
-- 列出學號、姓名、性別、班級、成績
SELECT
b.id AS 學號,b.name AS 姓名,a.sex AS 性別, -- 列出學號 、姓名、性別
aGrade.`name` AS 班級,a.score AS 分數 -- 列出班級、分數
FROM `afrom` AS a INNER JOIN `bfrom` AS b ON a.`name`=b.id
INNER JOIN `gradetest` AS `aGrade` ON a.gradeId=aGrade.id
WHERE a.score > 85
;
8.4查詢的微末細節
關於group by、having、where三者的用法(摘自網上su_bao博主)
WHERE語句在GROUP BY語句之前;SQL會在分組之前計算WHERE語句。
HAVING語句在GROUP BY語句之後;SQL會在分組之後計算HAVING語句。
先通過WHERE語句進行對結果的篩選,之後通過GROUP BY語句進行過濾,HAVING為組後過濾,即分組後再過濾
8.5子查詢語句
在之前的學習中Where語句後面都是跟隨的固定值,但實際上where的條件可以是一條查詢語句,這條語句為稱之為子查詢語句
比如查詢某個年級段大於80分的成績
SELECT a.`name` AS 學號,b.`name` AS 姓名,a.sex AS 性別, a.score AS 分數,a.gradeId AS 年級id
FROM afrom a INNER JOIN bfrom b ON b.id=a.`name`
WHERE a.gradeId IN (SELECT id FROM gradetest WHERE `id` BETWEEN 10 AND 20)
AND a.score>80;
9.事物基本瞭解
事務(Transaction),一般是指要做的或所做的事情。在計算機術語中是指訪問並可能更新資料庫中各種資料項的一個程式執行單元(unit)。事務通常由高階資料庫操縱語言或程式語言(如SQL,C++或Java)書寫的使用者程式的執行所引起,並用形如begin transaction和end transaction語句(或函式呼叫)來界定。事務由事務開始(begin transaction)和事務結束(end transaction)之間執行的全體操作組成。 ——百度百科
最經典還是屬於銀行轉賬的例子,假設A要給B轉賬,如果轉賬過程中A突然斷網了,在沒做好事物處理的時候,就會出現A轉出去了,B沒收到,或者B收到了A沒轉出去的BUG,事務就是為了針對這一問題,將兩件事情同步執行,要麼都成功要麼都失敗,同時事物也具有四個特性:
- 原子性
- 事務是多件事情執行,但事物的原子性保證了所有事情看成一個整體,一榮俱榮一損俱損
- 一致性
- 事務中,所有DML語句操作資料時,必須保證同時成功或者同時失敗 將語句操作之間就行同步
- 隔離性
- 事務A和事務B具有完全的隔離,互不相干
- 持續性
- 事務在最後結束時,都將記憶體資料持久化到硬碟中
9.1事務的基本操作
To be or not to be,This is a question.
- commit:提交
- rollback:回滾
MySQL預設是事務開啟的狀態,對此在以往的Insert、update、delete語句執行過程中不會出現差錯
每次呼叫增刪改三個語句時,MySQL會自動建立一個事務提交 即事務的自動提交
如何關閉和開啟事務的自動提交??
SET autocommit = 0|1|ON|OFF; -- 0和OFF為關閉 1和ON為開啟
為了方便學習事務的基本操作,這次不在使用MySQL視覺化工具來演示,而採用控制檯視窗
回顧之前的登陸MySQL,並且關閉自動提交
set autocommit = 0;
查詢結果
show variables like 'autocommit'
建立銀行表(先通過use進入庫)
create table if not exists `bank`(`name` varchar(4) not null comment "name",money int(4) not null comment"money")engine=innodb default charset=utf8;
插入資料
insert into bank(`name`,`money`) values ("張三","1000"),("李四","100");
select * from bank; -- 查詢結果
模擬張三給李四轉賬
mysql> select * from bank;
+------+-------+
| name | money |
+------+-------+
| 張三 | 1000 |
| 李四 | 100 |
+------+-------+
2 rows in set (0.00 sec)
mysql> updata bank set money=money-500 where `name`="張三";
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'updata bank set money=money-500 where `name`="張三"' at line 1
mysql> update bank set money=money-500 where `name`="張三";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update bank set money=money+500 where `name`="李四";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from bank;
+------+-------+
| name | money |
+------+-------+
| 張三 | 500 |
| 李四 | 600 |
+------+-------+
2 rows in set (0.00 sec)
看似好像是轉賬成功了,別急,我們重新開啟一個cmd視窗連線上資料看看
mysql> select * from bank;
Empty set (0.00 sec)
為什麼是空的?回顧之前的操作,我們先關閉了資料庫的自動提交,在建立表再插入資料,由於沒有執行commit因此對於tables的增刪改查只是做到了建立表
為了驗證猜想,開啟第一個MySQL視窗輸入
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
在重新查詢,發現查到了之前的改的
mysql> select * from bank;
+------+-------+
| name | money |
+------+-------+
| 張三 | 500 |
| 李四 | 600 |
+------+-------+
2 rows in set (0.01 sec)
rollback與commit是同理,在語句執行失敗的時候,就行回滾操作,將在下篇討論......
下篇地址:等待更新....