1. 程式人生 > >MySQL資料庫 -- 終端 -- 操作命令1.0

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資料庫伺服器主從 等