MySQL葵花宝典
一.數(shù)據(jù)庫(kù)基礎(chǔ)
1.數(shù)據(jù)庫(kù)的操作
1.1顯示當(dāng)前的數(shù)據(jù)庫(kù)
show databases;1.2創(chuàng)建數(shù)據(jù)庫(kù)
create database [if not exists] db_name;1.3使用數(shù)據(jù)庫(kù)
use db_name;1.4刪除數(shù)據(jù)庫(kù)
drop database [if exists] db_name;數(shù)據(jù)庫(kù)刪除后,內(nèi)部看不到對(duì)應(yīng)的數(shù)據(jù)庫(kù),里面的表和數(shù)據(jù)全被刪除
2.常用數(shù)據(jù)類型
2.1
| BIT[(M)] | M指定位數(shù),默認(rèn)為1 |
| TINYINT | 1字節(jié) |
| SMALLINT | 2字節(jié) |
| INT | 4字節(jié) |
| BIGINT | 8字節(jié) |
| FLOAT(M,D) | 4字節(jié),單精度,M指定長(zhǎng)度,D指定小數(shù)位數(shù)。會(huì)發(fā)生精度丟失 |
| DOUBLE(M,D) | 8字節(jié) |
| DECIMAL(M,D) | M/D最大值+2,雙精度,M指定長(zhǎng)度,D指定小數(shù)位數(shù)。精確數(shù)值 |
| NUMERIC(M,D) | M/D最大值+2,和DECIMAL一樣 |
數(shù)值類型可以指定為無(wú)符號(hào)(unsigned),表示不取負(fù)數(shù)。(盡量不適用unsigned)
1字節(jié)(bytes)=8bit
2.2字符串類型
| varchar(size) | 可變長(zhǎng)度字符串 |
| text | 長(zhǎng)文本數(shù)據(jù) |
| mediumtext | 中等長(zhǎng)度文本數(shù)據(jù) |
| BOLB | 二進(jìn)制形式的長(zhǎng)文本數(shù)據(jù) |
2.3日期類型
| datetime | 8字節(jié),1000-9999年,不會(huì)進(jìn)行時(shí)區(qū)的檢索及轉(zhuǎn)換 |
| timestamp | (時(shí)間戳)4字節(jié),1970-2038,自動(dòng)檢索當(dāng)前時(shí)區(qū)并進(jìn)行轉(zhuǎn)換 |
3.表的操作
需要操作數(shù)據(jù)庫(kù)中的表時(shí),先要使用該數(shù)據(jù)庫(kù)
use db_name;3.1查看表
desc tb_name; //查看表名 show create table tb_name; //查看表結(jié)構(gòu)+表編碼 show tables;//查看當(dāng)前數(shù)據(jù)庫(kù)一共有多少表3.2創(chuàng)建表
create table tb_name (field1 datatype,field2 datatype,.......... );可以使用comment增加字段說(shuō)明
示例:
create table stu_test (id int,name varchar(20) comment '姓名',password varchar(50) comment '密碼',age int,sex varchar(1),birthday timestamp,amout decimal(13,2),resume text );3.3刪除表
drop table [if exists] tb_name;3.4修改表內(nèi)容
alter table tb_name add+新列名稱+類型;//新增一列 alter table tb_name change+原列名+新列名+新列類型;//修改某一列 alter table tb_name 舊表名 rename 新表名;//修改表名稱 alter table tb_name convert to character set 新編碼; //修改表編碼二.MySQL表的CRUD
CURD即增加、查詢、更新、刪除
1、新增(create)
insert [into] tb_name (屬性名) value (屬性值);案例:
-- 創(chuàng)建一張學(xué)生表 DROP TABLE IF EXISTS student; CREATE TABLE student (id INT,sn INT comment '學(xué)號(hào)',name VARCHAR(20) comment '姓名',qq_mail VARCHAR(20) comment 'QQ郵箱' );1.1單行數(shù)據(jù)插入+全列插入
-- 插入兩條記錄,value_list 數(shù)量必須和定義表的列的數(shù)量及順序一致 INSERT INTO student VALUES (100, 10000, '唐三藏', NULL); INSERT INTO student VALUES (101, 10001, '孫悟空', '11111');1.2 多行數(shù)據(jù)+指定列插入
-- 插入兩條記錄,value_list 數(shù)量必須和指定列數(shù)量及順序一致 INSERT INTO student (id, sn, name) VALUES(102, 20001, '曹孟德'),(103, 20002, '孫仲謀');2.查詢(retrieve)
語(yǔ)法:
SELECT[DISTINCT] {* | {column [, column] ...} [FROM table_name][WHERE ...][ORDER BY column [ASC | DESC], ...]LIMIT ...其中distinct為去重,asc為升序,desc為降序
案例:
-- 創(chuàng)建考試成績(jī)表 DROP TABLE IF EXISTS exam_result; CREATE TABLE exam_result (id INT,name VARCHAR(20),chinese DECIMAL(3,1),math DECIMAL(3,1),english DECIMAL(3,1) ); -- 插入測(cè)試數(shù)據(jù) INSERT INTO exam_result (id,name, chinese, math, english) VALUES(1,'唐三藏', 67, 98, 56),(2,'孫悟空', 87.5, 78, 77),(3,'豬悟能', 88, 98.5, 90),(4,'曹孟德', 82, 84, 67),(5,'劉玄德', 55.5, 85, 45),(6,'孫權(quán)', 70, 73, 78.5),(7,'宋公明', 75, 65, 30);(1)全行全列查詢
select * from tb_name;(2)查找指定列
-- 指定列的順序不需要按定義表的順序來(lái) SELECT id, name, english from exam_result;(3)查詢字段為表達(dá)式
-- 表達(dá)式不包含字段 SELECT id, name, 10 FROM exam_result; -- 表達(dá)式包含一個(gè)字段 SELECT id, name, english + 10 FROM exam_result; -- 表達(dá)式包含多個(gè)字段 SELECT id, name, chinese + math + english FROM exam_result;(4)別名
SELECT column [AS] alias_name [...] FROM table_name; -- 結(jié)果集中,表頭的列名=別名 SELECT id, name, chinese + math + english 總分 FROM exam_result;as 可以省略,列名與別名中間用空格省略
(5)去重查詢:DISTINCT
98分重復(fù)了
(6)排序:order by
select 列名 from tb_name order by 列名 [asc/desc];//默認(rèn)升序若結(jié)果中包含null值,這個(gè)值null認(rèn)為是最小值,比負(fù)數(shù)還小
針對(duì)多個(gè)列進(jìn)行排序:
查看所有學(xué)生的姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),其中按照語(yǔ)文成績(jī)升序,數(shù)學(xué)成績(jī)降序排序
優(yōu)先按照語(yǔ)文成績(jī)升序排序,只有兩個(gè)語(yǔ)文成績(jī)相同時(shí)才按照數(shù)學(xué)成績(jī)降序排序
(7)分頁(yè)查詢 limit
select 屬性名稱 from tb_name limit n; //查詢結(jié)果按照前n行輸出 select 屬性名稱 from tb_name limit n offset s;//查詢結(jié)果按照前n行輸出,從第s行輸出開始(8)條件查詢:where (不支持別名)
3.修改表數(shù)據(jù) update
update tb_name set 列名 = (表達(dá)式);//根據(jù)表達(dá)式確定修改的行(1)修改一行一列
update exam_result set math = math + 30 where name = '張三';//把name屬性為‘張三’的數(shù)學(xué)成績(jī)+30(2)修改一行多列
update exam_result set math = math + 30,english = english + 20 where name = '張三';(3)修改多行數(shù)據(jù)(where過濾出來(lái)的結(jié)果是多行)
//成績(jī)表中所有名中帶三的加30分 update exam_result set math = math + 30 where name like '%三%';(4)全列修改
update 不帶where條件;//(重置)4.刪除(delete)
delete from 表名 where 條件;刪除全表數(shù)據(jù)
delete from exam_result;//行行delete,慢,可加條件,可恢復(fù) truncate table exam_result;//相當(dāng)于在os中直接把數(shù)據(jù)變成0,快,不可恢復(fù),不能加條件三.MySQL進(jìn)階
1.數(shù)據(jù)庫(kù)約束
1.1約束類型
- NOT NULL - 指示某列不能存儲(chǔ) NULL 值。
- UNIQUE - 保證某列的每行必須有唯一的值。
- DEFAULT - 規(guī)定沒有給列賦值時(shí)的默認(rèn)值。
- PRIMARY KEY - NOT NULL 和 UNIQUE 的結(jié)合。確保某列(或兩個(gè)列多個(gè)列的結(jié)合)有唯一標(biāo)識(shí),有助于更容易更快速地找到表中的一個(gè)特定的記錄。
- FOREIGN KEY - 保證一個(gè)表中的數(shù)據(jù)匹配另一個(gè)表中的值的參照完整性。
- CHECK - 保證列中的值符合指定的條件。對(duì)于MySQL數(shù)據(jù)庫(kù),對(duì)CHECK子句進(jìn)行分析,但是忽略CHECK子句。
示例:
-- 重新設(shè)置學(xué)生表結(jié)構(gòu) DROP TABLE IF EXISTS student; CREATE TABLE student ( id INT NOT NULL PRIMARY KEY, //id屬性不為空(設(shè)置為主鍵時(shí)可省略not null) sn INT UNIQUE,//指定sn屬性為唯一、不可重復(fù)的 name VARCHAR(20) DEFAULT 'unkown',//插入name列為空時(shí),默認(rèn)值為‘unknown’ qq_mail VARCHAR(20) );對(duì)于整數(shù)類型的主鍵,常常搭配自增長(zhǎng)auto_increment來(lái)使用。插入數(shù)據(jù)對(duì)應(yīng)字段不給值時(shí),使用最大值+1
1.2外鍵用于關(guān)聯(lián)其他表的主鍵或唯一鍵
foreign key (字段名) references 主表(列)2.表的設(shè)計(jì)
三大范式
2.1 一對(duì)一
2.2一對(duì)多
2.3多對(duì)多
3.新增
插入查詢結(jié)果
insert into tb_name(字段1,字段2,...) select ....案例:創(chuàng)建一張用戶表,設(shè)計(jì)有name姓名、email郵箱、sex性別、mobile手機(jī)號(hào)字段。需要把已有的
學(xué)生數(shù)據(jù)復(fù)制進(jìn)來(lái),可以復(fù)制的字段為name、qq_mail
4.查詢
4.1聚合查詢
(1)聚合函數(shù)
| count() | 返回查詢到的數(shù)據(jù)數(shù)量 |
| sum() | 返回查詢數(shù)據(jù)的總和 |
| avg() | 返回查詢數(shù)據(jù)的平均值 |
| max() | 返回查詢到的數(shù)據(jù)的最大值 |
| min() | 返回查詢到的數(shù)據(jù)的最小值 |
count(任意值)效果相同,相當(dāng)于在臨時(shí)表中創(chuàng)建了一列屬性,值都為設(shè)置的任意值,統(tǒng)計(jì)當(dāng)前有多少行,速度快
(2)GROUP BY 子句
SELECT 中使用 GROUP BY 子句可以對(duì)指定列進(jìn)行分組查詢。需要滿足:使用 GROUP BY 進(jìn)行分組查詢時(shí),SELECT 指定的字段必須是“分組依據(jù)字段”,其他字段若想出現(xiàn)在SELECT 中則必須包含在聚合函數(shù)
中。
(3)HAVING
GROUP BY 子句進(jìn)行分組以后,需要對(duì)分組結(jié)果再進(jìn)行條件過濾時(shí),不能使用 WHERE 語(yǔ)句,而需要用HAVING
4.2聯(lián)合查詢
//初始化測(cè)試數(shù)據(jù): drop table if exists classes; drop table if exists student; drop table if exists course; drop table if exists score;create table classes (id int primary key auto_increment, name varchar(20), `desc` varchar(100));create table student (id int primary key auto_increment, sn varchar(20), name varchar(20), qq_mail varchar(20) ,classes_id int);create table course(id int primary key auto_increment, name varchar(20));create table score(score decimal(3, 1), student_id int, course_id int);insert into classes(name, `desc`) values ('計(jì)算機(jī)系2019級(jí)1班', '學(xué)習(xí)了計(jì)算機(jī)原理、C和Java語(yǔ)言、數(shù)據(jù)結(jié)構(gòu)和算法'), ('中文系2019級(jí)3班','學(xué)習(xí)了中國(guó)傳統(tǒng)文學(xué)'), ('自動(dòng)化2019級(jí)5班','學(xué)習(xí)了機(jī)械自動(dòng)化');insert into student(sn, name, qq_mail, classes_id) values ('09982','黑旋風(fēng)李逵','xuanfeng@qq.com',1), ('00835','菩提老祖',null,1), ('00391','白素貞',null,1), ('00031','許仙','xuxian@qq.com',1), ('00054','不想畢業(yè)',null,1), ('51234','好好說(shuō)話','say@qq.com',2), ('83223','tellme',null,2), ('09527','老外學(xué)中文','foreigner@qq.com',2);insert into course(name) values ('Java'),('中國(guó)傳統(tǒng)文化'),('計(jì)算機(jī)原理'),('語(yǔ)文'),('高階數(shù)學(xué)'),('英文');insert into score(score, student_id, course_id) values -- 黑旋風(fēng)李逵 (70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6), -- 菩提老祖 (60, 2, 1),(59.5, 2, 5), -- 白素貞 (33, 3, 1),(68, 3, 3),(99, 3, 5), -- 許仙 (67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6), -- 不想畢業(yè) (81, 5, 1),(37, 5, 5), -- 好好說(shuō)話 (56, 6, 2),(43, 6, 4),(79, 6, 6), -- tellme (80, 7, 2),(92, 7, 6);classes表
course表
score表
student表
(1)內(nèi)連接
select 字段 from 表1 別名1 [inner] join 表2 別名2 on 連接條件 and 其他條件; select 字段 from 表1 別名1,表2 別名2 where 連接條件 and 其他條件;
(2)外連接
外連接分為左外連接和右外連接。如果聯(lián)合查詢,左側(cè)的表完全顯示我們就說(shuō)是左外連接;右側(cè)的表完全顯示我們就說(shuō)是右外連接。
案例:查詢所有同學(xué)的成績(jī),及同學(xué)的個(gè)人信息,如果該同學(xué)沒有成績(jī),也需要顯示
-- “老外學(xué)中文”同學(xué) 沒有考試成績(jī),也顯示出來(lái)了 select * from student stu left join score sco on stu.id=sco.student_id; -- 對(duì)應(yīng)的右外連接為: select * from score sco right join student stu on stu.id=sco.student_id; -- 學(xué)生表、成績(jī)表、課程表3張表關(guān)聯(lián)查詢 SELECT stu.id, stu.sn, stu.NAME, stu.qq_mail, sco.score, sco.course_id, cou.NAME FROM student stu LEFT JOIN score sco ON stu.id = sco.student_id LEFT JOIN course cou ON sco.course_id = cou.id ORDER BY stu.id;(3)自連接
自連接是指在同一張表連接自身進(jìn)行查詢。
案例:
顯示所有“計(jì)算機(jī)原理”成績(jī)比“Java”成績(jī)高的成績(jī)信息
以上查詢只顯示了成績(jī)信息,并且是分布執(zhí)行的。要顯示學(xué)生及成績(jī)信息,并在一條語(yǔ)句顯示:
SELECT stu.*, s1.score Java, s2.score 計(jì)算機(jī)原理 FROM score s1 JOIN score s2 ON s1.student_id = s2.student_id JOIN student stu ON s1.student_id = stu.id JOIN course c1 ON s1.course_id = c1.id JOIN course c2 ON s2.course_id = c2.id AND s1.score < s2.score AND c1.NAME = 'Java' AND c2.NAME = '計(jì)算機(jī)原理';(4)子查詢
子查詢是指嵌入在其他sql語(yǔ)句中的select語(yǔ)句,也叫嵌套查詢
- 單行子查詢:返回一行記錄的子查詢
查詢與“不想畢業(yè)” 同學(xué)的同班同學(xué):
- 多行子查詢:返回多行記錄的子查詢
案例:查詢“語(yǔ)文”或“英文”課程的成績(jī)信息 - [NOT] IN關(guān)鍵字:
可以使用多列包含:
-- 插入重復(fù)的分?jǐn)?shù):score, student_id, course_id列重復(fù) insert into score(score, student_id, course_id) values -- 黑旋風(fēng)李逵 (70.5, 1, 1),(98.5, 1, 3), -- 菩提老祖 (60, 2, 1); -- 查詢重復(fù)的分?jǐn)?shù) SELECT * FROM score WHERE ( score, student_id, course_id ) IN ( SELECT score, student_id, course_id FROM score GROUP BY score, student_id, course_id HAVING count( 0 ) > 1 );- 在from子句中使用子查詢:子查詢語(yǔ)句出現(xiàn)在from子句中。這里要用到數(shù)據(jù)查詢的技巧,把一個(gè)
子查詢當(dāng)做一個(gè)臨時(shí)表使用。
查詢所有比“中文系2019級(jí)3班”平均分高的成績(jī)信息:
查詢成績(jī)表中,比以上臨時(shí)表平均分高的成績(jī)
SELECT * FROM score sco, ( SELECT avg( sco.score ) score FROM score sco JOIN student stu ON sco.student_id = stu.id JOIN classes cls ON stu.classes_id = cls.id WHERE cls.NAME = '中文系2019級(jí)3班' ) tmp WHERE sco.score > tmp.score;(5)合并查詢
在實(shí)際應(yīng)用中,為了合并多個(gè)select的執(zhí)行結(jié)果,可以使用集合操作符 union,union all。使用UNION
和UNION ALL時(shí),前后查詢的結(jié)果集中,字段需要一致。
- union
該操作符用于取得兩個(gè)結(jié)果集的并集。當(dāng)使用該操作符時(shí),會(huì)自動(dòng)去掉結(jié)果集中的重復(fù)行。
案例:查詢id小于3,或者名字為“英文”的課程:
- union all
該操作符用于取得兩個(gè)結(jié)果集的并集。當(dāng)使用該操作符時(shí),不會(huì)去掉結(jié)果集中的重復(fù)行。
案例:查詢id小于3,或者名字為“Java”的課程
四.MySQL索引和事物
1.索引
1.1概念
索引是一種特殊的文件,包含著對(duì)數(shù)據(jù)表里所有記錄的引用指針。可以對(duì)表中的一列或多列創(chuàng)建索引,并指定索引的類型,各類索引有各自的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。(具體細(xì)節(jié)在后續(xù)的數(shù)據(jù)庫(kù)原理課程講解)
1.2作用
- 數(shù)據(jù)庫(kù)中的表、數(shù)據(jù)、索引之間的關(guān)系,類似于書架上的圖書、書籍內(nèi)容和書籍目錄的關(guān)系。
- 索引所起的作用類似書籍目錄,可用于快速定位、檢索數(shù)據(jù)。
- 索引對(duì)于提高數(shù)據(jù)庫(kù)的性能有很大的幫助。
1.3使用場(chǎng)景
- 數(shù)據(jù)量較大,且經(jīng)常對(duì)這些列進(jìn)行條件查詢。
- 該數(shù)據(jù)庫(kù)表的插入操作,及對(duì)這些列的修改操作頻率較低。
- 索引會(huì)占用額外的磁盤空間。
滿足以上條件時(shí),考慮對(duì)表中的這些字段創(chuàng)建索引,以提高查詢效率。
反之,如果非條件查詢列,或經(jīng)常做插入、修改操作,或磁盤空間不足時(shí),不考慮創(chuàng)建索引。
1.4使用
創(chuàng)建主鍵約束(PRIMARY KEY)、唯一約束(UNIQUE)、外鍵約束(FOREIGN KEY)時(shí),會(huì)自動(dòng)創(chuàng)建對(duì)應(yīng)列的索引。
- 查看索引
- 創(chuàng)建索引
對(duì)于非主鍵、非唯一約束、非外鍵的字段,可以創(chuàng)建普通索引
create index 索引名 on 表名(字段名);- 刪除索引
2.事務(wù)
2.1為什么要使用事務(wù)
準(zhǔn)備測(cè)試表:
drop table if exists accout; create table accout(id int primary key auto_increment,name varchar(20) comment '賬戶名稱',money decimal(11,2) comment '金額' ); insert into accout(name, money) values ('阿里巴巴', 5000), ('四十大盜', 1000);比如說(shuō),四十大盜把從阿里巴巴的賬戶上偷盜了2000元
-- 阿里巴巴賬戶減少2000 update accout set money=money-2000 where name = '阿里巴巴'; -- 四十大盜賬戶增加2000 update accout set money=money+2000 where name = '四十大盜';假如在執(zhí)行以上第一句SQL時(shí),出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤,或是數(shù)據(jù)庫(kù)掛掉了,阿里巴巴的賬戶會(huì)減少2000,但是四十大盜的賬戶上就沒有了增加的金額。
解決方案:使用事務(wù)來(lái)控制,保證以上兩句SQL要么全部執(zhí)行成功,要么全部執(zhí)行失敗。
2.2 事務(wù)的概念
事務(wù)指邏輯上的一組操作,組成這組操作的各個(gè)單元,要么全部成功,要么全部失敗。
在不同的環(huán)境中,都可以有事務(wù)。對(duì)應(yīng)在數(shù)據(jù)庫(kù)中,就是數(shù)據(jù)庫(kù)事務(wù)。
2.3事務(wù)的特性
2.4 使用
(1)開啟事務(wù):start transaction;
(2)執(zhí)行多條SQL語(yǔ)句
(3)回滾或提交:rollback/commit;
說(shuō)明:rollback即是全部失敗,commit即是全部成功。
start transaction; -- 阿里巴巴賬戶減少2000 update accout set money=money-2000 where name = '阿里巴巴'; -- 四十大盜賬戶增加2000 update accout set money=money+2000 where name = '四十大盜'; commit;五.JDBC
1.獲取數(shù)據(jù)源
MysqlDataSource dataSource = new MysqlDataSoure();2.配置數(shù)據(jù)源屬性
dataSource.setURL("jdbc:mysql://127.0.0.1:3306/庫(kù)名?characterEncoding = utf8&useSSL=false"); dataSource.setUser("root"); dataSource.setPassword("數(shù)據(jù)庫(kù)的密碼");3.獲取數(shù)據(jù)庫(kù)的連接
需要導(dǎo)入java.sql.Connection
Connection connection = dataSource.getConnection();4.寫sql語(yǔ)句
String sql = "insert into user(username,password) values (?,?)";5.獲取sql對(duì)象
獲取執(zhí)行sql的Statement對(duì)象,mysql中每一個(gè)sql的執(zhí)行就對(duì)應(yīng)著一個(gè)Statement對(duì)象
PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1,"張三"); statement.setString(2,"111");statement:用于執(zhí)行不帶參數(shù)的簡(jiǎn)單sql語(yǔ)句
PrepareStatement: 1.用于執(zhí)行帶或不帶參數(shù)的sql語(yǔ)句 2.sql語(yǔ)句會(huì)預(yù)編譯在數(shù)據(jù)庫(kù)系統(tǒng) 3.執(zhí)行速度快于statement
6.執(zhí)行這個(gè)sql,增刪改查調(diào)用executeUpdate,返回受影響的行數(shù)
int rows = statement.executeUpdate(); System.out.println("插入成功,插入" + rows + "行");7.關(guān)閉資源
connection.close();8.具體CURD的實(shí)現(xiàn)
總結(jié)
- 上一篇: 插入排序及其性能分析(动图演示)
- 下一篇: 学会老板思维,用数据诊断优化业务!