MySQL資料庫 -- 終端 -- 操作命令1.0
mysql伺服器:(Mac可以通過homebrew來安裝)
sudo apt-get install mysql-server
sudo server mysql start
sudo server mysql stop
sudo server mysql restart
ps ajx | grep mysql 或 ps aux | grep mysql
mysql客戶端:
sudo apt-get install mysql-client
mysql -uroot -p
ctrl+d 或 quit 或 exit
-- mysql資料庫簡單操作:
mysql -uroot -p
select version();
select now();
prompt python>
資料庫操作:
create database python_test charset=utf8;
show databases;
show create database python_test;
drop database python_test;
select database();
use python_test;
資料表操作:
show tables;
create table person(
id int unsigned primary key auto_increment not null,
name varchar(20) not null default 0,
age tinyint unsigned default 0,
height decimal(5,2),
gender enum('男','女','中性','保密') default '保密',
cls_id int unsigned default 0,
is_delete bit default 0
);
show tables;
desc person;
show create table person;
drop table person;
修改表結構:alter table person xxx;
add:
alter table person add birthday datetime;
change:
alter table person change birthday birth datetime;
alter table person change birth birth date not null;
modify:
alter table person modify birth date nut null;
drop:
alter table person drop birth;
資料表中資料操作:
-增-insert:
方式1:
insert into person values
(0,'小明',18,180.00,2,1,0),
(0,'小月月',18,180.00,2,2,1),
(0,'彭于晏',29,185.00,1,1,0),
(0,'劉德華',59,175.00,1,2,1),
(0,'黃蓉',38,160.00,2,1,0),
(0,'鳳姐',28,150.00,4,2,1),
(0,'王祖賢',18,172.00,2,1,1),
(0,'周杰倫',36,NULL,1,1,0),
(0,'程坤',27,181.00,1,2,0),
(0,'劉亦菲',25,166.00,2,2,0),
(0,'金星',33,162.00,3,3,1),
(0,'靜香',12,180.00,2,4,0),
(0,'郭靖',12,170.00,1,4,0),
(0,'周杰',34,176.00,2,5,0);
方式2:
--準備資料 areas.sql 建立一個表 areas 結構搭建好後
-- 通過 source 指令匯入一個sql檔案,注意 .sql 字尾不可省略
source ~/Desktop/areas.sql
方式3:
insert into person (name, height) values ('王菲', 170),('謝霆鋒', 170),('成龍', 173);
方式4:多表間操作-子查詢插入資料-insert ... select # 將查詢的結果插入到某一個表中
-以 jing_dong 資料庫為例:
insert into goods_cates (name) select cate_name from goods group by cate_name;
-刪-delete:
delete from person where id = 7;
-改-update:
方式1:
update person set name='大月月',age=20,height=184.00 where id = 2;
方式2:連線更新-表內資料
update goods as g join goods_cates as c on g.cate_name = c.name set g.cate_name = c.id;
-注意:如果 表結構 約束改變,需要修改約束
-查-select:
select * from person;
select age,name,height from person;
select age as '芳名', height as '身高', age as '芳齡' from person;
-加雞腿
-- 建立表 並且插入資料 一步到位
- create ... select # 建立表的時候,就插入資料
-- brand_name 品牌名稱
- 如果查詢的資料的欄位和表中的欄位名不一樣 此時會在表中建立一個新的名字一樣的欄位,將查詢到的資料一一對應的自動建立的欄位上面
-- 給brand_name 起別名, 或者將goods_brands表中的name 修改為brand_name
create table if not exists goods_brands(
id int unsigned primary key auto_increment,
name varchar(40) not null
) select brand_name as name from goods group by brand_name;
mysql資料庫複雜操作:
-以 python_test_1 資料庫為例;
-基礎查詢
select * from students;
select name,gender from students;
select age as '芳名', gender as '性別' from students;
select students.* from students;
select students.name, students.gender from students;
select python_test_1.students.* from students;
select s.name, s.age, s.gender from students as s;
-去重行
select distinct gender from students;
-條件查詢
select * from students where age > 18;
select * from students where age = 18;
select * from students where age != 18;
select * from students where age >= 18 and gender = '男';
select * from students where age >= 18 or gender = '女';
select * from students where not age = 18;
-模糊查詢
like: % 任意字元可有可無 _ 任意一個字元
select * from students where name like '小%';
select * from students where name like '__';
rlike:正則表示式規則
select * form students where name rlike '^周.*';
-範圍查詢-在不在...裡
in not in 非連續範圍,列舉
select * from students where age in (18,18,34,49,45);
select * from students where age not in (18,34);
between ... and ... not between ... and ... 連續範圍[ ],閉區間
select * from students where age between 18 and 50;
select * from students where age not between 18 and 34;
-空判斷-is判斷-null not null
select * from students where height is null;
select * from students where height is not null;
-聚合統計函式-目的是為了-統計
-總數count()
* 按行計數,即使null
select count(*) from students;
欄位計數,如果null不計數
select count(height) from students;
-最大值max()-最小值min()
select max(height) from students;
-求和sum()
select sum(age) from students;
-平均值avg()
select avg(age) from students;
select sum(age)/count(*) from students;
-四捨五入round(123.23, 1) 保留1位小數,如:round(23.46, 1) -> 23.5 round(23.44, 1) ->23.4
select round(avg(age), 2) from students;
-加雞腿
? 幫助文件
? functions;
? round;
? avg;
-分組
-group by 按條件-欄位中的值相同的,分組成一組一組的(行)
select gender as g from students group by gender;
select gender,avg(age) from students group by gender;
select gender,count(*),max(age),avg(height) from students group by gender;
-group_concat() 按條件分組成一組一組的(行),將欄位中值的以 “集合” 形式顯示出來,如: 男 (彭于晏,劉德華,周杰倫,程坤,郭靖,胡歌)
select group_concat(name) from students group by gender;
select gender, group_concat(name) from students group by gender;
select gender,group_concat(name) as '對應性別都有誰,叫什麼名字,列舉出來',max(age) from students group by gender;
-having 條件篩選 表示對於已經分組的資料做進一步的篩選 和 分組技能 是一對 cp
注意:有having 一定 group by (having 雖然可以用 where 替代,但大家都這樣用,共識,好識別)
select gender from students group by gender having gender = '男';
-with rollup 在最後新增一行,來記錄當前列裡所有記錄的總和
select gender as g, count(*) from students group by gender with rollup;
select gender as g, group_concat(name) from students group by gender with rollup;
-排序-order by 條件
asc 升序(預設) desc 降序
select * from students where age between 18 and 36 and gender = 1 order by age;
select * from students where age between 18 and 36 and gender = 1 order by age asc;
多個欄位,首要條件,次要條件,次次要條件...
select * from students where age between 18 and 36 and gender = 2 order by age asc, height desc, id desc;
-分頁-limit start, count
-- start: 表示從哪裡開始查詢, start 預設值為0, 可以省略, 表示跳過多少條資料 ->(pagenum - 1) * count
-- count: 表示當頁需要查詢多少條
-格式:limit (pagenum - 1) * count, count;
第1頁
select * from students limit 4;
select * from students limit 0,4;
第2頁
select * from students limit 4,4;
--例子:按照年齡從小到大排序,每頁顯示5個,顯示第3頁的資訊
select * from students order by age asc limit 10,5;
-SQL語句格式先後排序(權重)
-- 簡單小結:
條件查詢(比較、邏輯、模糊、範圍、空)
分組、分組後進一步篩選
排序
分頁
select distinct * ,[group_concat(name, age)],[round(avg(age), 2)],[聚合統計函式]
from 表名
where ....
group by ... having ...
order by ...
limit start,count
-邏輯刪除 標記這條資料在某些情況不能夠被顯示
-使用bit 型別來實現,bit 是二進位制資料,只有 0 1
--諮詢牛哥後,一般預設表中出現 0001就是邏輯刪除,表中顯示 什麼都沒有 就是沒有邏輯刪除,跟最初表結構定義預設值無關
-- 查詢students中沒有邏輯刪除的學生資訊
select * from students where is_delete = 0;
-資料庫備份和恢復(mysqldump, mysql)
-備份:mysqldump 命令
--python_test_bf.sql 如果不存在會自動建立
mysqldump -uroot -p python_test > ~/Desktop/python_test_bf.sql
-- mysqldump -udianfubao -h192.168.212.101 -p noah > ~/Desktop/noah.sql
-恢復 mysql 命令
--如果沒有demo 這個資料庫,必須先連線mysql,建立一個數據庫demo ,然後退出連線到終端:
--如果有demo 這個資料庫,裡邊表相同的會先刪除在恢復,表不同的保留不會遺失:
mysql -uroot -p demo < ~/Desktop/python_test_bf.sql
-- mysql -uroot -p cmdb < ~/Desktop/noah.sql
-升級版 如:從mac 備份整個完整的全部資料庫(包括系統自帶資料庫) 到mac 桌面,並恢復到ubuntu 中,這樣ubuntu 資料庫會和mac 資料庫完全一樣
-完整資料庫備份/恢復-這種操作,與上邊是不同的
-備份
--all-databases :匯出所有資料庫
--lock-all-tables :執行操作時鎖住所有表,防止操作時有資料修改
mysqldump -uroot -p --all-databases --lock-all-tables > ~/Desktop/master_db.sql
-拷貝轉移 mac 桌面 -> ubuntu 桌面
scp ~/Desktop/master_db.sql [email protected]:/home/python/Desktop/
-恢復
mysql -uroot -p < ~/Desktop/master_db.sql 這個指令需要手動敲入
mysql資料庫-表1-表2-表3...-間的操作處理-屬於條件查詢處理範疇-參考上邊SQL語句格式先後順序
-連續查詢
-內連線查詢
... join ... on ...
select * from students join classes on students.cls_id = classes.id;
select s.name,c.name from students as s join classes as c on s.cls_id = c.id;
-外連線查詢
--左外連線:左邊的表作為主表,主表的資料都會顯示(滿足連線條件+不滿足連線條件),右邊的表作為副表,不滿足連線條件的資料會以NULL填充
... left join ... on ...
select * from students left join classes on students.cls_id = classes.id;
-自關聯 一種特殊的內連續查詢 --> 自己關聯自己 a join a -->應用場景:無限分級(上下級)
-- 將一個表,想象成兩個表,將兩個表中的資料按照設定的連線條件進行篩選, 符合連線條件的資料才能夠被篩選出來
-以 python_test_0 中表 areas 為例:
--省級聯動 url:http://demo.lanrenzhijia.com/2014/city0605/
--省/直轄市 -> 市/區 ->區、縣/街道 --> (上下級,卻在一個表中)
-- 建立一個數據表areas
create table areas(
aid int primary key,
atitle varchar(20),
pid int
);
向表中匯入資料:source ~/Desktop/areas.sql
-- 查詢所有省份/直轄市
select * from areas where pid is null;
-- 查詢出廣州市有哪些區縣
select p.atitle, c.atitle from areas as p join areas as c on c.pid = p.aid where p.atitle = '河北省';
select p.atitle, c.atitle from areas as p join areas as c on p.aid = c.pid where p.atitle = '石家莊市';
-子查詢
-- 定義:在一個 select 語句中,嵌入了另外一個 select 語句, 那麼 被嵌入的 select 語句稱之 子查詢語句
--子查詢中特定關鍵字使用
in 範圍
格式1: 主查詢 where 條件 in (列子查詢(屬性))
格式2: 主查詢 where (欄位1,欄位2...) = (子查詢為行級子查詢 - 單行 n 列(記錄))
格式3: 主查詢 from (子查詢語句 - 多行多列(表)) as 別名 -- 這種 必須得起個別名 這很重要 因為此時子查詢結果是一個表
格式1:
select * from students where age in (select age from students where age in (18,18,25,36,38,40));
格式2:
select * from students where (height) > (select avg(height) from students);
select * from classes where id not in (select cls_id from students);
格式3: -- 直接當作 表 來使用,必須起 別名
select * from (select * from students) as tmp;
-\G 將查詢的資料的所有 列單獨成行 顯示,即顯示一條記錄,一條一條顯示出來,對於大大量資料可以更好的觀看:
select * from areas where pid is null\G;
-SQL練習
-以 jing_dong_test 資料庫為例:
-感受下,具體想看,去看看原來資料吧
-- 查詢每種型別中最貴的商品資訊
方法1: select g.* from goods as g join (select cate_name,max(price) as max_price from goods group by cate_name) as tmp on g.cate_name = tmp.cate_name and g.price = tmp.max_price;
方法2: select * from goods where (cate_name, price) in (select cate_name,max(price) from goods group by cate_name);
[email protected]以上都是SQL語句的經常使用幾乎所有方法,下邊是在程式碼中,經常用到的
mysql資料庫,在web 伺服器開發中,一般除了直接執行SQL語句外,經常配合 “檢視、事務、索引(面試)” 來使用,此外,和“外來鍵、關鍵字”(較少用)等 最詳情可去看 -> 00-mysql_第四天筆記.sql
- 檢視-view (對於一個SQL查詢語句的封裝)
-- 問題:
對於複雜的查詢,往往是有多個數據表進行關聯查詢而得到,如果資料庫因為某些原因發生了改變,如資料表名字改變了等,
為了保證查詢出來的資料與之前相同,則需要在多個地方進行修改,維護起來非常麻煩
-- 定義:
通俗的講,檢視就是 一條SELECT語句執行後返回的結果集 作為一張虛擬的表 是對基本表的引用
注意:一張虛表,查詢語句執行的結果,不儲存具體的資料(基本表資料發生了改變,檢視也會跟著改變)
-- 建立檢視 ->建議以 v_ 開頭命名
create view 檢視名稱 as select語句;
create view v_students as select * from students;
-- 檢視/使用檢視 -> 都當作一個表來使用即可 ->"中介公司"
-- 刪掉檢視
drop view 檢視名稱;
- 作用:
-- 提高了重用性,就像一個函式
-- 對資料庫重構,則卻不影響程式的執行(即:若資料表名字變了,但如果開發使用的是檢視,只需改視圖裡的這個表名就可以了,維護很方便)
-- 提高了安全效能,可以對不同的使用者
-- 讓資料更加清晰,減少複雜的SQL語句,增強可讀性
重重重點:
如: Django框架,內部封裝一些很常用到的SQL查詢的結果集,可以封裝成一個檢視,作為開發時查詢使用,可以減少一些SQL語句編寫;
-事務 (begin, commit, rollback)
-- 應用場景
-- 事務廣泛的運用於訂單系統、銀行系統等多種場景
-- 定義:
所謂事務,它是一個操作序列,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位
把一個多步驟任務打包在一個事務中,任何一個步驟失敗,則必須回滾所有的步驟,回到事務建立前的狀態
-- 引擎
表的引擎型別必須是 innodb 型別才可以使用事務,這是mysql表的預設引擎
-- 開啟事務 ->執行命令的變更,會維護到本地快取中,而不維護在物理表中
begin; 或者 start transaction;
-- 進行一系列操作
update students set name='大月月',age=20,height=184 where id = 2;
select * from students;
-- 提交事務 ->將快取中的資料變更維護到物理表中
commit;
-- 回滾事務 ->放棄快取中變更的資料,回到事務開啟前的狀態
rollback;
-- 作用:
1、平時在mysql 中修改 表中資料 的命令其實是會自動的觸發事務(自動開啟,自動提交),包括 insert、update、delete
2、而在SQL語句中使用 手動開啟事務 的原因是:可以進行多次資料的修改,如果成功一起成功,否則一起會滾到之前的資料
-- 注意:
事務 只對資料表中的資料有效,針對資料行加鎖,所操作資料行無法被另一使用者操作,對於 資料庫的操作和表結構 的更改無效
-- 總結:
事務的三大指令:
開啟事務: begin;
提交事務: commit;
回滾事務: rollback;
事務的四大特徵(簡稱 ACID ) -> 經常面試會被提問 ! ! !
1. 原子性: 一個事務必須被視為一個不可分割的最小工作單元,要麼成功要麼失敗
2. 一致性:狀態切換,只要沒有commit 即使系統崩潰等情況,事務所做修改無效,回到開啟前狀態
3. 隔離性:一個事務中所做的一切修改,只要還沒有commit ,對其他事務都是不可見的(看不出修改)
這裡,格外說下,Django框架預設也是這種隔離級別,在專案中,對於樂觀鎖處理資料庫,需要其他事務可以看見,要修改級別;
4. 永續性:只要事務commit ,所有的修改都會永久儲存到資料庫,即使之後系統崩潰,也不會丟失
- 索引-(大大重點)
-- 定義
索引是一種特殊的檔案(InnoDB資料表上的索引是表空間的一個組成部分),它們包含著對資料表裡所有記錄的引用指標
-- 目的
- 提高查詢的速度
- 只需要對合適的欄位建立索引(重查詢)
- 索引會額外的佔用磁碟空間, 會降低表的更新速度
01 檢視索引
show index from 表名;
02 建立索引
- 注意:
如果指定欄位是字串,需要指定長度,建議長度與定義欄位時的長度一致
欄位型別如果不是字串,可以不填寫長度部分
create index 索引名稱 on 表名(欄位名稱(長度))
03 刪除索引
drop index 索引名稱 on 表名;
- 索引例項
1. 準備大量的資料 100w
-- 建立資料庫test0
create database test0 charset=utf8;
-- 建立測試表test_index
create table if not exists test_index (
id int unsigned primary key auto_increment not null,
title varchar(10)
);
在python中通過for 迴圈來實現
-> day15_h - 01-表_索引_準備資料.py
在ubuntu 執行,匯入資料
2. 通過主鍵欄位查詢最後一條資料, 並且記錄查詢的時間
需要開啟時間檢測
set profiling=1;
select * from test_index where id = 1000000;
3. 通過非主鍵(沒有索引) 來查詢最後一條資料, 並且記錄查詢的時間
select * from test_index where title = "ha-999999";
檢視每個sql指令執行消耗的時間
show profiles;
4. 給非索引字典新增索引 ->名稱:title_index, 查詢最後一條資料, 獲取是時間
-- 如果給字串型別的欄位新增索引的時候, 需要設定欄位的長度, 最好和建立的時候設定的長度相等, 非字串的欄位就不需要寫長度
create index title_index on test_index(title(10));
5. 檢視下,目前表有幾個索引
show index from test_index;
6. 給有索引的欄位再做測試,對比時間
需要開啟時間檢測
set profiling=1;
- 兩者查詢速度已經到了一個量級 ! !
select * from test_index where id = 1000000;
select * from test_index where title = 'ha-999999';
檢視每個sql指令執行消耗的時間
show profiles;
- 索引原理: 有無索引的區別
select * from test_index where title = "ha-999999";
-- 將資料表的資料從硬碟讀取到記憶體, 在記憶體中進行資料逐條的比較
-- 不要重複多次的進行磁碟的IO, 效率很低, 記憶體(二級緩衝)
select * from test_index where id = 1000000;
-- 主鍵欄位有索引
-- 將主鍵欄位的 索引讀取記憶體
-- 索引是按照 一定順序排列(BTREE 平衡樹), 有序, 就決定查詢速度非常快,查詢索引非常快,可以通過索引直接定位到資料,
-- 42億: 無序, 最悲觀(最後一個)--> 42億
-- 42億: 有序, 最悲觀(二分式:一半一半...)--> (42億/2/2/2...)32次, BTREE比32次還要低,即BTREE會更快
時間複雜度: 都是最悲觀的那種情況.
- 樹結構 - 資料結構(重重點 ! ! ! 如: 氣泡排序, 快速排序) - 資料:
binary tree -> 二叉樹
balance tree -> 平衡樹
對比:
1. 平衡樹比二叉樹更快
2. 平衡樹(矮且胖)、二叉樹(高且瘦)
- 總結:
1. 非索引欄位, 將資料從硬碟讀取到記憶體,並且一條一條的比對 這需要消耗效能, 導致查詢很慢
2. 建立了索引之後, 索引會按照 樹結構(BTREE)排序(有序), 通過有索引欄位查詢資料的時候
3. 讀取索引根節點, 磁碟IO的數量也會小很多, 將資料讀取到記憶體進行資料的比較, 快速找到對應的資料索引位置, 再通過索引定位到資料
4. 資料庫的索引查詢的複雜度 比logn還要低
下一節
索引 賬戶管理 mysql資料庫伺服器主從 等