MySQL總結

1.初識

1.數據庫

  1. 什麼角色: 用戶名密碼 商品價格等信息 對數據的處理更便捷
  2. web程序 數據庫管理員專門管理 MySQL是一個開
  3. 數據庫的縮寫 db
  4. DBMS 數據庫管理系統
  5. mysql RDBMS 關係型數據庫管理系統
  6. 解決了:
    1. 文件操做的效率和便捷問題
    2. 多個服務同時使用數據的一致性問題
    3. 安全和並法問題

2.數據庫分類

  1. 關係型數據庫
    1. 慢 經過一個信息其餘的信息,帳號密碼
    2. MySQL(免費裏面最好用) Oracle(收費 但最好)[同一家公司]
    3. sqlserver(微軟旗下)
    4. sqllite(輕量級 不多用) accesse(小金融公司)
  2. 非關係型數據庫
    1. 快 缺點是關聯性很不搶
    2. redis最好 MongoDB(輕量級 直接用)
    3. memcache(之前貨 內存級別)
  3. MySQL數據庫管理系統 DBMS
    1. 之後用到的數據庫
    2. 用的最可能是5.6 5.7坑不少

3.卸載,安裝

  1. 卸載html

    1. 在裏面找MySQL 環境變量 找到以後先中止 在cmd裏面python

    2. 自帶客戶端MySQL.exe 第三方Navicat好用 可是先不用mysql

    3. 中止服務 刪除服務 把安裝軟件也刪除(文件夾) 刪除環境變量(先找到)nginx

    4. 最後重啓 是清除註冊表(百度刪除方法)web

      net stop mysql 中止mysql服務
          mysqld remove  刪除服務
          把安裝軟件也刪掉
          刪除環境變量
          清除註冊表/重啓計算機
  2. 安裝正則表達式

    1. 路徑>>>路徑不能有中文 路徑不能有特殊字符 \t \......
    2. 修改配置文件>>>編碼utf-8 全部配置項後面不能有特殊符號 修改兩個路徑basedir datadir
    3. 檢測文件的擴展名設置>>>不要隱藏 禁止隱藏
    4. 配置環境變量>>> 在path中添加個路徑 bin的路徑
    5. 以管理員的身份從新打開一個cmd>>>mysqld install 安裝成功
    6. 啓動mysql>>>net start mysql 啓動mysql server
    7. 在cmd啓動mysql 客戶端>>>mysql>>>客戶端和本地的mysql server相連

4.用戶操做和登陸

建立用戶和受權redis

  1. mysql server端
    1. net start mysql 啓動一個叫作mysql的服務
    2. net stop mysql 中止一個服務
  2. mysql 啓動客戶端,客戶端會自動的鏈接本地的3306端口
    1. mysql -uroot 表示要用root用戶登錄>>>默認密碼是空==root最高權限==
    2. set password = password('123'); 設置密碼
    3. mysql -uroot -p 回車>>>Enter password :123 使用密碼登錄
    4. 登錄成功mysql -uroot -p123 回車 直接登錄成功
  3. 建立帳號
    1. 使用公司的數據庫 管理員會建立一個帳號給你用>>你的數據庫 借給別人用也能夠建立一個帳號
    2. 建立:>>>mysql>create user 'eva'@'192.168.13.%' identified by '123';
    3. 遠程登錄>>>mysql> -ueva -p123 -h192.168.13.254
    4. 查看某個用戶的權限>>>mysql> show grants for 'eva'@'192.168.10.%';
    5. 建立帳號並受權>>>mysql> grant all on *.* to 'eva'@'%' identified by '123' (all是最高權限)
    6. 受權>>>mysql> flush privileges; # 刷新使受權當即生效
    7. ==強行離職 補貼N+1工資 風險與機遇並存==

2.MySQL的庫.表的詳細操做

1.庫操做

  1. 增:create database db1 charset utf8;
  2. 增:create database db1; (能夠不寫utf8)
  3. 查:show databases;
  4. 查:show create database 庫名;(查看庫的詳細建立語句)
  5. 改:alter database db1 charset latin1;
  6. 刪除: drop database db1;
  7. 切換:use 庫名;

2.表操做

1.儲存引擎

  1. 數據的存儲方式 -- 存儲引擎engines 使用不一樣的存儲引擎,數據是以不一樣的方式存儲的sql

  2. 建立表設置儲存引擎:數據庫

    show create table staff;
    create table myisam_t (id int,name char(18)) engine=myisam;
    create table memory_t (id int,name char(18)) engine=memory;
  3. show engines; 查看存儲引擎安全

    https://img2018.cnblogs.com/blog/988061/201811/988061-20181114114754297-1522063600.png

    1566696025909

  4. innodb 2個文件 ==事務==

    1. mysql5.6以上 默認的存儲方式
    2. transaction 事務 保證數據安全 數據的完整性而設置的概念
    3. row-level locking 行級鎖
    4. table-level locking 表級鎖
    5. foreign keys 外鍵約束
    6. 樹tree - 加速查詢 (樹形結構(數據+樹) + 表結構)
    7. 1566696711695
  5. myisam 3個文件

    1. mysql5.5如下 默認的存儲方式
    2. table-level locking 表級鎖
    3. 樹tree - 加速查詢 (樹形結構 + 數據 + 表結構)
  6. 經常使用存儲引擎及使用場景

    1. ==InnoDB==>>>用於事務處理應用程序,支持外鍵和行級鎖。若是應用對事物的完整性有比較高的要求,在併發條件下要求數據的一致性,數據操做除了插入和查詢以外,還包括不少更新和刪除操做,那麼InnoDB存儲引擎是比較合適的。InnoDB除了有效的下降由刪除和更新致使的鎖定,還能夠確保事務的完整提交和回滾,對於相似計費系統或者財務系統等對數據準確要求性比較高的系統都是合適的選擇。
    2. ==MyISAM==>>>若是應用是以讀操做和插入操做爲主,只有不多的更新和刪除操做,而且對事務的完整性、併發性要求不高,那麼能夠選擇這個存儲引擎。
    3. ==Memory==>>>將全部的數據保存在內存中,在須要快速定位記錄和其餘相似數據的環境下,能夠提供極快的訪問。Memory的缺陷是對錶的大小有限制,雖然數據庫由於異常終止的話數據能夠正常恢復,可是一旦數據庫關閉,存儲在內存中的數據都會丟失。
  7. 流程關係

    1566698260664

2.先切換到文件夾下:==use 庫名==

  1. 增:create table 表名(id int,name char);
  2. 查:show tables;
  3. 查:show create table 表名;(表的詳細信息
  4. )
  5. 改:
    1. alter table 表名 rename 新名字; 改表名
    2. alter table t1 modify name char(3); 修改類型
    3. alter table t1 change name name1 char(2); 修更名字和類型
  6. 刪:drop table 表名;
  7. 清空表操做:
    1. delete from t1; #若是有自增id,新增的數據,仍然是以刪除前的最後同樣做爲起始。
    2. truncate table t1;數據量大,刪除速度比上一條快,且直接從零開始

3.MySQL的基礎數據類型

  1. 介紹

    1. 存儲引擎決定了表的類型,而表內存放的數據也要有不一樣的類型,每種數據類型都有本身的寬度,但寬度是可選的詳細參考

    2. mysql經常使用數據類型概覽

      #1. 數字:
          整型:tinyint  int  bigint
          小數:
              float :在位數比較短的狀況下不精準
              double :在位數比較長的狀況下不精準
                  0.000001230123123123
                  存成:0.000001230000
              decimal:(若是用小數,則用推薦使用decimal)
                  精準
                  內部原理是以字符串形式去存
      #2. 字符串:
          char(10):簡單粗暴,浪費空間,存取速度快
              root存成root000000
          varchar:精準,節省空間,存取速度慢
          sql優化:建立表時,定長的類型往前放,變長的日後放
                          好比性別           好比地址或描述信息
          >255個字符,超了就把文件路徑存放到數據庫中。
                  好比圖片,視頻等找一個文件服務器,數據庫中只存路徑或url。
      #3. 時間類型:
          最經常使用:datetime
      #4. 枚舉類型與集合類型
  2. 數值類型

    tinyint int
        create table int_t (
              ti tinyint,            # ****
              i  int,                # *****
              f float,      # 精度問題 小數點後5位 # *****
              d double,     # 精度更高但也不許確
              e decimal(30,20)
              tiun tinyint unsigned,
              iun int unsigned
        );

    1567073215115

  3. 日期類型

    內置函數  now()
    
    datetime  打卡時間/日誌/論壇博客類的評論\文章 *****
    date      員工生日/入職日期/離職日期/開班時間   *****
    time      上課時間/下課時間/規定上班時間    競賽數據
    year      年
    timestamp 因爲表示範圍的問題,致使用的少了
    
    create table time_t2(
        dt datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,   # 表示的範圍更大,還能擁有timestamp的特色
        d  date,
        t  time,
        y  year,
        ts timestamp    # 不能爲空,默認值是當前時間,在修改的時候同時更新時間
    )

    1567073239861

  4. 字符串類型

    char    0-255    定長存儲 存儲速度更快 佔用更多的空間  *****
            char(12)
            alex --> 'alex        ' --> 12的長度
        varchar 0-65535  變長存儲 存儲速度慢  佔用的空間小  ****
            varchar(12)
            'alex' --> 'alex4' --> 5的長度
    
    手機號碼/身份證號碼 : char
    用戶名/密碼 : 有必定範圍彈性 char
    評論 : varchar
    
    時間換空間,空間換時間.沒有能夠有也沒有能夠無

    1567073260924

  5. 枚舉類型與集合類型

    set 多選 集合 去重   從有限的條件中多選一個引號裏逗號分隔
    enum 單選 枚舉      單選只能從有限的條件裏選擇  沒有就是空
    
        單選題,只能從有限的條件中選擇
        create table enum_t(
            id int,
            name char(12),
            gender enum('男','女','不詳') 
        )
    
        gender性別(男 女 不詳)
    
        多選題,從有限的條件中選
        create table set_t(
            id int,
            name char(12),
            hobby set('抽菸','喝酒','燙頭','搓腳') 
        )

4.MySQL完整性約束

PRIMARY KEY (PK)    標識該字段爲該表的主鍵,能夠惟一的標識記錄
FOREIGN KEY (FK)    標識該字段爲該表的外鍵
NOT NULL    標識該字段不能爲空
UNIQUE KEY (UK)    標識該字段的值是惟一的
AUTO_INCREMENT    標識該字段的值自動增加(整數類型,並且爲主鍵)
DEFAULT    爲該字段設置默認值

UNSIGNED 無符號
ZEROFILL 使用0填充
  1. ==unsigned 無符號的:數字==

  2. not null與default

    1. not null 非空 null 可空

    2. default 默認值

      默認值,建立列時能夠指定默認值,當插入數據時若是未主動設置,則自動添加默認值
      create table tb1(
        nid int not null defalut 2,
        num int not null
      );
  3. unique 惟一

    1. 普通惟一

      1. 獨一無二,惟一屬性:id,身份證號等

      2. 是一種key,惟一鍵,是在數據類型以外的附加屬性,有加速查詢的做用

        create table department2(
        id int,
        name varchar(20),
        comment varchar(100),
        constraint uk_name unique(name)
        );
    2. 聯合惟一

      create table service(
        id int primary key auto_increment,
        name varchar(20),
        host varchar(15) not null,
        port int not null,
        unique(host,port) #聯合惟一
      );
  4. primary key

    1. 從約束角度看primary key字段的值不爲空且惟一,那咱們直接使用not null+unique不就能夠了嗎,要它幹什麼?主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之爲索引組織表,一張表中必須有且只有一個主鍵

    2. 一個表中能夠:單列作主鍵 多列作主鍵(複合主鍵或者叫作聯合主鍵)

    3. 關於主鍵的通俗解釋和強調內容(重點************************)

      unique key和primary key都是MySQL的特殊類型,不只僅是個字段約束條件,還稱爲索引,能夠加快查詢速度,這個索引功能咱們後面再講,如今只講一下這些key做爲約束條件的效果。
      
          關於主鍵的強調內容:
              1.一張表中必須有,而且只能由一個主鍵字段:innodb引擎下存儲表數據的時候,會經過你的主鍵字段的數據來組織管理全部的數據,將數據作成一種樹形結構的數據結構,幫你較少IO次數,提升獲取定位數據、獲取數據的速度,優化查詢。
                  解釋:若是咱們在一張表中沒有設置primary key,那麼mysql在建立表的時候,會按照順序從上到下遍歷你設置的字段,直到找到一個not null unique的字段,自動識別成主鍵pri,經過desc能夠看到,這樣是否是很差啊,因此咱們在建立表的時候,要給他一個主鍵,讓他優化的時候用,若是沒有pri也沒有not null unique字段,那麼innodb引擎下的mysql被逼無奈,你沒有設置主鍵字段,主鍵又有不爲空且惟一的約束,又不能擅自給你的字段加上這些約束,那麼沒辦法,它只能給你添加一個隱藏字段來幫你組織數據,若是是這樣,你想一想,主鍵是否是幫咱們作優化查詢用的啊,這個優化是咱們能夠經過主鍵來查詢數據:例如:若是咱們將id設置爲主鍵,當咱們查一個id爲30的數據的時候,也就是select * from tb1 where id=30;這個查詢語句的速度很是快,不須要遍歷前面三十條數據,就好像咱們使用的字典似的,找一個字,不須要一頁一頁的翻書,能夠首先看目錄,而後看在哪一節,而後看在哪一頁,一步步的範圍,而後很快就找到了,這就像咱們說的mysql的索引(主鍵、惟一鍵)的工做方式,一步一步的縮小範圍來查找,幾步就搞定了,因此經過主鍵你可以快速的查詢到你所須要的數據,因此,若是你的主鍵是mysql幫你加的隱藏的字段,你查詢數據的時候,就不能將這個隱藏字段做爲條件來查詢數據了,就不能享受到優化後的查詢速度了,對麼
      
              2.一張表裏面,一般都應該有一個id字段,並且一般把這個id字段做爲主鍵,固然你非要讓其餘的字段做爲主鍵也是能夠的,看你本身的設計,建立表的時候,通常都會寫create table t1(id int primary key);id int primary key這個東西在建表的時候直接就寫上
    4. 在沒有設置主鍵的時候,not null+unique會被默認當成主鍵

      mysql> create table t1(id int not null unique);
      Query OK, 0 rows affected (0.02 sec)
      
      mysql> desc t1;
      +-------+---------+------+-----+---------+-------+
      | Field | Type    | Null | Key | Default | Extra |
      +-------+---------+------+-----+---------+-------+
      | id    | int(11) | NO   | PRI | NULL    |       |
      +-------+---------+------+-----+---------+-------+
      1 row in set (0.00 sec)
    5. 單列主鍵測試

      ============單列作主鍵===============
      #方法一:not null+unique
      create table department1(
      id int not null unique, #主鍵
      name varchar(20) not null unique,
      comment varchar(100)
      );
      
      mysql> desc department1;
      +---------+--------------+------+-----+---------+-------+
      | Field   | Type         | Null | Key | Default | Extra |
      +---------+--------------+------+-----+---------+-------+
      | id      | int(11)      | NO   | PRI | NULL    |       |
      | name    | varchar(20)  | NO   | UNI | NULL    |       |
      | comment | varchar(100) | YES  |     | NULL    |       |
      +---------+--------------+------+-----+---------+-------+
      rows in set (0.01 sec)
      
      #方法二:在某一個字段後用primary key
      create table department2(
      id int primary key, #主鍵
      name varchar(20),
      comment varchar(100)
      );
      
      mysql> desc department2;
      +---------+--------------+------+-----+---------+-------+
      | Field   | Type         | Null | Key | Default | Extra |
      +---------+--------------+------+-----+---------+-------+
      | id      | int(11)      | NO   | PRI | NULL    |       |
      | name    | varchar(20)  | YES  |     | NULL    |       |
      | comment | varchar(100) | YES  |     | NULL    |       |
      +---------+--------------+------+-----+---------+-------+
      rows in set (0.00 sec)
      
      #方法三:在全部字段後單獨定義primary key
      create table department3(
      id int,
      name varchar(20),
      comment varchar(100),
      constraint pk_name primary key(id); #建立主鍵併爲其命名pk_name
      
      mysql> desc department3;
      +---------+--------------+------+-----+---------+-------+
      | Field   | Type         | Null | Key | Default | Extra |
      +---------+--------------+------+-----+---------+-------+
      | id      | int(11)      | NO   | PRI | NULL    |       |
      | name    | varchar(20)  | YES  |     | NULL    |       |
      | comment | varchar(100) | YES  |     | NULL    |       |
      +---------+--------------+------+-----+---------+-------+
      rows in set (0.01 sec)
    6. 聯合主鍵解釋

      聯合主鍵
              和聯合惟一是相似的,
              mysql> create table t10(
                  ->id int,
                  ->port int,
                  ->primary key(id,port)
                  -> );
              Query OK, 0 rows affected (0.45 sec)
      
              mysql> desc t10;
              +-------+---------+------+-----+---------+-------+
              | Field | Type    | Null | Key | Default | Extra |
              +-------+---------+------+-----+---------+-------+
              | id    | int(11) | NO   | PRI | 0       |       | 
              | port  | int(11) | NO   | PRI | 0       |       |
              +-------+---------+------+-----+---------+-------+
              2 rows in set (0.10 sec)
      
              看key,兩個都寫的是pri,兩個聯合起來做爲主鍵,他們兩個做爲一個主鍵,不能再有其餘的主鍵了,也就是在建立表的時候,只能出現一次primary key方法。
              有同窗說,老師,我不寫primary key行不,只寫一個not null unique字段,固然行,可是咱們應該這樣作嗎,是否是不該該啊,因此之後設置主鍵的時候,就使用primary key來指定
    7. 多列(聯合)主鍵測試

      ==================多列作主鍵================
      create table service(
      ip varchar(15),
      port char(5),
      service_name varchar(10) not null,
      primary key(ip,port)
      );
      
      
      mysql> desc service;
      +--------------+-------------+------+-----+---------+-------+
      | Field        | Type        | Null | Key | Default | Extra |
      +--------------+-------------+------+-----+---------+-------+
      | ip           | varchar(15) | NO   | PRI | NULL    |       |
      | port         | char(5)     | NO   | PRI | NULL    |       |
      | service_name | varchar(10) | NO   |     | NULL    |       |
      +--------------+-------------+------+-----+---------+-------+
      3 rows in set (0.00 sec)
      
      mysql> insert into service values
          -> ('172.16.45.10','3306','mysqld'),
          -> ('172.16.45.11','3306','mariadb')
          -> ;
      Query OK, 2 rows affected (0.00 sec)
      Records: 2  Duplicates: 0  Warnings: 0
      
      mysql> insert into service values ('172.16.45.10','3306','nginx');
      ERROR 1062 (23000): Duplicate entry '172.16.45.10-3306' for key 'PRIMARY'
  5. auto_increment 自動增長

    1. 只能操做數字 自帶非空屬性 只能對unique字段進行設置 不受刪除影響 內部有記錄

    2. 默認起始位置爲1,步長也爲1.

      不指定id,則自動增加
      create table student(
      id int primary key auto_increment, 設置自動增長
      name varchar(20),
      sex enum('male','female') default 'male'
      );
    3. sex enum('male','female') default 'male' 建立表時指定auto_increment的初始值,注意初始值的設置爲表選項,應該放到括號外

    4. insert into student values(4,'asb','female'); 設置ID 對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增加

    5. insert into student(name) values('egon'); truncate student; 應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它(從0開始)

    6. alter table student auto_increment=3; 在建立完表後,修改自增字段的起始值

    7. show create table student;
      ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8(顯示默認值)

    8. 設置自增:

      set session auth_increment_increment=2 #修改會話級別的步長

      set global auth_increment_increment=2 #修改全局級別的步長(全部會話都生效)

  6. foreign key 外鍵約束

    1. 快速理解foreign key(外鍵其實就是標明表和表之間的關係,表和表之間若是有關係的話就三種:一對一,多對一,多對多)

      on delete cascade 級聯刪除
      on update cascade 級聯更新
  7. 分析步驟:

    1. 先站在左表的角度去找

      是否左表的多條記錄能夠對應右表的一條記錄,若是是,則證實左表的一個字段foreign key 右表一個字段(一般是id)

    2. 再站在右表的角度去找

      是否右表的多條記錄能夠對應左表的一條記錄,若是是,則證實右表的一個字段foreign key 左表一個字段(一般是id)

  8. 總結

    1. 多對一: 若是隻有步驟1成立,則是左表多對一右表 若是隻有步驟2成立,則是右表多對一左表
      1. 多對多:若是步驟1和2同時成立,則證實這兩張表時一個雙向的多對一,即多對多,須要定義一個這兩張表的關係表來專門存放兩者的關係
      2. 一對一:若是1和2都不成立,而是左表的一條記錄惟一對應右表的一條記錄,反之亦然。這種狀況很簡單,就是在左表foreign key右表的基礎上,將左表的外鍵字段設置成unique便可
    =====================多對一=====================
       create table press(
       id int primary key auto_increment,
       name varchar(20)
       );
    
       create table book(
       id int primary key auto_increment,
       name varchar(20),
       press_id int not null,
       foreign key(press_id) references press(id)
       on delete cascade
       on update cascade
       );
    
    
       insert into press(name) values
       ('北京工業地雷出版社'),
       ('人民音樂很差聽出版社'),
       ('知識產權沒有用出版社')
       ;
    
       insert into book(name,press_id) values
       ('九陽神功',1),
       ('九陰真經',2),
       ('九陰白骨爪',2),
       ('獨孤九劍',3),
       ('降龍十巴掌',2),
       ('葵花寶典',3)
       =====================多對多=====================
       create table author(
       id int primary key auto_increment,
       name varchar(20)
       );
    
    
       #這張表就存放做者表與書表的關係,即查詢兩者的關係查這表就能夠了
       create table author2book(
       id int not null unique auto_increment,
       author_id int not null,
       book_id int not null,
       constraint fk_author foreign key(author_id) references author(id)
       on delete cascade
       on update cascade,
       constraint fk_book foreign key(book_id) references book(id)
       on delete cascade
       on update cascade,
       primary key(author_id,book_id)
       );
    
    
       #插入四個做者,id依次排開
       insert into author(name) values('egon'),('alex'),('yuanhao'),('wpq');
    
       #每一個做者與本身的表明做以下
       1 egon: 
             1 九陽神功
             2 九陰真經
             3 九陰白骨爪
             4 獨孤九劍
             5 降龍十巴掌
             6 葵花寶典
    
    
       2 alex: 
             1 九陽神功
             6 葵花寶典
    
       3 yuanhao:
             4 獨孤九劍
             5 降龍十巴掌
             6 葵花寶典
    
       4 wpq:
             1 九陽神功
    
    
       insert into author2book(author_id,book_id) values
       (1,1),
       (1,2),
       (1,3),
       (1,4),
       (1,5),
       (1,6),
       (2,1),
       (2,6),
       (3,4),
       (3,5),
       (3,6),
       (4,1)
       ;
       =====================一對一=====================
       必定是student來foreign key表customer,這樣就保證了:
         1 學生必定是一個客戶,
         2 客戶不必定是學生,但有可能成爲一個學生
    
    
       create table customer(
       id int primary key auto_increment,
       name varchar(20) not null,
       qq varchar(10) not null,
       phone char(16) not null
       );
    
    
       create table student(
       id int primary key auto_increment,
       class_name varchar(20) not null,
       customer_id int unique, #該字段必定要是惟一的
       foreign key(customer_id) references customer(id) #外鍵的字段必定要保證unique
       on delete cascade
       on update cascade
       );
    
    
       #增長客戶
       insert into customer(name,qq,phone) values
       ('李飛機','31811231',13811341220),
       ('王大炮','123123123',15213146809),
       ('守榴彈','283818181',1867141331),
       ('吳坦克','283818181',1851143312),
       ('贏火箭','888818181',1861243314),
       ('戰地雷','112312312',18811431230)
       ;
    
    
       #增長學生
       insert into student(class_name,customer_id) values
       ('脫產3班',3),
       ('週末19期',4),
       ('週末19期',5)
       ;
  9. 外鍵約束有三種約束模式(都是針對父表的約束):

    1. 模式一: district 嚴格約束(默認的 ),父表不能刪除或者更新已經被子表數據引用的記錄
    2. 模式二:cascade 級聯模式:父表的操做,對應的子表關聯的數據也跟着操做 。
    3. 模式三:set null:置空模式,父表操做以後,子表對應的數據(外鍵字段)也跟着被置空。
    4. 一般的一個合理的約束模式是:刪除的時候子表置空;更新的時候子表級聯。
    5. 指定模式的語法:foreign key(外鍵字段)references 父表(主鍵字段)on delete 模式 on update 模式;
    6. 注意:刪除置空的前提條件是 外鍵字段容許爲空,否則外鍵會建立失敗。
    7. 外鍵雖然很強大,可以進行各類約束,可是外鍵的約束下降了數據的可控性和可拓展性。一般在實際開發時,不多使用外鍵來約束。

3.MySQL的行的詳細操做

1.刪除或修改被關聯字段

場景:book表和publish表爲多對一關係,book表的pid字段外鍵關聯到了publish表的id字段
1 查看外鍵關係名稱:
    show create table book; 
        | book  | CREATE TABLE `book` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `name` char(10) DEFAULT NULL,
          `pid` int(11) DEFAULT NULL,
          PRIMARY KEY (`id`),
          KEY `pid` (`pid`),
          CONSTRAINT `book_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `publish` (`id`)
        ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |

2 刪除外鍵關係
    alter table book drop foreign key book_ibfk_1(外鍵名稱);
3 刪除字段
    alter table publish drop id(字段名稱);
4 添加字段
    alter table publish add id(字段名稱) int(數據類型) primary key auto_increment(約束條件);

5 建立表完成以後,後添加外鍵關係
    alter table book add foreign key(pid) references publish(id);

2.建立外鍵時指定外鍵名稱

建立表時:
create table t1(
    id int,
    pid int,
    constraint fk_t1_publish foreign key(pid) references publish(id);
)
建立表完成以後,後添加外鍵關係
    alter table book add constraint fk_t1_publish foreign key(pid) references publish(id);

3.級聯

級聯有幾個模式

嚴格模式(默認的),外鍵有強制約束效果,被關聯字段不能隨意刪除和修改

模式(cascade):外鍵有強制約束效果,被關聯字段刪除或者修改,關聯他的那麼字段數據會隨之刪除或者修改

constraint fk_t1_publish foreign key(pid) references publish(id) on delete cascade on update cascade;

set null模式: 被關聯字段刪除時,關聯他的字段數據會置成null

4.增刪改查

  1. 增:insert into t1 values(1,'egon1'),(2,'egon2'),(3,'egon3');
  2. 查:select * from t1;
  3. 改:update t1 set name='sb' where id=2; 後面加條件
  4. 刪:delete from t1 where id=1;

5.SQL語句(三種)

  1. DDL語句 數據庫定義語言: 數據庫、表、視圖、索引、存儲過程,例如CREATE DROP ALTER
  2. DML語句 數據庫操縱語言: 插入數據INSERT、刪除數據DELETE、更新數據UPDATE、查詢數據SELECT
  3. DCL語句 數據庫控制語言: 例如控制用戶的訪問權限GRANT、REVOKE

6.額外

  1. *auto_increment 表示:自增
  2. *primary key 表示:約束(不能重複且不能爲空);加速查找

4.單表查詢

前提

1.單表查詢

select 某一個東西
        能夠查一個,多個,*全部
        調用函數 : now() user() database() concat() concat_ws()
        進行四則運算
        能夠去重 distinct
        能夠進行條件判斷 case when語句

2.單標查詢的語法

查詢數據的本質:mysql會到你本地的硬盤上找到對應的文件,而後打開文件,按照你的查詢條件來找出你須要的數據。下面是完整的一個單表查詢的語法

select * from,這個select * 指的是要查詢全部字段的數據。

SELECT distinct 字段1,字段2... FROM 庫名.表名 
from後面是說從庫的某個表中去找數據,mysql會去找到這個庫對應的文件夾下去找到你表名對應的那個數據文件,找不到就直接報錯了,找到了就繼續後面的操做

WHERE 條件  從表中找符合條件的數據記錄,where後面跟的是你的查詢條件

GROUP BY field(字段) 分組

HAVING 篩選   過濾,過濾以後執行select後面的字段篩選,就是說我要肯定一下須要哪一個字段的數據,你查詢的字段數據進行去重,而後在進行下面的操做

ORDER BY field(字段)  將結果按照後面的字段進行排序

LIMIT 限制條數  將最後的結果加一個限制條數,就是說我要過濾或者說限制查詢出來的數據記錄的條數

3.==重點中的重點==:關鍵字的執行優先級

from > where > group by > having > select > distinct > order by > limit

  1. 找到表:from
  2. 拿着where指定的約束條件,去文件/表中取出一條條記錄
  3. 將取出的一條條記錄進行分組group by,若是沒有group by,則總體做爲一組
  4. 將分組的結果進行having過濾
  5. 執行select
  6. 去重
  7. 將結果按條件排序:order by
  8. 限制結果的顯示條數
  9. 詳細博客

1.簡單查詢(*)

避免重複DISTINCT:
desc employee; 查看錶結構
SELECT id,name,sex,age,hire_date,post,post_comment,salary,office,depart_id FROM employee;  select後面寫什麼查詢什麼
SELECT * FROM employee; 查詢所有 不推薦用* ,查詢的時候*的效率低,
SELECT name,salary FROM employee; 查詢全部的name和salary
SELECT post FROM employee; 查詢全部的post 可是有重複
SELECT DISTINCT post FROM employee;  查詢post distinct去重功能
SELECT DISTINCT post,salary FROM employee;   由於post和salary沒有徹底同樣的
select distinct post,sex from employee;  post和sex兩組數據同樣纔會去重


經過四則運算查詢:
SELECT name, salary*12 FROM employee;   查薪資每一個都*12
SELECT name, salary*12 AS Annual_salary FROM employee;    as + 新字段名,就是起一個別名
SELECT name, salary*12 Annual_salary FROM employee;    經過新的別名查詢 除了乘法之外,加減乘除都是能夠的


自定義顯示格式,本身規定查詢結果的顯示格式:
CONCAT() 函數用於鏈接字符串
SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS Annual_salary from employee;    concat幫咱們作字符串拼接的,而且拼接以後的結果,都在一個叫作Annual_salary的字段中
SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS Annual_salary,CONCAT('性別:',sex) from employee;    分紅兩列
SELECT CONCAT(name,':',salary*12)  AS Annual_salary from employee;    經過冒號來將name和salary鏈接起來
select concat('<名字:',name,'>    ','<薪資:',salary,'>') from employee;    查出全部員工的名字,薪資,格式爲 <名字:egon>    <薪資:3000>
select distinct depart_id from employee;    查出全部的崗位(去掉重複)
SELECT name,salary*12 AS annual_year from employee;    查出全部員工名字,以及他們的年薪,年薪的字段名爲annual_year()

2.where約束

以前咱們用where 後面跟的語句是否是id=1這種類型的啊,用=號鏈接的,除了=號外,還能使用其餘的,看下面:

  1. 比較運算符:> < >= <= <> !=

  2. between 80 and 100 值在80到100之間

  3. and是都知足 or只要知足一個

  4. in(80,90,100) 值是80或90或100

  5. like 'egon%'
      pattern能夠是%或_,
      %表示任意多字符
      _表示一個字符

  6. 邏輯運算符:在多個條件直接可使用邏輯運算符 and or not

    1:單條件查詢
    SELECT name FROM employee 
     WHERE post='sale';    單表查詢 優先級,where的優先級比select高,因此順序是先找到這個employee表,而後按照post='sale'的條件,而後去表裏面select數據
    
    
    2:多條件查詢
    SELECT name,salary FROM employee 
            WHERE post='teacher' AND salary>10000;    多條件查詢
    
    
    3:關鍵字BETWEEN AND 寫的是一個區間
    SELECT name,salary FROM employee 
            WHERE salary BETWEEN 10000 AND 20000;    關鍵字BETWEEN AND 是一個區間
    SELECT name,salary FROM employee 
            WHERE salary NOT BETWEEN 10000 AND 20000;    加個not,就是不在這個區間內
    
    
    4:關鍵字IS NULL(判斷某個字段是否爲NULL不能用等號,須要用IS) 判斷null只能用is
    SELECT name,post_comment FROM employee 
            WHERE post_comment IS NULL;    關鍵字IS NULL(判斷某個字段是否爲NULL不能用等號,須要用IS) 判斷null只能用is
    SELECT name,post_comment FROM employee 
            WHERE post_comment IS NOT NULL;    加not,
    SELECT name,post_comment FROM employee 
            WHERE post_comment='';    ''是空字符串,不是null,兩個是不一樣的東西,null是啥也沒有,''是空的字符串的意思,是一種數據類型,null是另一種數據類型
    
    
    5:關鍵字IN集合查詢
    SELECT name,salary FROM employee 
            WHERE salary IN (3000,3500,4000,9000) ; salary裏面是in條件的打印
    SELECT name,salary FROM employee 
            WHERE salary NOT IN (3000,3500,4000,9000) ;    salary裏面不是in條件的打印
    
    6:關鍵字LIKE模糊查詢,模糊匹配,能夠結合通配符來使用
    SELECT * FROM employee 
            WHERE name LIKE 'eg%';    通配符’%’  匹配任意全部字符
    SELECT * FROM employee 
                WHERE name LIKE 'al__';    通配符’_’  匹配任意一個字符  注意我這裏寫的兩個_,用1個的話,匹配不到alex,由於al後面還有兩個字符ex。
    
    
    1. 查看崗位是teacher的員工姓名、年齡
    select name,age from employee where post = 'teacher';
    2. 查看崗位是teacher且年齡大於30歲的員工姓名、年齡
    select name,age from employee where post='teacher' and age > 30; 
    3. 查看崗位是teacher且薪資在9000-1000範圍內的員工姓名、年齡、薪資
    select name,age,salary from employee where post='teacher' and salary between 9000 and 10000;
    4. 查看崗位描述不爲NULL的員工信息
    select * from employee where post_comment is not null;
    5. 查看崗位是teacher且薪資是10000或9000或30000的員工姓名、年齡、薪資
    select name,age,salary from employee where post='teacher' and salary in (10000,9000,30000);
    6. 查看崗位是teacher且薪資不是10000或9000或30000的員工姓名、年齡、薪資
    select name,age,salary from employee where post='teacher' and salary not in (10000,9000,30000);
    7. 查看崗位是teacher且名字是jin開頭的員工姓名、年薪
    select name,salary*12 from employee where post='teacher' and name like 'jin%';
    where條件我們就說完了,這個where條件到底怎麼運做的,咱們來講一下:咱們以select id,name,age from employee where id>7;這個語句來講一下
    
      首先先找到employee表,找到這個表以後,mysql會拿着where後面的約束條件去表裏面找符合條件的數據,而後遍歷你表中全部的數據,查看一下id是否大於7,逐條的對比,而後只要發現id比7大的,它就會把這一整條記錄給select,可是select說我只拿id、name、age這個三個字段裏面的數據,而後就打印了這三個字段的數據,而後where繼續往下過濾,看看id是否是還有大於7的,而後發現一個符合條件的就給select一個,而後重複這樣的事情,直到把數據所有過濾一遍纔會結束。這就是where條件的一個工做方式。

3.分組查詢 group by

示例:
    # 統計每一個崗位的名稱以及最高工資
    select post,max(salary) from employee group by post;
    
    分組時能夠跟多個條件,那麼這個多個條件同時重複纔算是一組,group by 後面多條件用逗號分隔
    select post,max(salary) from employee group by post,id;

ONLY_FULL_GROUP_BY模式
set global sql_mode='ONLY_FULL_GROUP_BY';
若是設置了這個模式,那麼select後面只能寫group by後面的分組依據字段和聚合函數統計結果

什麼是分組?爲何要分組?

  1. 首先明確一點:分組發生在where以後,即分組是基於where以後獲得的記錄而進行的

  2. 分組指的是:將全部記錄按照某個相同字段進行歸類,好比針對員工信息表的職位分組,或者按照性別進行分組等

  3. 爲什麼要分組呢?是由於咱們有時候會須要以組爲單位來統計一些數據或者進行一些計算的,對不對,比方說下面的幾個例子
    取每一個部門的最高工資
    取每一個部門的員工數
    取男人數和女人數

  4. 小竅門:‘每’這個字後面的字段,就是咱們分組的依據,只是個小竅門,可是不能表示全部的狀況,看上面第三個分組,沒有'每'字,這個就須要咱們經過語句來自行判斷分組依據

    咱們能用id進行分組嗎,能,可是id是否是重複度很低啊,基本沒有重複啊,對不對,這樣的字段適合作分組的依據嗎?不適合,對不對,依據性別分組行不行,固然行,由於性別咱們知道,是否是就兩種啊,也可能有三種是吧,這個重複度很高,對不對,分組來查的時候纔有更好的意義

  5. 大前提:
    能夠按照任意字段分組,可是分組完畢後,好比group by post,只能查看post字段,若是想查看組內信息,須要藉助於聚合函數. 注意一點,在查詢語句裏面select 字段 from 表,這幾項是必需要有的,其餘的什麼where、group by等等都是無關緊要的

  6. select * from employee group by post; group by 語句 按照post分組

4.having過濾(分組再過濾)

select post,max(salary) from employee group by post having max(salary)>20000;
having過濾後面的條件可使用聚合函數,where不行
select post,avg(salary) as new_sa from employee where age>=30 group by post having avg(salary) > 10000;統計各部門年齡在30歲及以上的員工的平均薪資,而且保留平均工資大於10000的部門
select post,group_concat(name),count(id) from employee group by post having count(id) < 2;查詢各崗位內包含的員工個數小於2的崗位名、崗位內包含員工名字、個數
select post,avg(salary) from employee group by post having avg(salary) > 10000;查詢各崗位平均薪資大於10000的崗位名、平均工資
select post,avg(salary) from employee group by post having avg(salary) > 10000 and avg(salary) <20000;查詢各崗位平均薪資大於10000且小於20000的崗位名、平均工資
select count(distinct post) from employee;
去重distinct 統計個數count

5.去重

示例:
     select distinct post from employee;
注意問題:select的字段必須寫在distinct的後面,而且若是寫了多個字段,好比:
    select distinct post,id from employee;這句話,意思就是post和id兩個組合在一塊兒同時重複的纔算是重複數據

6.查詢排序 order by

按單列排序  salary排序的
    SELECT * FROM employee ORDER BY salary; #默認是升序排列
    SELECT * FROM employee ORDER BY salary ASC; #升序
    SELECT * FROM employee ORDER BY salary DESC; #降序
    
    多條件排序
    按照age字段升序,age相同的數據,按照salary降序排列
    select * from employee order by age asc ,salary esc;
    
    
1. 查詢全部員工信息,先按照age升序排序,若是age相同則按照hire_date降序排序
select * from employee order by age ASC,hire_date DESC;
2. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資升序排列
select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) asc;
3. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資降序排列
select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) desc;

7.限制查詢的記錄數 limit

取出工資最高的前三位
    SELECT * FROM employee ORDER BY salary DESC 
        LIMIT 3;    默認初始位置爲0,從第一條開始順序取出三條 

    SELECT * FROM employee ORDER BY salary DESC
        LIMIT 0,5;  從第0開始,即先查詢出第一條,而後包含這一條在內日後查5條 

    SELECT * FROM employee ORDER BY salary DESC
        LIMIT 5,5;  從第5開始,即先查詢出第6條,而後包含這一條在內日後查5條

==到目前爲止,單表查詢全部的語法都講完了,語法就是按照咱們博客最上面說的語法順序來寫,可是執行的時候,要按照對應的各個方法的優先級去執行。==

8.補充:級聯set null的用法和示例

mysql> create table tt2(id int primary key auto_increment,name char(10));

mysql> create table tt3(id int,pid int,foreign key(pid) references tt2(id) on delete set null);
Query OK, 0 rows affected (1.06 sec)

mysql> desc tt3;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
| pid   | int(11) | YES  | MUL | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> insert into tt2(name) values('xx1'),('xx2');
Query OK, 2 rows affected (0.14 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into tt3 values(1,1),(2,1);
Query OK, 2 rows affected (0.12 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from tt3;
+------+------+
| id   | pid  |
+------+------+
|    1 |    1 |
|    2 |    1 |
+------+------+
2 rows in set (0.00 sec)

mysql> delete from tt2 where id = 1;
Query OK, 1 row affected (0.10 sec)

mysql> select * from tt3;
+------+------+
| id   | pid  |
+------+------+
|    1 | NULL |
|    2 | NULL |
+------+------+
2 rows in set (0.00 sec)

9.使用正則表達式

以前咱們用like作模糊匹配,只有%和_,侷限性比較強,因此咱們說一個正則,以前咱們是否是學過正則匹配,你以前學的正則表達式均可以用,正則是通用的
SELECT * FROM employee WHERE name REGEXP '^ale';
SELECT * FROM employee WHERE name REGEXP 'on$';
SELECT * FROM employee WHERE name REGEXP 'm{2}';

小結:對字符串匹配的方式
WHERE name = 'egon';
WHERE name LIKE 'yua%';
WHERE name REGEXP 'on$';
查看全部員工中名字是jin開頭,n或者g結果的員工信息
select * from employee where name regexp '^jin.*[g|n]$';

10.聚合函數

強調:聚合函數聚合的是組的內容,如果沒有分組,則默認一組
SELECT COUNT(*) FROM employee;    count是統計個數
SELECT COUNT(*) FROM employee WHERE depart_id=1;    後面跟where條件的意思是統計一下知足depart_id=1這個的全部記錄的個數
SELECT MAX(salary) FROM employee;    max()統計分組後每組的最大值,這裏沒有寫group by,那麼就是統計整個表中全部記錄中薪資最大的,薪資的值
SELECT MIN(salary) FROM employee;
SELECT AVG(salary) FROM employee;
SELECT SUM(salary) FROM employee;
SELECT SUM(salary) FROM employee WHERE depart_id=3;

11.帶IN關鍵字的子查詢

#查詢員工平均年齡在25歲以上的部門名,能夠用連表,也能夠用子查詢,咱們用子查詢來搞一下
select id,name from department
    where id in 
        (select dep_id from employee group by dep_id having avg(age) > 25);
#連表來搞一下上面這個需求
select department.name from department inner join employee on department.id=employee.dep_id 
    group by department.name 
    having avg(age)>25;

總結:子查詢的思路和解決問題同樣,先解決一個而後拿着這個的結果再去解決另一個問題,連表的思路是先將兩個表關聯在一塊兒,而後在進行group by啊過濾啊等等操做,二者的思路是不同的
#查看技術部員工姓名
select name from employee
    where dep_id in 
        (select id from department where name='技術');

#查看不足1人的部門名(子查詢獲得的是有人的部門id)
select name from department where id not in (select distinct dep_id from employee);

12.帶比較運算符的子查詢

待定代碼有問題,沒有表,沒法驗證

#比較運算符:=、!=、>、>=、<、<=、<>
#查詢大於全部人平均年齡的員工名與年齡
mysql> select name,age from emp where age > (select avg(age) from emp);


#查詢大於部門內平均年齡的員工名、年齡
select t1.name,t1.age from emp t1
inner join 
(select dep_id,avg(age) avg_age from emp group by dep_id) t2
on t1.dep_id = t2.dep_id
where t1.age > t2.avg_age;

13.帶EXISTS關鍵字的子查詢

EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。而是返回一個真假值。True或False
    當返回True時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行查詢。還能夠寫not exists,和exists的效果就是反的
select * from employee
where exists  
(select id from department where id=200);
department表中存在dept_id=203,Ture
不存在的時候是錯 返回  Empty set (0.00 sec)

14.GROUP BY

單獨使用GROUP BY關鍵字分組
    SELECT post FROM employee GROUP BY post;
    注意:咱們按照post字段分組,那麼select查詢的字段只能是post,想要獲取組內的其餘相關信息,須要藉助函數
    
    
GROUP BY關鍵字和GROUP_CONCAT()函數一塊兒使用,好比說我想按部門分組,每一個組有哪些員工,都顯示出來
    SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;    按照崗位分組,並查看組內全部成員名,經過逗號拼接在一塊兒
    SELECT post,GROUP_CONCAT(name,':',salary) as emp_members FROM employee GROUP BY post;按照崗位分組,並查看組內全部成員名,經過逗號拼接在一塊兒
    
    
GROUP BY通常都會與聚合函數一塊兒使用,聚合是什麼意思:聚合就是將分組的數據彙集到一塊兒,合併起來搞事情,拿到一個最後的結果
select post,count(id) as count from employee group by post;    按照崗位分組,並查看每一個組有多少人,每一個人都有惟一的id號,我count是計算一下分組以後每組有多少的id記錄,經過這個id記錄我就知道每一個組有多少人了


關於集合函數,mysql提供瞭如下幾種聚合函數:count、max、min、avg、sum等,上面的group_concat也算是一個聚合函數了,作字符串拼接的操做

15.ONLY_FULL_GROUP_BY (設置)

16.練習

1. 查詢崗位名以及崗位包含的全部員工名字
'''
a、先看一下和哪一個表有關係:全部的信息都在employee這個表裏面,因此先寫from employee,找到表了

b、看有沒有什麼過濾條件,大於小於啊什麼的,沒有吧,因此是否是不須要寫where條件啊

c、看看有沒有分組的內容,也就是看看上面的需求裏面有沒有分類的概念,發現是否是有啊,按照崗位來分組,對不對,因此該寫什麼了:from employee group by post;

d、而後再看須要查什麼字段出來,發現是否是要看崗位名和全部員工的名字啊,因此怎麼寫:select post,group_concat(name) from employee group by post;這就是完整語句了,不信你試試
'''
下面的題都按照上面這個邏輯來搞一搞:
2. 查詢崗位名以及各崗位內包含的員工個數
3. 查詢公司內男員工和女員工的個數
4. 查詢崗位名以及各崗位的平均薪資
5. 查詢崗位名以及各崗位的最高薪資
6. 查詢崗位名以及各崗位的最低薪資
7. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資。
8.統計各部門年齡在30歲及以上的員工平均薪資
想一下怎麼寫,一、from 表  二、where age>=30獲得一張虛擬表 三、對虛擬表按部門group by  四、select 部門和聚合函數avg
答案:select post,avg(salary) from employee where age>=30 group by post;
看結果:

    mysql> select post,avg(salary) from employee where age>=30 group by post;    由於有的部門裏面的員工沒有大於30歲的,因此沒有顯示出全部的部門
    +---------+---------------+
    | post | avg(salary) |
    +---------+---------------+
    | sale | 2500.240000 |
    | teacher | 255450.077500 |
    +---------+---------------+
    2 rows in set (0.09 sec)


到這裏咱們的group by就講完了,看一下咱們完整查詢語句裏面還有什麼

SELECT distinct 字段1,字段2... FROM 庫名.表名 
                  WHERE 條件       
                  GROUP BY field(字段)   
                  HAVING 篩選      #過濾,過濾以後執行select後面的字段篩選,就是說我要肯定一下須要哪一個字段的數據,你查詢的字段數據進行去重,而後在進行下面的操做
                  ORDER BY field(字段)   #將結果按照後面的字段進行排序
                  LIMIT 限制條數 

注意:雖然語法裏面咱們先寫的select,可是並非先執行的select,按照mysql本身的規範來執行的下面關鍵字的優先級
  from
  where
  group by
  having
  select
  distinct
  order by
  limit

5.多表查詢

介紹 建表

#部門表
create table department(
id int,
name varchar(20) 
);

#員工表,以前咱們學過foreign key,強行加上約束關聯,可是我下面這個表並無直接加foreign key,這兩個表我只是讓它們在邏輯意義上有關係,並無加foreign key來強制兩表創建關係,爲何要這樣搞,是有些效果要給你們演示一下
#因此,這兩個表是否是先創建哪一個表都行啊,若是有foreign key的話,是否是就須要注意表創建的順序了。那咱們來建表。
create table employee(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

#給兩個表插入一些數據
insert into department values
(200,'技術'),
(201,'人力資源'),
(202,'銷售'),
(203,'運營'); #注意這一條數據,在下面的員工表裏面沒有對應這個部門的數據

insert into employee(name,sex,age,dep_id) values
('egon','male',18,200),
('alex','female',48,201),
('wupeiqi','male',38,201),
('yuanhao','female',28,202),
('liwenzhou','male',18,200),
('jingliyang','female',18,204) #注意這條數據的dep_id字段的值,這個204,在上面的部門表裏面也沒有對應的部門id。因此二者都含有一條雙方沒有涉及到的數據,這都是爲了演示一下效果設計的昂
;


#查看錶結構和數據
mysql> desc department;

#查看
mysql> desc employee;
mysql> select * from department;
mysql> select * from employee1;

1.多表連表查詢

重點:外連接語法

SELECT 字段列表
    FROM 表1 INNER|LEFT|RIGHT JOIN 表2
    ON 表1.字段 = 表2.字段;

1.交叉鏈接:不適用任何匹配條件。生成笛卡爾積

查詢順序不同 一個在前一個在後
沒有給條件因此所有顯示 這就是笛卡爾積
mysql> select * from department,employee;
mysql> select * from employee,department;

2.內鏈接:只鏈接匹配的行

mysql> select * from employee,department where employee.dep_id=department.id; #拿出id對應的數據,後面加判斷
select employee.name from employee,department where employee.dep_id=department.id and department.name='技術';#有兩個表的時候前面顯示的name必須指定表,不然會報錯

3.外連接之左鏈接:優先顯示左表所有記錄

left join 左邊語法
select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;#以左表爲準,即找出全部員工信息,固然包括沒有部門的員工 本質就是:在內鏈接的基礎上增長左邊有右邊沒有的結果

4.外連接之右鏈接:優先顯示右表所有記錄

right join 右邊語法
select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;#以右表爲準,即找出全部部門信息,包括沒有員工的部門 本質就是:在內鏈接的基礎上增長右邊有左邊沒有的結果

5.全外鏈接:顯示左右兩個表所有記錄

select * from employee left join department on employee.dep_id = department.id
union
select * from employee right join department on employee.dep_id = department.id
;
#注意:mysql不支持全外鏈接 full JOIN 強調:mysql可使用此種方式間接實現全外鏈接
#注意 union與union all的區別:union會去掉相同的紀錄,由於union all是left join 和right join合併,因此有重複的記錄,經過union就將重複的記錄去重了。

6.符合條件鏈接查詢

select employee.name,department.name 
from employee inner join department on 
employee,dep_id=department.id where age>25;
#之內鏈接的方式查詢employee和department表,而且employee表中的age字段值必須大於25,即找出年齡大於25歲的員工以及員工所在的部門
select employee.id,employee.name,employee.age,department.name 
from employee,department
where employee.dep_id = department.idand age > 25
order by age asc;
#之內鏈接的方式查詢employee和department表,而且以age字段的升序方式顯示

7.子查詢

select * from employee inner join department on employee.dep_id = department.id; #查看那些部門有哪些員工,先連表 在查詢
select employee.name from employee inner join department on employee.dep_id = department.id where department.name='技術';#查看某個部門的員工名單,而後根據連表的結果進行where過濾,將select*改成select employee.name
select name from employee where dep_id = (select id from department where name='技術');#那咱們把上面的查詢結果用括號括起來,它就表示一條id=200的數據,而後咱們經過員工表來查詢dep_id=這條數據做爲條件來查詢員工的name

這些就是子查詢的一個思路,解決一個問題,再解決另一個問題,你子查詢裏面可不能夠是多個表的查詢結果,固然能夠,而後再經過這個結果做爲依據來進行過濾,而後咱們學一會兒查詢裏面其餘的內容,
子查詢:
1:子查詢是將一個查詢語句嵌套在另外一個查詢語句中。
2:內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。
3:子查詢中能夠包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字
4:還能夠包含比較運算符:= 、 !=、> 、<等

6.Navicat工具

圖形化操做數據庫表
掌握:
1. 測試+連接數據庫
2. 新建庫
3. 新建表,新增字段+類型+約束
4. 設計表:外鍵
5. 新建查詢
6. 備份庫/表

注意:
批量加註釋:ctrl+?鍵
批量去註釋:ctrl+shift+?鍵

7.pymysql模快和SQL注入問題

先安裝pymysql第三方模塊,導入模塊.

import pymysql
conn = pymysql.connect(
    host='127.0.0.1', #主機
    port=3306, #端口號
    user='root',#用戶名
    password='666', #密碼
    database='day43', #須要鏈接的庫
    charset='utf8'
)

cursor = conn.cursor()

sql = "select * from dep;"

ret = cursor.execute(sql) #ret 受影響的行數
print(cursor.fetchall())  #取出全部的
print(cursor.fetchmany(3))  #取出多條
print(cursor.fetchone())  #取出單條

cursor.scroll(3,'absolute')  #絕對移動,按照數據最開始位置往下移動3條
cursor.scroll(3,'relative')  #相對移動,按照當前光標位置往下移動3條

conn.commit()  #增刪改操做時,須要進行提交


sql注入:解決方案
    cursor.execute(sql,[參數1,參數2...])

不知道密碼或者用戶名就能夠登錄的操做
防止沒有密碼登錄操做(瞭解)

8.彙集索引和普通索特性介紹

彙集索引(主鍵)  id int primary key
普通索引 Index index_name(id)
惟一索引 int unique

主鍵:
表建立完了以後添加: Alter table 表名 add primary key(id)
     刪除主鍵索引: Alter table 表名 drop primary key;

惟一索引: 
表建立好以後添加惟一索引: alter table s1 add unique key  u_name(id);
                  刪除: alter table s1 drop unique key u_name;

普通索引:
建立:
Create table t1(
    Id int,
    Index index_name(id)
)
Alter table s1 add index index_name(id);
Create index index_name on s1(id);
刪除:
Alter table s1 drop index u_name;
DROP INDEX 索引名 ON 表名字;

聯合索引(聯合主鍵\聯合惟一\聯合普通索引)
    Create table t1(
            Id int,
            name char(10),
            Index index_name(id,name)
        )
b+樹:提升查詢效率

彙集索引
    組織存儲整表全部數據的依據
    id primary key
    葉子節點存的是真是數據,存的是整行記錄
    
輔助索引(普通索引)
    普通索引創建樹形結構,提升查詢效率,可是葉子節點存的是該列的數據和對應行的主鍵值
    index name_index(name)
    unique name_index(name)
    select name from 表名 where name='xx';
    葉子節點找到了對應數據,稱爲覆蓋索引
    找不到列數據,須要回表操做(拿着主鍵從新走一遍主鍵的樹形結構找到對應行的那一列數據)
索引分類
    主鍵索引  惟一索引 普通索引
    聯合主鍵索引  聯合惟一索引  聯合普通索引
    
聯合索引的最左匹配特性
多條件查詢時
    where name='xx' and age='xx' and sex='xx'
    index name_index(name,age,sex)
    where age='xx' and sex='xx'

9.備份還原,事務,鎖

mysqldump
    備份:mysqldump -uroot -p -B -d 庫名>路徑(g:\av\av.sql)
    還原:mysql -uroot -p < 路徑(g:\av\av.sql)
鎖和事務
innodb存儲引擎默認是行級鎖
myISAM 表鎖

 select * from xx where xx=xx for update; 排它鎖

事務
    原子性 一致性 隔離性 持久性
    
begin; 或者 start transaction;

commit;  提交

rollback; 回滾
事務介紹:
        簡單地說,事務就是指邏輯上的一組SQL語句操做,組成這組操做的各個SQL語句,執行時要麼全成功要麼全失敗。
        例如:你給我轉帳5塊錢,流程以下
            a.從你銀行卡取出5塊錢,剩餘計算money-5
            b.把上面5塊錢打入個人帳戶上,我收到5塊,剩餘計算money+5.
        上述轉帳的過程,對應的sql語句爲:
                update 你_account set money=money-5 where name='你';
                update 我_account set money=money+5 where name='我';
        上述的兩條SQL操做,在事務中的操做就是要麼都執行,要麼都不執行,否則錢就對不上了。
        這就是事務的原子性(Atomicity)。
    事務的四大特性:
        1.原子性(Atomicity)
            事務是一個不可分割的單位,事務中的全部SQL等操做要麼都發生,要麼都不發生。
        2.一致性(Consistency)
            事務發生前和發生後,數據的完整性必須保持一致。
        3.隔離性(Isolation)
            當併發訪問數據庫時,一個正在執行的事務在執行完畢前,對於其餘的會話是不可見的,多個併發事務之間的數據是相互隔離的。也就是其餘人的操做在這個事務的執行過程當中是看不到這個事務的執行結果的,也就是他們拿到的是這個事務執行以前的內容,等這個事務執行完才能拿到新的數據。
        4.持久性(Durability)
            一個事務一旦被提交,它對數據庫中的數據改變就是永久性的。若是出了錯誤,事務也不允撤銷,只能經過'補償性事務'。
        
    事務的開啓:
        數據庫默認事務是自動提交的,也就是發一條sql他就執行一條。若是想多條sql放在一個事務中執行,則須要使用事務進行處理。當咱們開啓一個事務,而且沒有提交,mysql會自動回滾事務。或者咱們使用rollback命令手動回滾事務。
相關文章
相關標籤/搜索