MySQL
是一個開卸載html
在裏面找MySQL 環境變量 找到以後先中止 在cmd裏面python
自帶客戶端MySQL.exe 第三方Navicat好用 可是先不用mysql
中止服務 刪除服務 把安裝軟件也刪除(文件夾) 刪除環境變量(先找到)nginx
最後重啓 是清除註冊表(百度刪除方法)web
net stop mysql 中止mysql服務 mysqld remove 刪除服務 把安裝軟件也刪掉 刪除環境變量 清除註冊表/重啓計算機
安裝正則表達式
建立用戶和受權redis
數據的存儲方式 -- 存儲引擎engines 使用不一樣的存儲引擎,數據是以不一樣的方式存儲的sql
建立表設置儲存引擎:數據庫
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;
show engines; 查看存儲引擎安全
innodb 2個文件 ==事務==
myisam 3個文件
經常使用存儲引擎及使用場景
流程關係
介紹
存儲引擎決定了表的類型,而表內存放的數據也要有不一樣的類型,每種數據類型都有本身的寬度,但寬度是可選的詳細參考
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. 枚舉類型與集合類型
數值類型
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 );
日期類型
內置函數 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 # 不能爲空,默認值是當前時間,在修改的時候同時更新時間 )
字符串類型
char 0-255 定長存儲 存儲速度更快 佔用更多的空間 ***** char(12) alex --> 'alex ' --> 12的長度 varchar 0-65535 變長存儲 存儲速度慢 佔用的空間小 **** varchar(12) 'alex' --> 'alex4' --> 5的長度 手機號碼/身份證號碼 : char 用戶名/密碼 : 有必定範圍彈性 char 評論 : varchar 時間換空間,空間換時間.沒有能夠有也沒有能夠無
枚舉類型與集合類型
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('抽菸','喝酒','燙頭','搓腳') )
PRIMARY KEY (PK) 標識該字段爲該表的主鍵,能夠惟一的標識記錄 FOREIGN KEY (FK) 標識該字段爲該表的外鍵 NOT NULL 標識該字段不能爲空 UNIQUE KEY (UK) 標識該字段的值是惟一的 AUTO_INCREMENT 標識該字段的值自動增加(整數類型,並且爲主鍵) DEFAULT 爲該字段設置默認值 UNSIGNED 無符號 ZEROFILL 使用0填充
==unsigned 無符號的:數字==
not null與default
not null 非空 null 可空
default 默認值
默認值,建立列時能夠指定默認值,當插入數據時若是未主動設置,則自動添加默認值 create table tb1( nid int not null defalut 2, num int not null );
unique 惟一
普通惟一
獨一無二,惟一屬性:id,身份證號等
是一種key,惟一鍵,是在數據類型以外的附加屬性,有加速查詢的做用
create table department2( id int, name varchar(20), comment varchar(100), constraint uk_name unique(name) );
聯合惟一
create table service( id int primary key auto_increment, name varchar(20), host varchar(15) not null, port int not null, unique(host,port) #聯合惟一 );
primary key
從約束角度看primary key字段的值不爲空且惟一,那咱們直接使用not null+unique不就能夠了嗎,要它幹什麼?主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之爲索引組織表,一張表中必須有且只有一個主鍵。
一個表中能夠:單列作主鍵 多列作主鍵(複合主鍵或者叫作聯合主鍵)
關於主鍵的通俗解釋和強調內容(重點************************)
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這個東西在建表的時候直接就寫上
在沒有設置主鍵的時候,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)
單列主鍵測試
============單列作主鍵=============== #方法一: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)
聯合主鍵解釋
聯合主鍵 和聯合惟一是相似的, 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來指定
多列(聯合)主鍵測試
==================多列作主鍵================ 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'
auto_increment 自動增長
只能操做數字 自帶非空屬性 只能對unique字段進行設置 不受刪除影響 內部有記錄
默認起始位置爲1,步長也爲1.
不指定id,則自動增加 create table student( id int primary key auto_increment, 設置自動增長 name varchar(20), sex enum('male','female') default 'male' );
sex enum('male','female') default 'male' 建立表時指定auto_increment的初始值,注意初始值的設置爲表選項,應該放到括號外
insert into student values(4,'asb','female'); 設置ID 對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增加
insert into student(name) values('egon'); truncate student; 應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它(從0開始)
alter table student auto_increment=3; 在建立完表後,修改自增字段的起始值
show create table student;
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8(顯示默認值)
設置自增:
set session auth_increment_increment=2 #修改會話級別的步長
set global auth_increment_increment=2 #修改全局級別的步長(全部會話都生效)
foreign key 外鍵約束
快速理解foreign key(外鍵其實就是標明表和表之間的關係,表和表之間若是有關係的話就三種:一對一,多對一,多對多)
on delete cascade 級聯刪除 on update cascade 級聯更新
分析步驟:
先站在左表的角度去找
是否左表的多條記錄能夠對應右表的一條記錄,若是是,則證實左表的一個字段foreign key 右表一個字段(一般是id)
再站在右表的角度去找
是否右表的多條記錄能夠對應左表的一條記錄,若是是,則證實右表的一個字段foreign key 左表一個字段(一般是id)
總結
=====================多對一===================== 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) ;
外鍵約束有三種約束模式(都是針對父表的約束):
場景: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);
建立表時: 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);
級聯有幾個模式
嚴格模式(默認的),外鍵有強制約束效果,被關聯字段不能隨意刪除和修改
模式(cascade):外鍵有強制約束效果,被關聯字段刪除或者修改,關聯他的那麼字段數據會隨之刪除或者修改
constraint fk_t1_publish foreign key(pid) references publish(id) on delete cascade on update cascade;
set null模式: 被關聯字段刪除時,關聯他的字段數據會置成null
select 某一個東西 能夠查一個,多個,*全部 調用函數 : now() user() database() concat() concat_ws() 進行四則運算 能夠去重 distinct 能夠進行條件判斷 case when語句
查詢數據的本質:mysql會到你本地的硬盤上找到對應的文件,而後打開文件,按照你的查詢條件來找出你須要的數據。下面是完整的一個單表查詢的語法 select * from,這個select * 指的是要查詢全部字段的數據。 SELECT distinct 字段1,字段2... FROM 庫名.表名 from後面是說從庫的某個表中去找數據,mysql會去找到這個庫對應的文件夾下去找到你表名對應的那個數據文件,找不到就直接報錯了,找到了就繼續後面的操做 WHERE 條件 從表中找符合條件的數據記錄,where後面跟的是你的查詢條件 GROUP BY field(字段) 分組 HAVING 篩選 過濾,過濾以後執行select後面的字段篩選,就是說我要肯定一下須要哪一個字段的數據,你查詢的字段數據進行去重,而後在進行下面的操做 ORDER BY field(字段) 將結果按照後面的字段進行排序 LIMIT 限制條數 將最後的結果加一個限制條數,就是說我要過濾或者說限制查詢出來的數據記錄的條數
from > where > group by > having > select > distinct > order by > limit
避免重複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()
以前咱們用where 後面跟的語句是否是id=1這種類型的啊,用=號鏈接的,除了=號外,還能使用其餘的,看下面:
比較運算符:> < >= <= <> !=
between 80 and 100 值在80到100之間
and是都知足 or只要知足一個
in(80,90,100) 值是80或90或100
like 'egon%'
pattern能夠是%或_,
%表示任意多字符
_表示一個字符
邏輯運算符:在多個條件直接可使用邏輯運算符 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條件的一個工做方式。
示例: # 統計每一個崗位的名稱以及最高工資 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後面的分組依據字段和聚合函數統計結果
什麼是分組?爲何要分組?
首先明確一點:分組發生在where以後,即分組是基於where以後獲得的記錄而進行的
分組指的是:將全部記錄按照某個相同字段進行歸類,好比針對員工信息表的職位分組,或者按照性別進行分組等
爲什麼要分組呢?是由於咱們有時候會須要以組爲單位來統計一些數據或者進行一些計算的,對不對,比方說下面的幾個例子
取每一個部門的最高工資
取每一個部門的員工數
取男人數和女人數
小竅門:‘每’這個字後面的字段,就是咱們分組的依據,只是個小竅門,可是不能表示全部的狀況,看上面第三個分組,沒有'每'字,這個就須要咱們經過語句來自行判斷分組依據
咱們能用id進行分組嗎,能,可是id是否是重複度很低啊,基本沒有重複啊,對不對,這樣的字段適合作分組的依據嗎?不適合,對不對,依據性別分組行不行,固然行,由於性別咱們知道,是否是就兩種啊,也可能有三種是吧,這個重複度很高,對不對,分組來查的時候纔有更好的意義
大前提:
能夠按照任意字段分組,可是分組完畢後,好比group by post,只能查看post字段,若是想查看組內信息,須要藉助於聚合函數. 注意一點,在查詢語句裏面select 字段 from 表,這幾項是必需要有的,其餘的什麼where、group by等等都是無關緊要的
select * from employee group by post; group by 語句 按照post分組
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
示例: select distinct post from employee; 注意問題:select的字段必須寫在distinct的後面,而且若是寫了多個字段,好比: select distinct post,id from employee;這句話,意思就是post和id兩個組合在一塊兒同時重複的纔算是重複數據
按單列排序 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;
取出工資最高的前三位 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條
==到目前爲止,單表查詢全部的語法都講完了,語法就是按照咱們博客最上面說的語法順序來寫,可是執行的時候,要按照對應的各個方法的優先級去執行。==
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)
以前咱們用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]$';
強調:聚合函數聚合的是組的內容,如果沒有分組,則默認一組 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;
#查詢員工平均年齡在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);
待定代碼有問題,沒有表,沒法驗證 #比較運算符:=、!=、>、>=、<、<=、<> #查詢大於全部人平均年齡的員工名與年齡 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;
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)
單獨使用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也算是一個聚合函數了,作字符串拼接的操做
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
#部門表 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;
重點:外連接語法 SELECT 字段列表 FROM 表1 INNER|LEFT|RIGHT JOIN 表2 ON 表1.字段 = 表2.字段;
查詢順序不同 一個在前一個在後 沒有給條件因此所有顯示 這就是笛卡爾積 mysql> select * from department,employee; mysql> select * from employee,department;
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必須指定表,不然會報錯
left join 左邊語法 select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;#以左表爲準,即找出全部員工信息,固然包括沒有部門的員工 本質就是:在內鏈接的基礎上增長左邊有右邊沒有的結果
right join 右邊語法 select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;#以右表爲準,即找出全部部門信息,包括沒有員工的部門 本質就是:在內鏈接的基礎上增長右邊有左邊沒有的結果
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就將重複的記錄去重了。
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字段的升序方式顯示
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:還能夠包含比較運算符:= 、 !=、> 、<等
圖形化操做數據庫表 掌握: 1. 測試+連接數據庫 2. 新建庫 3. 新建表,新增字段+類型+約束 4. 設計表:外鍵 5. 新建查詢 6. 備份庫/表 注意: 批量加註釋:ctrl+?鍵 批量去註釋:ctrl+shift+?鍵
先安裝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...]) 不知道密碼或者用戶名就能夠登錄的操做 防止沒有密碼登錄操做(瞭解)
彙集索引(主鍵) 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'
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命令手動回滾事務。