目錄python
# 用來存儲數據的倉庫 # 數據庫能夠在硬盤及內存中存儲數據 # 數據庫與文件存儲數據區別 # 數據庫本質也是經過文件來存儲數據, 數據庫的概念就是系統的管理存儲數據的文件
數據庫服務器端: 存放數據庫的主機集羣 數據庫客戶端: 能夠鏈接數據庫的任意客戶端 數據庫管理員: DBA # socket套接字的C/S架構應用
# 重要性: *** # 庫: 多表構建一個數據庫, 本質就是文件夾 # 表: 多條數據構建一張表, 本質就是文件 # 記錄: 存放一條條數據, 本質就是文件中一條條數據記錄 # (字段)id, name, age, gender...一個老師的數據 => 一條數據記錄
# 重要性: *** # 關係型數據庫 # 1.有表的概念 # 2.以表中一條條記錄存儲數據 # mysql oracle sqlServer access db2 # 非關係型數據庫 # 1.沒有表的概念 # 2.經過key-value鍵值對方式存儲數據 # mongodb redis memcache
# 安裝server端與client端 # 如何啓動server? 若是經過client鏈接server
# 前提:配置環境變量 # 瞭解 # 1.前往數據庫安裝路徑,bin文件夾下,cmd執行 mysqld 啓動mysql服務器端 # 2.前往數據庫安裝路徑,bin文件夾下,cmd執行 mysql 啓動mysql客戶端鏈接服務器端
# 掌握 # 將mysql服務器添加到系統服務,在系統服務中啓動mysql, 命令: mysqld --install # 進入系統服務: win+r => services.msc => 找到mysql服務手動啓動或關閉 # 鏈接數據庫:mysql -hlocalhost -P3306 -uroot -p # 經過最高權限進入數據庫, 要採用root用戶進入, 連入本地數據庫: mysql -uroot -p
# 查看mysql版本: select version(); # 查看當前用戶: select user(); # 查看mysqld下的(當前用戶能夠操做的)全部數據庫: show databases;
# 修改密碼: mysqladmin -uroot -p舊密碼 password "新密碼"
# 查看數據庫配置信息: \s => 統一編碼 => 防止亂碼(讀取不方便,數據丟失) # 1.在mysql安裝根目錄下:建立my.ini (my.cnf) (命令:type nul>文件名.文件後綴) # 2.設置配置信息並保存 [mysqld] #port=7777 註釋 character-set-server=utf8 collation-server=utf8_general_ci [client] default-character-set=utf8 # 3.重啓服務
# 前提: 鏈接上數據庫 # 1.增,建立數據庫 # 採用默認編碼集: create database db1; # db1爲數據庫名 # 自定義編碼集: create database db1 charset="gbk"; # 2.查,查看數據庫所有信息 # 縱觀全部數據庫: show databases; # 詳細信息: show create database db1; # 3.改,修改數據庫編碼集 # alter database db1 charset="utf8"; # 4.刪, 移除數據庫 # drop database db1;
#前提: 在具體的某個庫下建立表 # 進入指定數據庫: use db1 # 肯定當前使用的數據庫: select database(); #1.增, 建立表(字段1 類型, ..., 字段n 類型) # create table t1(name char, age int); # 2.查,查看錶信息 # 縱觀全部數據庫: show tables; # 詳細信息: show create table t1; # 表字段結構信息: desc t1; # 3.改 # 修改字段屬性: alter table t1 modify name char(20); # 修改字段名: alter table t1 change name usr char(16); # 修改表名: alter table t1 rename t2; # 4.刪, 移除表 # drop table t1;
# 前提: 知道具體操做的是哪張表 # 1.增, 添加字段 # insert into t1 (usr, age) values ("aa", 18),("bb", 8); # 2.查 # select * from t1; # 3.改 # update t1 set age=28 where usr="aa"; # 4.刪 # delete from t1 where age>8;
前提: 引擎是建表是規定, 提供給表使用的, 不是數據庫 mysql> show engines; # 展現全部引擎 # 重點: # innodb(默認): 支持事務, 行級鎖, 外鍵 # myisam: 查詢效率要優於innodb, 當不須要支持事務, 行級鎖, 外鍵, 能夠經過設置myisam來優化數據庫 mysql> use db1; mysql> create table t1(id int)engine=innodb; mysql> create table t2(id int)engine=myisam; mysql> create table t3(id int)engine=blackhole; mysql> create table t4(id int)engine=memory; insert into t1 values(1); insert into t2 values(1); insert into t3 values(1); insert into t4 values(1); select * from t1; ...
''' create table 表名( 字段名1 類型[(寬度) 約束條件], 字段名2 類型[(寬度) 約束條件], 字段名3 類型[(寬度) 約束條件] )engine=innodb charset=utf8; ''' # []可選參數
# create table db1.t1(name char(3) not null); # 數據插入時,name不能爲空(null), 且最長只能存放三個字符 # 總結: 寬度和約束條件爲可選參數, 用來限制存放數據的規則
# sql_mode: 反映數據庫的全局變量 # 數據庫模式限制的是客戶端對服務器操做數據的方式(是否嚴格) # 兩種模式 no_engine_substitution:非安全性,默認 strict_trans_tables:安全模式 # 查看當前數據庫模式: show variables like "%sql_mode%"; # %匹配0~n個任意字符 => 模糊查詢 # 設置爲安全模式 set global sql_mode="strict_trans_tables"; # 重啓鏈接(客戶端) quit # 應用 create table t1(name char(2)); insert into t1 values ("ab") # 正常 insert into t1 values ("owen") # 錯誤 Data too long for column 'name' at row 1
# mysql數據庫支持存放哪些數據 # 整型 | 浮點型 | 字符型 | 時間類型 | 枚舉類型 | 集合類型
'''類型 tinyint:1字節 -128~127 * smallint:2字節 mediumint:3字節 int:4字節 -2147483648~2147483647 * bigint:8字節 ''' '''約束 * unsigned:無符號 zerofill:0填充 ''' # 不一樣類型所佔字節數不同, 決定所佔空間及存放數據的大小限制 # eg: create table t8(x tinyint); insert into t8 values(200); # 非安全模式存入,值只能到最大值127 select (x) from t8; '''寬度 1.不能決定整型存放數據的寬度, 超過寬度能夠存放, 最終由數據類型所佔字節決定 2.若是沒有超過寬度,且有zerofill限制, 會用0填充前置位的不足位 3.沒有必要規定整型的寬度, 默認設置的寬度就爲該整型能存放數據的最大寬度 * ''' # eg:1 create table t9(x int(5)); insert into t9 values(123456); select (x) from t9; # 結果: 123456 insert into t9 values(2147483648); select (x) from t9; # 結果: 2147483647 insert into t9 values(10); select (x) from t9; # 結果: 10 # eg:2 create table t10(x int(5) unsigned zerofill); # 區域0~4294967295 insert into t10 values(10); select x from t10; # 結果: 00010 insert into t10 values(12345678900); select x from t10; # 結果: 4294967295
'''類型 float:4字節,3.4E–38~3.4E+38 * double:8字節,1.7E–308~1.7E+308 decimal:M,D大值基礎上+2 ''' '''寬度: 限制存儲寬度 (M, D) => M爲位數,D爲小數位 float(255, 30):精度最低,最經常使用 double(255, 30):精度高,佔位多 decimal(65, 30):字符串存,全精度 ''' # eg:1 create table t11 (age float(256, 30)); # Display width out of range for column 'age' (max = 255) create table t11 (age float(255, 31)); # Too big scale 31 specified for column 'age'. Maximum is 30. # eg:2 create table t12 (x float(255, 30)); create table t13 (x double(255, 30)); create table t14 (x decimal(65, 30)); insert into t12 values(1.11111111111111111111); insert into t13 values(1.11111111111111111111); insert into t14 values(1.11111111111111111111); select * from t12; # 1.111111164093017600000000000000 => 小數據,精度要求不高, 均採用float來存儲 * select * from t13; # 1.111111111111111200000000000000 select * from t14; # 1.111111111111111111110000000000 alter table t14 modify x decimal(10, 5); # 1.11111 => 限制了數據的存儲寬度
'''類型 char:定長 varchar:不定長 ''' '''寬度 限制存儲寬度 char(4):以4個字符存儲定長存儲數據 varchar(4):數據長度決定字符長度,爲可變長度存儲數據 ''' # eg: create table t15 (x char(4), y varchar(4)); insert into t15 values("zero", 'owen'); # '' | "" 都可以表示字符 select x,y from t15; # 正常 insert into t15 values("yanghuhu", 'lxxVSegon'); # 非安全模式數據丟失,能夠存放, 安全模式報錯 select x,y from t15; # 能夠正常顯示丟失後(不完整)的數據 insert into t15 values('a', 'b'); # 驗證數據所在字符長度 # 前提: 安全模式下以空白填充字符 set global sql_mode="strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH"; # 重啓鏈接 select char_length(x), char_length(y) from t15; # a佔4 b佔1 '''重點: 存儲數據的方式 ** => 數據庫優化 char: 必定按規定的寬度存放數據, 以規定寬度讀取數據, 一般更佔空間 varchar: 首先根據數據長度計算所需寬度, 並在數據開始以數據頭方式將寬度信息保存起來, 是一個計算耗時過程, 取先讀取寬度信息,以寬度信息爲依準讀取數據, 一般節省空間 ''' 8: zero egon lxx yanghuhu 8: 4zero4egon3lxx8yanghuhu 注: varchar的數據頭佔1~2字節 規定char|varchar寬度均爲4,用來存放4個字符的數據, char存取更高效,char佔4字符,varchar佔5字符,char更省空間 總結: 數據長度相近的數據提倡用char來存放數據, 數據須要高速存取,以空間換時間, 採用char
'''類型 year:yyyy(1901/2155) date:yyyy-MM-dd(1000-01-01/9999-12-31) time:HH:mm:ss datetime:yyyy-MM-dd HH:mm:ss(1000-01-01 00:00:00/9999-12-31 23:59:59) timestamp:yyyy-MM-dd HH:mm:ss(1970-01-01 00:00:00/2038-01-19 ??) ''' # eg: 1 create table t16(my_year year, my_date date, my_time time); insert into t16 values(); # 三個時間類型的默認值均是null insert into t16 values(2156, null, null); # 在時間範圍外,不容許插入該數據 insert into t16 values(1, '2000-01-01 12:00:00', null); # 2001 2000-01-01 null insert into t16 values(2019, '2019-01-08', "15-19-30"); # time報格式錯誤 => 按照時間規定格式存放數據 alter table t16 change my_year myYear year(2); # 時間的寬度修改後仍是採用默認寬度 => 不須要關係寬度 # eg:2 create table t17(my_datetime datetime, my_timestamp timestamp); insert into t17 values(null, null); # 能夠爲空, 不能爲null,賦值null採用默認值current_timestamp insert into t17 values('4000-01-01 12:00:00', '2000-01-01 12:00:00'); # 在各自範圍內能夠插入對應格式的時間數據 # datetime VS timestamp datetime:時間範圍,不依賴當前時區,8字節,能夠爲null timestamp:時間範圍,依賴當前時區,4字節,有默認值CURRENT_TIMESTAMP
'''類型 enum:單選 set:多選 ''' create table t19( sex enum('male','female','wasai') not null default 'wasai', # 枚舉 hobbies set('play','read','music') # 集合 ); insert into t19 values (null, null); # sex不能設置null insert into t19 values (); # wasai null insert into t19 (hobbies) values ('play,read'), ('music,play'); # sex採用默認值, 對hobbies字段添加兩條記錄 insert into t19 (sex,hobbies) values ('male,female', 'play'); # sex字段只能單選
""" primary key:主鍵,惟一標識,表都會擁有,不設置爲默認找第一個 不空,惟一 字段,未標識則建立隱藏字段 foreign key:外鍵 unique key:惟一性數據, 該條字段的值須要保證惟一,不能重複 auto_increment:自增,只能加給key字段輔助修飾 not null:不爲空 default:默認值 unsigned:無符號 zerofill:0填充 """ 注: 1.鍵是用來說的io提供存取效率 2.聯合惟一 create table web ( ip char(16), port int, unique(ip,port) ); 3.聯合主鍵 create table web ( ip char(16), port int, primary key(ip,port) ); # eg:1 # 單列惟一 create table t20 ( id int unique ); # 聯合惟一 create table web ( ip char(16), port int, unique(ip,port) ); # 若是聯合兩個字段,兩個字段全相同才相同,不然爲不一樣 insert into web values ('10.10.10.10', 3306), ('10.10.10.10', 3306); # 注: # 1.表默認都有主鍵, 且只能擁有一個主鍵字段(單列主鍵 | 聯合主鍵) # 2.沒有設置主鍵的表, 數據庫系統會自上而下將第一個規定爲unique not null字段自動提高爲primary key主鍵 # 3.若是整個表都沒有unique not null字段且沒有primary key字段, 系統會默認建立一個隱藏字段做爲主鍵 # 4.一般必須手動指定表的主鍵, 通常用id字段, 且id字段通常類型爲int, 由於int類型能夠auto_increment # eg:2 create table t21(id int auto_increment); # 自增約束必須添加給key的字段 # eg:3 create table t21(id int primary key auto_increment); # 自增要結合key,不賦值插入,數據會自動自增, 且自增的結果一直被記錄保留 # eg:4 # 聯合主鍵 create table t22( ip char(16), port int, primary key(ip,port) ); # 若是聯合兩個字段,兩個字段全相同才相同,不然爲不一樣 insert into web values ('10.10.10.10', 3306), ('10.10.10.10', 3306);
''' 1.修改表名 alter table 舊錶名 rename 新表名; 2.修改表的引擎與字符編碼 alter table 表名 engine="引擎名" charset="編碼名"; 3.複製表 * # 結構 create table 新表名 like 舊錶名; eg:1 create table nt like tt; # 將tt的表結構複製到新表nt中, 約束條件一併複製 eg:2 create table nt1 select * from tt where 1=2; # 將tt的表結構複製到新表nt1中, 約束條件不會複製 # 結構+數據 create table 新表名 select * from 舊錶名; 注: 會複製表結構+數據, 但不會複製約束條件 4.清空表 truncate 表名; 注:表被重置,自增字段重置 '''
create table t2( id int primary key auto_increment, x int, y int ); insert into t2(x, y) values(10, 20), (100, 200), (1000, 2000); ''' 1.修改字段信息 alter table 表名 modify 字段名 類型[(寬度) 約束]; alter table t2 modify x bigint default 0; # 模式不一樣, 涉及精度問題 2.修改字段名及信息 alter table 表名 change 舊字段名 新字段名 類型[(寬度) 約束]; alter table t2 change y c char(10) not null; # 模式不一樣, 涉及類型轉換問題 3.添加字段名 # 末尾添加 alter table 表名 add 字段名 類型[(寬度) 約束], ..., add 字段名 類型[(寬度) 約束]; alter table t2 add age int, add gender enum("male", "female", "wasai") default "wasai"; # t頭部添加 alter table 表名 add 字段名 類型[(寬度) 約束] first; # 指定位添加:指定字段後 alter table 表名 add 字段名 類型[(寬度) 約束] after 舊字段名; alter table t2 add y int after x; 4.刪除字段名 alter table 表名 drop 字段名; alter table t2 drop y; '''
''' # 操做前提:登陸root用戶 1.重要字段 Host | User | Password 2.新建用戶 create user 用戶名@主機名 identified by '密碼'; # 正確 create user zero@localhost identified by 'zero'; 注:insert into mysql.user(Host,User,Password) values("主機名","用戶名",password("密碼")); # 錯誤 3.設置用戶權限 grant 權限們 on 數據庫名.表名 to 用戶名@主機名 [with grant option]; grant create on db1.* to zero@localhost with grant option; 注:權限有select,delete,update,insert,drop..., all表明全部權限 注:數據庫名,表名能夠用*替換,表明全部 注:設置權限時若是沒有當前用戶,會自動建立用戶,提倡使用 重點: grant all on db1.* to owen@localhost identified by 'owen'; # (建立用戶)設置權限 4.撤銷權限 revoke 權限名 on 數據庫名.表名 from 用戶名@主機名; revoke delete on db1.* from owen@localhost; 5.修改密碼 set password for 用戶名@主機名 = password('新密碼'); set password for owen@localhost = password('123'); 6.刪除用戶 drop user 用戶名@主機名; '''
社會中存儲須要能夠構建成表的數據, 它們造成的表,每每之間存儲某種或某些社會關係,mysql
mysql數據庫創建表結構就是社會中產生的各類數據, 分門別類管理web
但mysql創建的(代碼層次的)表之間, 一樣須要處理表與表之間的關係正則表達式
造成了 多對一 | 多對多 | 一對一 三種關係redis
''' 案例:員工employees表 | 部門department表 建表規則: 先創建主表,再創建從表,在從表中設置主表的惟一字段(一般爲主鍵)做爲外鍵 建表語法: create table 主表( id int primary key auto_increment, ... ); create table dep( id int primary key auto_increment, name varchar(16), work varchar(16) ); create table 從表( id int primary key auto_increment, ... 主表_id int, # 只是在從表中起了一個名字, 該名字和主表主鍵對應,全部起了個見名知義的名字 foreign key(主表_id) references 主表(惟一字段名id) on update cascade on delete cascade ); create table emp( id int primary key auto_increment, name varchar(16), salary float, dep_id int, foreign key(dep_id) references dep(id) on update cascade # 設置級聯 on delete cascade ); 插入記錄規則: 先插入主表數據,再插入從表數據 insert into dep values(1, '市場部', '銷售'), (2, '教學部', '授課'); insert into emp(name, salary, dep_id) values('egon', 3.0, 2),('yanghuhu', 2.0, 2),('sanjiang', 10.0, 1),('owen', 88888.0, 2),('liujie', 8.0, 1); 更新刪除數據: 兩表間相互影響,先從依賴數據入手,再進行更新刪除操做 eg:1 刪除主表dep中一個部門 delete from dep where id=1; => 從表emp中屬於該部門的員工都被刪除了 更新從表emp中一個員工的部門 update emp set dep_id=3 where name='egon'; <= 部門必須存在 insert into dep values(3, '管理部', '吃飯睡覺打豆豆, 明確團隊方針'); '''
''' 案例:做者author表 | 書book表 建表規則: 新建第三張表,經過兩個外鍵造成多對多關係 建表語法: create table 表1( id int primary key auto_increment, ... ); create table book( id int primary key auto_increment, name varchar(16), price int ); create table 表2( id int primary key auto_increment, ... ); create table author( id int primary key auto_increment, name varchar(16) ); create table 關係表( id int primary key auto_increment, 表1_id int, 表2_id int, foreign key(表1_id) references 表1(id) on update cascade on delete cascade, foreign key(表2_id) references 表2(id) on update cascade on delete cascade ); create table book_author( id int primary key auto_increment, book_id int, author_id int, foreign key(book_id) references book(id) on update cascade on delete cascade, foreign key(author_id) references author(id) on update cascade on delete cascade ); '''
''' 案例:丈夫husband表 | 妻子wife表 建表規則: 未存放外鍵的表被依賴,稱之爲左表;存放外鍵的表示依賴表,稱之爲右表;先操做左邊再操做右表 建表語法: create table 左表( id int primary key auto_increment, ... ); create table husband( id int primary key auto_increment, name varchar(16) ); create table 右表( id int primary key auto_increment, ... 左表_id int unique, # 一對一的外鍵須要惟一性 foreign key(左表_id) references 左表(id) on update cascade on delete cascade ); create table wife( id int primary key auto_increment, name varchar(16), husband_id int unique, # 一對一的外鍵須要惟一性 foreign key(husband_id) references husband(id) on update cascade on delete cascade ); '''
''' 1.全部數據按順序插入 insert [into] 表名 values (值1, ..., 值n)[, ..., (值1, ..., 值n)]; 2.指定字段匹配插入,能夠任意順序 insert [into] 表名(字段2, 字段1, ..., 字段n) values (值2, 值1, ..., 值n)[, ..., (值2, 值1, ..., 值n)]; 3.插入查詢結果 insert [into] 表1(字段1, ..., 字段n) select 字段1, ..., 字段n from 表2 [條件]; ''' # eg: 1 create table t1( id int auto_increment, x int, y int, primary key(id) ); insert t1 values (1, 2, 3), (2, 20, 30); # 按順序插入 insert into t1(y, x) values (300, 200); # 按規定字段順序指定插入 create table nt1 like t1; # 複製表即完整結構 insert into nt1 select * from t1; # 複製全部數據 create table tt1( x int, z int ); insert into tt1 values (999, 888); insert into nt1(x) select x from tt1; # 將tt1中指定字段插入到nt1中指定的字段 insert into nt1(x, y) select x,z from tt1; # tt1x及z字段的結果賦值給nt1中x,y字段
''' 1.會記錄自增信息,操做會被日誌記錄,效率低 delete from 表名 [條件]; delete from t1; # 沒有條件的狀況下是清空全部數據, 但會記錄自增信息 insert into t1(x, y) values(6, 66); 2.清空表,會重置自增信息 truncate table 表名; truncate table nt1; insert into nt1(x, y) values(6, 66); '''
update 表名 set 字段1=值1[, ..., 字段n=值n] [條件] update tt1 set x=666; # 無條件, 全改 update tt1 set x=777, z=555 where z<888; # 只修改知足條件的行
''' select [distinct] 字段1 [as 別名], ..., 字段n [as 別名] from [庫名.]表名 [ where 約束條件 group by 分組依據 having 過濾條件 order by 排序的字段 limit 限制顯示的條數 ]; 注: 1.查表中全部字段用*表示 2.條件的書寫規則嚴格按照語法順序書寫,能夠缺省,但不能夠錯序 3.約束條件的流程:from -> where -> group by -> having -> distinct -> order by -> limit 4.字段能夠起別名 5.字段能夠直接作運算 select age + 1 'new_age' from emp; 6.分組後的條件都可以使用聚合函數 ''' ''' 3. def from(): return "查詢的文件" def where(file): return "條件篩選後的結果" def group_by(res): return "分組後的結果" def having(res): return "再次過濾後的結果" def distinct(res): return "去重後的結果" def order_by(res): return "排序後的結果" def limit(res): return "限制條數後的結果" def select(from=from, where=null, ..., limit=null): file = from() res = where(file) if where else file res = group_by(res) if group_by else res ... res = limit(res) if limit else res return res select(where=where, group_by=group_by) '''
CREATE TABLE `emp` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL, `gender` enum('男','女','未知') NULL DEFAULT '未知', `age` int(0) NULL DEFAULT 0, `salary` float NULL DEFAULT 0, `area` varchar(20) NULL DEFAULT '中國', `port` varchar(20) DEFAULT '未知', `dep` varchar(20), PRIMARY KEY (`id`) ); INSERT INTO `emp` VALUES (1, 'yangsir', '男', 42, 10.5, '上海', '浦東', '教職部'), (2, 'engo', '男', 38, 9.4, '山東', '濟南', '教學部'), (3, 'jerry', '女', 30, 3.0, '江蘇', '張家港', '教學部'), (4, 'tank', '女', 28, 2.4, '廣州', '廣東', '教學部'), (5, 'jiboy', '男', 28, 2.4, '江蘇', '蘇州', '教學部'), (6, 'zero', '男', 18, 8.8, '中國', '黃浦', '諮詢部'), (7, 'owen', '男', 18, 8.8, '安徽', '宣城', '教學部'), (8, 'jason', '男', 28, 9.8, '安徽', '巢湖', '教學部'), (9, 'ying', '女', 36, 1.2, '安徽', '蕪湖', '諮詢部'), (10, 'kevin', '男', 36, 5.8, '山東', '濟南', '教學部'), (11, 'monkey', '女', 28, 1.2, '山東', '青島', '教職部'), (12, 'san', '男', 30, 9.0, '上海', '浦東', '諮詢部'), (13, 'san1', '男', 30, 6.0, '上海', '浦東', '諮詢部'), (14, 'san2', '男', 30, 6.0, '上海', '浦西', '教學部');
select concat(area, '-', port) as '家鄉' from emp; # 上海-浦東... 屬於 起的別名 家鄉 列 select concat_ws("-", name, area, port) '信息' from emp; # 以"-"字符拼接後面的全部字段 select upper(name) 'name', gender, age from emp; # 能夠指定多個字段 select name, ceil(salary), floor(salary), round(salary) from emp where name='kevin'; # 數學函數 # 去重前提: 所查全部字段的綜合結果徹底相同, 才認爲是重複的, 只保留重複中的一行數據 select distinct area from emp; select distinct area, port from emp;
concat(字段1,...,字段n):完成字段的拼接 concat_ws(x, 字段1,...,字段n):完成字段的拼接,x爲鏈接符 lower():小寫 upper():大寫 ceil():向上取整 floor():向下取整 round():四捨五入
''' 1.比較運算符 = | < | > | <= | >= | != select * from emp where area!="上海"; 2.區間運算符 between 10 and 20:10~20 in(10, 20, 30):10或20或30 select * from emp where id between 3 and 5; # [3, 5], 閉合區間,包含3和5, 三行數據 select * from emp where id in(2, 4, 6, 8, 10, 12, 14, 16, 18); # 分離的區間,2,4,6,8,10,12,14都會被顯示 3.邏輯運算符 and | or | not select * from emp where area="山東" and port="濟南"; 4.類似運算符 like '_owen%':模糊匹配字符串owen,_表示一個字符,%表示任意字符 # 匹配的字段爲en,想獲得的結果爲owen select * from emp where name like '__en%'; # 在en前能夠出現2個任意字符, 以後能夠出現0或多個任意字符 ''' # 需求: # 查找姓名有數字的員工信息
# why: like完成模糊匹配, 但功能侷限, 能夠模糊個數, 但不能模糊類型, 正則能夠完成類型及個數的模糊匹配 ''' 語法:字段 regexp '正則表達式' 注:只支持部分正則語法 ''' # 完成需求: select * from emp where name regexp '.*[0-9]+.*';
''' 分組:根據字段相同值造成不一樣的類別,不明確分組其實整個表就爲一個默認大組 緣由:把以值共性獲得的類別做爲考慮單位,再也不關係單條記錄,並且一組記錄 結果:只能考慮組內多條數據的聚會結果(聚合函數結果),分組的字段一樣是聚合結果,如:組內的最大最小值 sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION 聚合函數: max():最大值 min():最小值 avg():平均值 sum():和 count():記數 group_concat():組內字段拼接,用來查看組內其餘字段 eg:1 每一個部門的平均薪資 select dep, avg(salary) '平均薪資' from emp group by dep; eg:2 每一個部門都有哪些人 select dep, group_concat(name) from emp group by dep; 需求: 各性別中附屬於教學部的最高薪資 select max(salary) '最高薪資', gender from emp where dep='教學部' group by gender; 思考: 想知道需求中員工的姓名 => 子查詢 上方結果: 男的最高薪資對應的人名, 女的最高薪資對應的人名 # select group_concat(name), max(salary) '最高薪資', gender from emp where dep='教學部' group by gender; 錯誤 ''' ''' 1. 14條數據部門有3個, 而且每一個部分有多條記錄, 能夠做爲分組依據, 同理, 性別也能夠 # select * from emp group by dep; # 非分組安全模式下, 能夠查詢非聚合結果, 顯示的是第一條記錄, 沒有意義, 分組安全模式下不能查詢非聚合結果的字段 select dep from emp group by dep; 2. 若是就像以姓名進行分組, 能夠, 但沒多大意義, 緣由name值基本上都不相同, 以組考慮會致使組內大多隻要一條記錄(自成一組), 組的利用就不是很強烈, 此類分組是無心義的 select name from emp group by name; # 能夠分組, 意義不大 考慮的三個問題: 以什麼分組(相同數據較多的字段) 分組後的考慮單位(組並不是組內的每一條記錄) 能夠查詢的結果(當前分組的字段及聚合函數造成的聚合結果) '''
# res = select max(salary) '最高薪資', gender from emp where dep='教學部' group by gender; # select name from emp where (salary 跟 res做比較) # 一個查詢依賴於另外一個查詢的結果 => 一個查詢的結果做爲另一個查詢的條件 => 子查詢
''' 子查詢:將一條查詢結果做爲另一條查詢的條件 語法:一條select語句用()包裹獲得的結果做爲另外一條select語句的條件 # 僞sql: select * from emp where salary =|in (select salary from emp where 條件) 單行子查詢: 子查詢語句的結果爲一行數據,能夠結合 = | < | > | <= | >= | != 運算符來完成父查詢 select salary from emp where salary > 10; # => 做爲子查詢 # 查詢姓名,性別.地區,基於薪資大於10的結果的查詢結果 eg: 1 select name, gender, area from emp where salary = (select salary from emp where salary > 10); 多行子查詢: 子查詢語句的結果爲多行數據,能夠結合 in | all | any 運算符來完成父查詢 in:任意單一值,一次只能考慮子查詢中的一個結果 all:所有值,將子查詢結果做爲一個總體考慮 any:任意多個值:子查詢的每個結果均可以做爲參考依據 eg: 2 # 子查詢的結果 (9.4, 3) select name from emp where salary in (select max(salary) '最高薪資' from emp where dep='教學部' group by gender); # 遍歷14條數據, 14條數據的salary在(9.4, 3)區域中,就能夠完成匹配, 結果爲兩條(9.4和3那兩條) select * from emp where salary < all(select max(salary) '最高薪資' from emp where dep='教學部' group by gender); # 遍歷14條數據, salary要小於(9.4, 3)中的每個, 反映就是小於3, 結果爲薪資1.2,2.4的那四條數據 select * from emp where salary > any(select max(salary) '最高薪資' from emp where dep='教學部' group by gender); # 遍歷14條數據, salary大於9.4或大於3的數據均知足條件, 結果就是刨除小於等於3的那幾條數據 '''
''' why:完成在分組以後的篩選 注意:having條件是實現聚合結果層面上的篩選 => 拿聚會結果完成判斷 需求: 1.各部門的平均薪資 select dep, avg(salary) '平均薪資' from emp group by dep; 2.平均薪資大於6w的部門(部門與部門的平均薪資) 解決: 以dep進行分組, 以avg(salary)做爲判斷條件(篩選) select dep, avg(salary) '平均薪資' from emp group by dep having avg(salary) > 6; # 總結: having經過聚合函數結果完成篩選 select max(salary) from emp having max(salary) > 9.4; # 雖然沒有明確書寫group by, 但在having中使用了聚合函數,因此該查詢就將整個表當作一個默認大表來考慮,因此查詢的字段只能爲聚合函數的結果 '''
''' why:完成排序 注意:可使用聚合函數,哪怕沒有明確group by 升序 | 降序:asc | desc eg:order by age desc => 按照年齡降序 select * from emp order by age desc; 需求: 將部門按照部門平均工資降序方式排序 select dep, avg(salary) from emp group by dep order by avg(salary) desc; '''
''' why:限制最終結果的數據行數 注意:limit只與數字結合使用 應用: limit 1:只能顯示一行數據 limit 6,5:從第6+1行開始顯示5條數據(索引從0開始) select * from emp limit 1; select * from emp limit 6,5; 需求: 得到薪資最高的人的一條信息 select * from emp order by salary desc limit 1; '''
create table dep( id int primary key auto_increment, name varchar(16), work varchar(16) ); create table emp( id int primary key auto_increment, name varchar(16), salary float, dep_id int ); insert into dep values(1, '市場部', '銷售'), (2, '教學部', '授課'), (3, '管理部', '開車'); insert into emp(name, salary, dep_id) values('egon', 3.0, 2),('yanghuhu', 2.0, 2),('sanjiang', 10.0, 1),('owen', 88888.0, 2),('liujie', 8.0, 1),('yingjie', 1.2, 0);
''' # 需求: # 查看每位員工的部門的全部信息 select * from emp; select * from dep; # 子查詢, 最終結果只能顯示單表的信息, 但需求是同時顯示兩張表的信息 => 先將兩張表合成一張表 select * from emp where dep_id in (select id from dep); ''' ''' 笛卡爾積: 集合 X{a, b} * Y{o, p, q} => Z{{a, o}, {a, p}, {a, q}, {b, o}, {b, p}, {b, q}} 交叉查詢: select * from emp, dep; | select * from emp course join dep; ''' ''' 作了篩選, 結果<=完整數據, 非笛卡爾積 select * from emp, dep where db2.emp.dep_id = db2.dep.id; # 同sql語句上表現是從兩張表拿數據 # 注意: 同時查詢兩張表造成新的表,能夠稱之爲虛擬表, 原表與表之間可能存在重複字段, 同時使用時須要明確所屬表,必要時還需明確所屬數據庫 '''
''' inner join on 內鏈接:結果爲兩張表有對應關係的數據(emp有dep沒有,emp沒有dep有的記錄均不會被虛擬表展現) 語法:左表 inner join 右表 on 兩表有關聯的字段的條件, on就是產生對於關係的(鏈接的依據) eg:select * from emp inner join dep on emp.dep_id = dep.id; '''
''' left join on 左鏈接:在內鏈接的基礎上還保留左表特有的記錄 語法:左表 left join 右表 on 兩表有關聯的字段的條件 eg:select emp.name '員工', dep.name '部門', dep.work '職責' from emp left join dep on emp.dep_id = dep.id; '''
''' right join on 右鏈接:在內鏈接的基礎上還保留右表特有的記錄 語法:左表 right join 右表 on 兩表有關聯的字段的條件 eg:select * from emp right join dep on emp.dep_id = dep.id; ''' ''' 在鏈接語法join 前就是左表, 後就是右表 採用的是left關鍵詞就是左鏈接, right關鍵詞就是右鏈接, inner關鍵詞就是內鏈接 '''
''' 全鏈接:在內鏈接的基礎上分別保留這左表及右表特有的記錄 語法:mysql沒有full join on語法,但能夠經過去重達到效果 eg: select * from emp left join dep on emp.dep_id = dep.id union select * from emp right join dep on emp.dep_id = dep.id; '''
# 模塊pymysql # 按照並導入pymysql: pip3 insatll pymysql # 經過pymysql操做數據庫分四步: ''' 1.創建鏈接 conn = pymysql.connect(host="localhost", port=3306, db='db2', user='root', password='root') 2.設置字典類型遊標 cursor = conn.cursor(pymysql.cursors.DictCursor) 3.執行sql語句並使用執行結果 # 書寫sql語句 sql = 'select * from emp' # 執行sql語句, 有返回值, 返回值爲獲得的記錄行數 line = cursor.execute(sql) print(line) # 使用執行的結果: fetchone())當前遊標日後獲取一行記錄 fetchall()當前遊標日後全部的記錄 scroll(num, mode="relative|absolute") relative: 遊標從當前位置日後移動num行 ablolute: 遊標從頭日後移動num行, 通常能夠結合line來使用能定位到任意位置 tag = cursor.fetchone() # 第一條 print(tag) print(tag['salary']) tag = cursor.fetchone() # 第二條 print(tag) cursor.scroll(1, mode='relative') # 偏移第三條 # cursor.scroll(line - 1, mode='absolute') # 指針絕對, 遊標永遠從頭開始偏移 tags = cursor.fetchall() # 第四條到最後 print(tags) 4.斷開鏈接 cursor.close() conn.close() '''
# 什麼是sql注入: # 經過書寫sql包含(註釋相關的)特殊字符, 讓原有的sql執行順序發生改變, 從而改變執行獲得的sql # 目的: # 繞過原有的sql安全認證, 達到對數據庫攻擊的目的 # 沒有處理sql注入的寫法 sql = 'select * from user where usr="%s" and pwd="%s"' % (usr, pwd) res = cursor.execute(sql) # sql注入 # 1.知道用戶名: abc" -- hehe | ooo # select * from user where usr="abc" -- hehe" and pwd="ooo" # 2.不知道用戶名 aaa" or 1=1 -- hehe | 000 # select * from user where usr="aaa" or 1=1 -- hehe" and pwd="000" # 處理sql注入 sql = 'select * from user where usr=%s and pwd=%s' res = cursor.execute(sql, (usr, pwd))
# 增 # 增sql語句 sql1 = 'insert into user(usr, pwd) values (%s, %s)' # 在內存中一次插入一條 cursor.execute(sql1, ("opq", "123")) # 在內存中一次插入多條 cursor.executemany(sql1, [("aaa", "000"), ("bbb", "111")]) # 將內存中的數據提交到硬盤中 conn.commit() # 刪 sql2 = 'delete from user where usr=%s' cursor.execute(sql2, ("aaa")) conn.commit() # 改 sql3 = 'update user set pwd=%s where usr=%s' res = cursor.execute(sql3, ("222", "bbb")) conn.commit()
''' what:事務是邏輯上的一組操做,要麼都成功,要麼都失敗 why:不少時候一個數據操做,不是一個sql語句就完成的,可能有不少個sql語句,若是部分sql執行成功而部分sql執行失敗將致使數據錯亂 eg:轉帳 => 轉入轉出均成功,才能認爲操做成功 事務的使用: start transaction; --開啓事物,在這條語句以後的sql將處在同一事務,並不會當即修改數據庫 commit;--提交事務,讓這個事物中的sql當即執行數據的操做, rollback;--回滾事務,取消這個事物,這個事物不會對數據庫中的數據產生任何影響 事務的四大特性: 1.原子性:事務是一組不可分割的單位,要麼同時成功,要麼同時不成功 2.一致性:事物先後的數據完整性應該保持一致(數據庫的完整性:若是數據庫在某一時間點下,全部的數據都符合全部的約束,則稱數據庫爲完整性的狀態) 3.隔離性:事物的隔離性是指多個用戶併發訪問數據時,一個用戶的事物不能被其它用戶的事務所幹擾,多個併發事務之間數據要相互隔離 4.持久性:持久性是指一個事物一旦被提交,它對數據的改變就是永久性的,接下來即便數據庫發生故障也不該該對其有任何影響 事務的用戶隔離級別: 數據庫使用者能夠控制數據庫工做在哪一個級別下,就可與防止不一樣的隔離性問題 read uncommitted --不作任何隔離,可能髒讀,幻讀 read committed --能夠防止髒讀,不能防止不可重複讀,和幻讀, Repeatable read --能夠防止髒讀,不可重複讀,不能防止幻讀 Serializable --數據庫運行在串行化實現,全部問題都沒有,就是性能低 修改隔離級別: select @@tx_isolation;--查詢當前級別 set[session|global] transaction isolation level ....;修改級別 實例: set global transaction isolation level Repeatable read; 注:修改後從新鏈接服務器生效 '''
#準備數據 create table account( id int primary key auto_increment, name varchar(20), money double ); insert into account values (1,'owen',10000), (2,'egon',1000), (3,'jerry',1000), (4,'kevin',1000); # egon向owen借1000塊錢 # 未使用事務 update account set money = money - 1000 where id = 1; update account set moneys = money + 1000 where id = 2; # money打錯了致使執行失敗 # 在python中使用事務處理 from pymysql.err import InternalError sql = 'update account set money = money - 1000 where id = 1;' sql2 = 'update account set moneys = money + 1000 where id = 2;' # money打錯了致使執行失敗 try: cursor.execute(sql) cursor.execute(sql2) conn.commit() except InternalError: print("轉帳失敗") conn.rollback()