1.mysql的簡介mysql
2.增刪改查操做linux
3.單表查詢正則表達式
4.多表查詢常見的三種方式sql
5.pymysql模塊操做數據庫數據庫
概述:mysql是一個關係型數據庫,關係型數據庫模型是把複雜的數據結構歸結爲簡單的二元關係(即二維表格形式,不是excel,可是和excel的形式很像)windows
mysql安裝目錄說明:性能優化
配置文件裏面主要分三段:服務器
[mysqld] 配置mysql服務端相關的信息數據結構
[mysql] 配置mysql客戶端相關的信息ide
[client] 配置其餘客戶端相關的信息
安裝數據庫後會有四個自帶的數據庫:
information_schema數據庫是MySQL自帶的,它提供了訪問數據庫元數據的方式。什麼是元數據呢?元數據是關於數據的數據,如數據庫名或表名,
列的數據 類型,或訪問權限等。有些時候用於表述該信息的其餘術語包括「數據詞典」和「系統目錄」。
mysql:這個是mysql的核心數據庫,相似於sql server中的master表,主要負責存儲數據庫的用戶、權限設置、關鍵字等mysql本身須要使用的控制和管理
信息。不能夠刪除,若是對mysql不是很瞭解,也不要輕易修改這個數據庫裏面的表信息。
performance_schema mysql 5.5 版本 新增了一個性能優化的引擎: PERFORMANCE_SCHEMA這個功能默認是關閉的: 須要設置參數: performance_schema 才能夠啓動該功能,這個參數是靜態參數,只能寫在my.ini 中 不能動態修改。
這裏的數據表分爲幾類:
1) setup table : 設置表,配置監控選項。
2) current events table : 記錄當前那些thread 正在發生什麼事情。
3) history table 發生的各類事件的歷史記錄表
4) summary table 對各類事件的統計表
5) 雜項表,亂七八糟表
test: 安裝mysql自帶的測試表,默認爲空,沒什麼用。
給mysql root用戶設置密碼的三種方式
方法1: 用SET PASSWORD命令
首先登陸MySQL,使用mysql自帶的那個客戶端鏈接上mysql。
格式:mysql> set password for 用戶名@localhost = password('新密碼');
例子:mysql> set password for root@localhost = password('123');
方法2:用mysqladmin
格式:mysqladmin -u用戶名 -p舊密碼 password 新密碼
例子:mysqladmin -uroot -p123456 password 123
方法3:用UPDATE直接編輯那個自動的mysql庫中的user表
use mysql
mysql> update user set password=password('123') where user='root' and host='localhost';
mysql> flush privileges; 刷新權限,讓其生效,不然不生效,修改不成功。
忘記root的解決方案以windows爲例:
先關閉mysql服務:
方法一:net start/stop MySQL ps:須要以管理員的身份運行cmd才行
方法二:tasklist | findstr mysql
taskkill /F /PID id
切換的安裝mysql的bin下
G: ps:windows下切換到盤符不用寫cd,直接寫盤符便可
cd MySQL/bin
--skip-grant-table 跳過權限表
update user set password=password("new password") where user="root"
flush privileges
最後重啓服務便可
修改字符集:
\s 查看mysql初始信息
show create database dbname; 查看建立庫的信息
show variables like "%char%"; 查看各個角色的編碼
解決亂碼:注意一下其中的character_set_client、character_set_connection、character_set_results這三項就是由於這三和服務端的編碼不一致致使的,因此咱們須要將這三項改成和服務端一致的字符集就能夠了。
在windows下查看sqlite的utf-8中文須要先執行chcp 65001把當前頁換爲utf-8編碼
chcp 命令:
chcp 65001 就是換成UTF-8代碼頁,在命令行標題欄上點擊右鍵,選擇"屬性"->"字體",將字體修改成True Type字體"Lucida Console",而後點擊肯定將屬性應用到當前窗口
chcp 936 能夠換回默認的GBK
chcp 437 是美國英語
linux系統查看系統默認編碼的指令:
執行指令:cat sysconfig i18n
結果中有一條是:LANG="zh_CN.utf8"
關於引擎知識: mysql默認引擎是Innodb,不一樣的引擎在目錄下會生成不一樣的文件,不一樣的引擎會生成不一樣的文件,Innodb支持事務操做
1.後綴名爲.frm的文件:這個文件主要是用來描述數據表結構(id,name字段等)和字段長度等信息 2.後綴名爲.ibd的文件:這個文件主要儲存的是採用獨立表儲存模式時儲存數據庫的數據信息和索引信息; 3.後綴名爲.MYD(MYData)的文件:從名字能夠看出,這個是存儲數據庫數據信息的文件,主要是存儲採用獨立表儲存模式時存儲的數據信息; 4.後綴名爲.MYI的文件:這個文件主要儲存的是數據庫的索引信息; 5.ibdata1文件:主要做用也是儲存數據信息和索引信息,這個文件在mysql安裝目錄的data文件夾下。 從上面能夠看出,.ibd儲存的是數據信息和索引信息,ibdata1文件也是存儲數據信息和索引信息,.MYD和.MYI也是分別儲存數據信息和索引信息,那他們之間有什麼區別呢? 主要區別是再於數據庫的存儲引擎不同,若是儲存引擎採用的是MyISAM,則生成的數據文件爲表名.frm、表名.MYD、表名的MYI;而儲存引擎若是是innoDB,開啓了innodb_file_per_table=1,也就是採用獨立儲存的模式,生成的文件是表名.frm、表名.ibd,若是採用共存儲模式的,數據信息和索引信息都存儲在ibdata1中; 在進行數據恢復的時候,若是用的是MYISAM數據引擎,那麼數據很好恢復,只要將相應.frm, .MYD, .MYI文件拷貝過去便可。可是若是是innodb的話,則每個數據表都是一個單獨的文件,只將相應的.frm和.ibd文件拷貝過去是不夠的,必須在你的ibd文件的tablespace id和ibdata1文件中的元信息的tablespace id一致才能夠。
開啓事務:start transaction 開啓事務 begin也是開啓事務
事務回滾:rollback
提交:commit
簡單操做:
SQL語句主要是針對數據庫裏面三個角色進行操做,對象是:庫、表、行,操做包括:增刪改查。
一、庫(data文件夾中的文件夾,每建立一個庫,這個庫的名稱就是文件夾的名稱,文件夾裏面保存着一些這個庫相關的初始信息)
增:create database db1 charset utf8; #建立一個庫,能夠指定字符集
查:show databases; #查看數據庫中全部的庫
show create database db1; #查看單獨某個庫db1的信息
改:alter database db1 charset latin1; #修改庫的字符集,注意語句的格式(其餘語句也是這麼個格式),alter(修改) database(修改數據庫) db1 (哪一個數據庫) charset(字符集) latin1(改爲哪一個字符集)
刪除: drop database db1; #刪除數據庫
二、表(操做文件,表是上面庫文件夾裏面的文件)
先切換庫:use db1; #要操做表文件,要先切換到對應的庫下才能操做表
查看當前所在的是哪一個庫:select database();
增:create table t1(id int,name char(10) );
查:show tables; #查看當前庫中全部的表
show create table t1; #查看單表的建立信息
desc t1;查看錶信息,以表格的形式展現結果:
describe t1;#上下這兩句是同樣的結果
改:alter table t1 modify name char(3); #修改字段屬性的,將name字段的char長度改成3
刪:drop table t1;
3. 行(操做文件(表)中的內容/記錄)(*****未來的重中之重)
增:insert into t1 values(1,'dsb1'),(2,'dsb2'),(3,'dsb3'); #往t1表中插入三行數據
查:select * from t1; #查看t1表中全部字段的數據
改:update t1 set name='sb' where id=2;
刪:delete from t1 where id=1; #刪除id爲1的行
清空表:
delete from t1; #若是有自增id,新增的數據,仍然是以刪除前的最後同樣做爲起始。
truncate table t1;數據量大,刪除速度比上一條快,且直接從零開始, 通常用於設置了自增而後想從id 1起始的。
auto_increment 表示:自增
primary key 表示:約束(不能重複且不能爲空);加速查找
建立語法:
一、建立數據庫
CREATE DATABASE 數據庫名 charset utf8;
命令規則:
能夠由字母、數字、下劃線、@、#、$
區分大小寫
惟一性
不能使用關鍵字如 create select
不能單獨使用數字
最長128位
2.建立表語法:
create table 表名( 字段名1 類型[(寬度) 約束條件], 字段名2 類型[(寬度) 約束條件], 字段名3 類型[(寬度) 約束條件] );
1. 在同一張表中,字段名是不能相同 2. 寬度和約束條件可選、非必須,寬度指的就是字段長度約束,例如:char(10)裏面的10 3. 字段名和類型是必須的
經常使用的數據類型:
1. 數字: 整型:tinyinit int bigint
適用範圍:存儲年齡,等級,id,各類號碼等
tinyint[(m)] [unsigned] [zerofill] ps:unsigned 表明無符號不設置unsigned默認有符號 zerofill 0填充
小數: float :在位數比較短的狀況下不精準 double :在位數比較長的狀況下不精準
decimal:(若是用小數,則用推薦使用decimal)
精準,內部原理是以字符串形式去存
2. 字符串:
char(10):簡單粗暴,浪費空間,存取速度快,以三個字節來存儲數據,小於三的,自動補零
varchar:精準,節省空間,存取速度慢
sql優化:建立表時,定長的類型往前放,變長的日後放好比性別 好比地址或描述信息 >255個字符,超了就把文件路徑存放到數據庫中。 好比圖片,視頻等找一個文件服務器,數據庫中只存路徑或url。
3.時間:
data: 年月日
time: 時分秒
datetime 年月日加時分秒
4.枚舉和集合:
enum:多選一
set:複選
擴展:MySQL的mode設置,用於限制一些無效的輸入
設置的三種方法: 方法3須要重啓服務才能生效
1.臨時:set sql_mode='strict_trans_tables'
2.數據庫重啓失效:set global sql_mode='strict_trans_tables'
3.永久設置:my.cnf文件(windows系統是my.ini文件),新增 sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
查看當前mode模式:
select @@global.sql_mode
select @@sql_mode
表的完整性約束
約束條件與數據類型的寬度同樣,都是可選參數,做用:用於保證數據的完整性和一致性
主要分爲如下:
PRIMARY KEY (PK) 標識該字段爲該表的主鍵,能夠惟一的標識記錄 FOREIGN KEY (FK) 標識該字段爲該表的外鍵 NOT NULL 標識該字段不能爲空 UNIQUE KEY (UK) 標識該字段的值是惟一的 AUTO_INCREMENT 標識該字段的值自動增加(整數類型,並且爲主鍵) DEFAULT 爲該字段設置默認值 UNSIGNED 無符號 ZEROFILL 使用0填充
設置unique的兩種方法:
方法一: create table department1( id int, name varchar(20) unique, comment varchar(100) ); 方法二: 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) #聯合惟一 ); ps:若是插入的值host和port都重複纔會報錯
主鍵primary key字段的值不爲空且惟一
主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之爲索引組織表,一張表中必須有且只有一個主鍵。
單列作主鍵=============== #方法一:not null+unique
create table department1( id int not null unique, #主鍵 name varchar(20) not null unique, comment varchar(100) );
#方法二:在某一個字段後用primary key create table department2( id int primary key, #主鍵 name varchar(20), comment varchar(100) );
#方法三:在全部字段後單獨定義primary key create table department3( id int, name varchar(20), comment varchar(100), constraint pk_name primary key(id)); #建立主鍵併爲其命名pk_name
==================多列作主鍵================ create table service( ip varchar(15), port char(5), service_name varchar(10) not null, primary key(ip,port) );
自增 auto_increment
默認起始位置爲1,步長也爲1.
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);
對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增加
應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它
truncate student;
在建立完表後,修改自增字段的起始值
alter table student auto_increment=3;
#也能夠建立表時指定auto_increment的初始值,注意初始值的設置爲表選項,應該放到括號外 create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' )auto_increment=3;
外鍵:foreign key
一 快速理解foreign key(外鍵其實就是標明表和表之間的關係,表和表之間若是有關係的話就三種:一對一,多對一,多對多
foreign key的下面幾個約束做用:
一、先要創建被關聯的表才能創建關聯表
二、在插入數據記錄的時候,要先想被關聯表中插入數據,才能往關聯表裏面插入數據
三、更新或者刪除數據的時候,都須要考慮關聯表和被關聯表的關係
解決方案:
a.刪除表的時候,先刪除關聯表,再刪除被關聯表
b.重建表的時候,在加外鍵關聯的時候加上這兩句:on delete cascade 和 on update cascade
建立:
表類型必須是innodb存儲引擎,且被關聯的字段,即references指定的另一個表的字段,必須保證惟一 create table department( id int primary key, name varchar(20) not null )engine=innodb; #dpt_id外鍵,關聯父表(department主鍵id),同步更新,同步刪除 create table employee( id int primary key, name varchar(20) not null, dpt_id int, constraint fk_name foreign key(dpt_id) #這句話的意思是constraint 是聲明咱們要創建一個約束啦,fk_name是約束的名稱。 on delete cascade on update cascade )engine=innodb;
總結: #多對一: 若是隻有步驟1成立,則是左表多對一右表 若是隻有步驟2成立,則是右表多對一左表 #多對多 若是步驟1和2同時成立,則證實這兩張表時一個雙向的多對一,即多對多,須要定義一個這兩張表的關係表來專門存放兩者的關係 #一對一: 若是1和2都不成立,而是左表的一條記錄惟一對應右表的一條記錄,反之亦然。這種狀況很簡單,就是在左表foreign key右表的基礎上,將左表的外鍵字段設置成unique便可
查看全部外鍵的名稱的方法: select REFERENCED_TABLE_SCHEMA,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME,table_name,CONSTRAINT_NAME from
information_schema.key_column_usage;
#包含咱們建立外鍵的時候,mysql幫咱們自動生成的外鍵名稱。
修改表alter table
語法:
1. 修改表名
ALTER TABLE 表名 RENAME 新表名;
2. 增長字段
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…];
增長數據字段的時候指定位置經過first和after控制
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…] FIRST;
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…] AFTER 字段名;
3. 刪除字段
ALTER TABLE 表名 DROP 字段名;
4. 修改字段
ALTER TABLE 表名 MODIFY 字段名 數據類型 [完整性約束條件…]; 改字段類型和約束條件
ALTER TABLE 表名 CHANGE 舊字段名 新字段名 舊數據類型 [完整性約束條件…]; 改字段名
ALTER TABLE 表名 CHANGE 舊字段名 新字段名 新數據類型 [完整性約束條件…]; 除了改了字段名,還改了數據類型、完整性約束等等的內容
5. 增長約束(針對已有的主鍵增長auto_increment) mysql> alter table student10 modify id int(11) not null primary key auto_increment; ERROR 1068 (42000): Multiple primary key defined mysql> alter table student10 modify id int(11) not null auto_increment; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 6. 對已經存在的表增長複合主鍵 mysql> alter table service2 -> add primary key(host_ip,port); 7. 增長主鍵 mysql> alter table student1 -> modify name varchar(10) not null primary key; 8. 增長主鍵和自動增加 mysql> alter table student1 -> modify id int not null primary key auto_increment; 9. 刪除主鍵 a. 刪除自增約束 mysql> alter table student10 modify id int(11) not null; b. 刪除主鍵 mysql> alter table student10 -> drop primary key;
複製表:
語法:複製表結構+記錄 (key不會複製: 主鍵、外鍵和索引)
mysql> create table new_service select * from service;
只複製表結構,不要數據
mysql> select * from service where 1=2;
行記錄操做
1.插入
插入完整數據(順序插入) 語法一: INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n); #指定字段來插入數據,插入的值要和你前面的字段相匹配
語法二: INSERT INTO 表名 VALUES (值1,值2,值3…值n); #不指定字段的話,就按照默認的幾個字段來插入數據
插入查詢結果 語法: INSERT INTO 表名(字段1,字段2,字段3…字段n) SELECT (字段1,字段2,字段3…字段n) FROM 表2 WHERE …; #將從表2裏面查詢出來的結果來插入到咱們的表中,可是注意查詢出來的數據要和咱們前面指定的字段要對應好
2.更新
語法: UPDATE 表名 SET 字段1=值1, #注意語法,能夠同時來修改多個值,用逗號分隔 字段2=值2, WHERE CONDITION; #更改哪些數據,經過where條件來定位到符合條件的數據
3.刪除
語法: DELETE FROM 表名 WHERE CONITION; #刪除符合條件的一些記錄 DELETE FROM 表名;若是不加where條件,意思是將表裏面全部的內容都刪掉,可是清空全部的內容,通常咱們用truncate ,可以將id置爲零,delete不能將id置零,再插入數據的時候,會按照以前的數據記錄的id數繼續遞增
4.查詢(寫在下一節,由於查詢的知識點多)
5.受權
#受權表 user #該表放行的權限,針對:全部數據,全部庫下全部表,以及表下的全部字段 db #該表放行的權限,針對:某一數據庫,該數據庫下的全部表,以及表下的全部字段 tables_priv #該表放行的權限。針對:某一張表,以及該表下的全部字段 columns_priv #該表放行的權限,針對:某一個字段
#受權:對文件夾,對文件,對文件某一字段的權限 查看幫助:help grant 經常使用權限有:select,update,alter,delete all能夠表明除了grant以外的全部權限
#建立用戶 create user 'egon'@'1.1.1.1' identified by '123'; create user 'egon'@'192.168.1.%' identified by '123'; create user 'egon'@'%' identified by '123';
#針對全部庫的受權:*.* grant select on *.* to 'egon1'@'localhost' identified by '123'; #只在user表中能夠查到egon1用戶的select權限被設置爲Y #針對某一數據庫:db1.* grant select on db1.* to 'egon2'@'%' identified by '123'; #只在db表中能夠查到egon2用戶的select權限被設置爲Y #針對某一個表:db1.t1 grant select on db1.t1 to 'egon3'@'%' identified by '123'; #只在tables_priv表中能夠查到egon3用戶的select權限
select * from tables_priv where user='egon4'\G 查看權限 tables_priv能夠修改爲對應的表
#刪除權限 revoke select on db1.* from 'egon'@'%';
三.單表查詢
語法:
select * from,這個select * 指的是要查詢全部字段的數據。
SELECT distinct 字段1,字段2... FROM 庫名.表名 #from後面是說從庫的某個表中去找數據,mysql會去找到這個庫對應的文件夾下去找到你表名對應的那個數據文件,找不到就直接報錯了,找到了就繼續後面的操做 WHERE 條件 #從表中找符合條件的數據記錄,where後面跟的是你的查詢條件 GROUP BY field(字段) #分組 HAVING 篩選 #過濾,過濾以後執行select後面的字段篩選,就是說我要肯定一下須要哪一個字段的數據,你查詢的字段數據進行去重,而後在進行下面的操做 ORDER BY field(字段) #將結果按照後面的字段進行排序 LIMIT 限制條數 #將最後的結果加一個限制條數,就是說我要過濾或者說限制查詢出來的數據記錄的條數
重點中的重點:關鍵字的執行優先級 from 找到表:from where 拿着where指定的約束條件,去文件/表中取出一條條記錄 group by 將取出的一條條記錄進行分組group by,若是沒有group by,則總體做爲一組 having 將分組的結果進行having過濾 select 執行select distinct 去重 order by 將結果按條件排序:order by limit 限制結果的顯示條數
1.簡單查詢
SELECT * FROM employee; #不推薦用* 慢
SELECT DISTINCT post FROM employee; 去重
SELECT name, salary*12 FROM employee; 四則運算查詢
SELECT name, salary*12 AS Annual_salary FROM employee; #as + 新字段名,就是起一個別名的意思
CONCAT() 函數用於鏈接字符串 SELECT CONCAT('姓名: ',name,' 年薪: ', salary*12) AS Annual_salary 按照本身規定的格式查詢
SELECT CONCAT('姓名: ',name,' 年薪: ', salary*12) AS Annual_salary,CONCAT('性別:',sex) from employee;#還能夠這樣分紅兩列
CONCAT_WS() 第一個參數爲分隔符來進行字符串拼接 SELECT CONCAT_WS(':',name,salary*12) AS Annual_salary #經過冒號來將name和salary鏈接起來
SELECT CONCAT(name,':',salary*12) AS Annual_salary from employee; 能實現跟上面同樣的效果
結合CASE語句:結合條件來對查詢的結果進行一些加工操做 SELECT ( CASE WHEN NAME = 'egon' THEN NAME WHEN NAME = 'alex' THEN CONCAT(name,'_BIGSB') ELSE concat(NAME, 'SB') END ) as new_name,sex FROM employee;
where約束
where語句中可使用:
1. 比較運算符:> < >= <= <> !=
2. between 80 and 100 值在80到100之間
3. in(80,90,100) 值是80或90或100
4. like 'egon%'
pattern能夠是%或_,
%表示任意多字符
_表示一個字符
5. 邏輯運算符:在多個條件直接可使用邏輯運算符 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; #就是salary>=10000 and salary<=20000的數據 SELECT name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000; #加個not,就是不在這個區間內,薪資小於10000的或者薪資大於20000的,注意沒有等於, #4:關鍵字IS NULL(判斷某個字段是否爲NULL不能用等號,須要用IS) 判斷null只能用is SELECT name,post_comment FROM employee WHERE post_comment IS NULL; SELECT name,post_comment FROM employee WHERE post_comment IS NOT NULL; SELECT name,post_comment FROM employee WHERE post_comment=''; 注意''是空字符串,不是null,兩個是不一樣的東西,null是啥也沒有,''是空的字符串的意思,是一種數據類型,null是另一種數據類型 ps: 執行 update employee set post_comment='' where id=2; 再用上條查看,就會有結果了 #5:關鍵字IN集合查詢 SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ; #這樣寫是否是太麻煩了,寫一大堆的or,下面咱們用in這個簡單的寫法來搞 SELECT name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ; SELECT name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ; #6:關鍵字LIKE模糊查詢,模糊匹配,能夠結合通配符來使用 通配符’%’ #匹配任意全部字符 SELECT * FROM employee WHERE name LIKE 'eg%'; 通配符’_’ #匹配任意一個字符 SELECT * FROM employee WHERE name LIKE 'al__'; #注意我這裏寫的兩個_,用1個的話,匹配不到alex,由於al後面還有兩個字符ex。
Goup 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記錄我就知道每一個組有多少人了
聚合函數
#強調:聚合函數聚合的是組的內容,如果沒有分組,則默認一組 示例: 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;
having過濾
HAVING與WHERE不同的地方在於!!!!!!
having的語法格式和where是如出一轍的,只不過having是在分組以後進行的進一步的過濾,where不能使用聚合函數,having是可使用聚合函數的
#!!!執行優先級從高到低:where > group by > having #1. Where 發生在分組group by以前,於是Where中能夠有任意字段,可是絕對不能使用聚合函數。 #2. Having發生在分組group by以後,於是Having中可使用分組的字段,沒法直接取到其餘字段,having是可使用聚合函數
需求:統計各部門年齡在30歲及以上的員工的平均薪資,而且保留平均工資大於10000的部門
答案:select post,avg(salary) as new_sa from employee where age>=30 group by post having avg(salary) > 10000;
having只能在group by後面運行
去重:select distinct post from employee; 注意distinct去重要寫在查詢字段的前面
查詢排序order by
按單列排序 SELECT * FROM employee ORDER BY salary; #默認是升序排列 SELECT * FROM employee ORDER BY salary ASC; #升序 SELECT * FROM employee ORDER BY salary DESC; #降序
按多列排序:先按照age升序,若是年紀相同,則按照薪資降序 SELECT * from employee ORDER BY age, #注意排序的條件用逗號分隔 salary DESC;
限制查詢記錄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條
有時須要查詢出某個字段不重複的記錄,這時可使用mysql提供的distinct這個關鍵字來過濾重複的記錄,可是實際中咱們每每用distinct來返回不重複字段的條數(count(distinct id)),其緣由是distinct只能返回他的目標字段,而沒法返回其餘字段,distinct 想寫在其餘字段後面須要配合聚合函數來寫。 mysql> select id,count(distinct post) from employee; ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause 報錯了:是由於distinct不能返回其餘的字段,只能返回目標字段 mysql> select count(distinct post) from employee;
有時須要查詢出某個字段不重複的記錄,這時可使用mysql提供的distinct這個關鍵字來過濾重複的記錄,可是實際中咱們每每用distinct來返回不重複字段的條數(count(distinct id)),其緣由是distinct只能返回他的目標字段,而沒法返回其餘字段,distinct 想寫在其餘字段後面須要配合聚合函數來寫。 mysql> select id,count(distinct post) from employee; ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause 報錯了:是由於distinct不能返回其餘的字段,只能返回目標字段 mysql> select count(distinct post) from employee;
正則表達式查詢
#以前咱們用like作模糊匹配,只有%和_,侷限性比較強,因此咱們說一個正則,以前咱們是否是學過正則匹配,你以前學的正則表達式均可以用,正則是通用的
SELECT * FROM employee WHERE name REGEXP '^ale'; SELECT * FROM employee WHERE name REGEXP 'on$'; SELECT * FROM employee WHERE name REGEXP 'm{2}';
查看全部員工中名字是jin開頭,n或者g結果的員工信息
select * from employee where name regexp '^jin.*[g|n]$';
四.多表查詢常見的三種方式
多表鏈接查詢
內鏈接:只鏈接匹配的行
select * from employee,department where employee.dep_id=department.id;
查出技術部的員工的名字
select employee.name from employee,department where employee.dep_id=department.id and department.name='技術';
缺點:邏輯不太清晰
外連接之左鏈接:優先顯示左表所有記錄
#以左表爲準,即找出全部員工信息,固然包括沒有部門的員工 #本質就是:在內鏈接的基礎上增長左邊有右邊沒有的結果 #注意語法:
select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
外連接之右鏈接:優先顯示右表所有記錄
#以右表爲準,即找出全部部門信息,包括沒有員工的部門 #本質就是:在內鏈接的基礎上增長右邊有左邊沒有的結果 mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
全外鏈接:在內鏈接的基礎上增長左邊有右邊沒有的和右邊有左邊沒有的結果 #注意:mysql不支持全外鏈接 full JOIN #強調:mysql可使用此種方式間接實現全外鏈接 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;
#示例1:之內鏈接的方式查詢employee和department表,而且employee表中的age字段值必須大於25,即找出年齡大於25歲的員工以及員工所在的部門 select employee.name,department.name from employee inner join department on employee.dep_id = department.id where age > 25; #示例2:之內鏈接的方式查詢employee和department表,而且以age字段的升序方式顯示 select employee.id,employee.name,employee.age,department.name from employee,department where employee.dep_id = department.id and age > 25 order by age asc;
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:還能夠包含比較運算符:= 、 !=、> 、<等
一、帶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);
二、帶比較運算符的子查詢
select name,age from emp where age > (select avg(age) from emp); ps:查詢年齡大於平均年的的人
三、帶EXISTS關鍵字的子查詢
EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。而是返回一個真假值。True或False
當返回True時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行查詢。還能夠寫not exists,和exists的效果相反。
select * from employee -> where exists -> (select id from department where id=200);
五.pymysql模塊操做數據庫
#安裝 pip3 install pymysql
import pymysql
conn = pymysql.connect(
host='localhost',
port=3306,
user='root',
password='wang',
database='db1',
charset='utf8'
)
cursor = conn.cursor(pymysql.cursors.DictCursor) #建立遊標以字典的形式展現,不寫值默認是元組
sql = 'select * from department;' #寫sql
ret = cursor.execute(sql) #執行sql
print('受影響的行數>>> ',ret)
#print(cursor.fetchall()) #打印全部
# cursor.scroll(3,mode='absolute') #絕對位置移動光標
# cursor.scroll(3,mode='relative') #相對位置移動光標
print(cursor.fetchone()) #打印一行
#cursor.commit() #至關於mysql裏面的flush privileges 增刪改須要commit才能生效
未完待續......