SQL回顧

數據庫的本質是一種特殊的文件python

數據庫是由數據表組成的,數據表是真正存儲數據的mysql

數據庫客戶端-->SQL語句-->數據庫服務器-->數據庫文件redis

表與表之間存在關聯的數據庫稱爲關係型數據庫 (sql-server my-sql(5.1, 5.6, 5.7) Oracle(10g, 11g) db2)
非關係型數據庫(mongodb redis)sql

惟一的標識一行信息的特殊的列 主鍵(primary key)不容許重複,不容許爲空
當前表中的某個字段來自與另外一張表中的主鍵的值,那麼這個字段稱之爲 外鍵(foreign key)
列 字段 同一類的信息
行 記錄 對象的詳細信息
記錄的集合組成數據表,數據表的集合組成數據庫文件mongodb


DQL 數據查詢語言 select
DML 數據操做語言 insert, update, delete
DDL 數據定義語言 create, drop數據庫

數據庫服務端的安裝 sudo apt-get install mysql
數據庫客戶端的安裝 sudo apt-get install mysql-client編程

將程序的一些配置 寫到配置文件中 修改的時候不用修改程序只須要修改配置文件便可(能夠更好地保護程序源碼)緩存

decimal() 佔5位小數佔2位安全

enum("狀況1","狀況2",..) 把全部可能出現的狀況都列舉出來服務器

體積比較大的文件不存在數據庫中 存在第三方網站或者文件存儲系統中 數據表中存儲圖片的url(如圖片,音視頻)(這個url是外鍵)

文件存儲系統 (GFS TFS fastdfs--小文件)

數據的使用原則 合適爲宜

數據約束
(not null,primary key,auto increment,unsigned 等 )

數據約束和數據類型 都保證數據的完整性

命令行鏈接數據庫
mysql -u root -p-->須要輸入密碼
mysql -u -p密碼

命令行數據庫操做基本語句
select now();顯示時間
select datdabases;查詢全部數據庫
create database 數據庫名(不能重名) charset=utf8;建立數據庫 數據庫中須要漢字或字符 須要指定編碼格式
alter 數據庫名 character set 編碼格式; 修改已建立數據庫的編碼格式
select datdabase(); 查看當前使用的數據庫
use 數據庫名; 使用一個數據庫
drop database 數據庫名; 刪除數據庫 謹慎使用最好別用

命令行表的操做

create table 表名(字段 約束,字段 約束,...); 建立表

desc 表名; 查看錶結構
show tables; 查看數據庫中有那些表
show create table 表名; 查看建立表的語句

select * from 表名; 查看錶中的全部數據

insert into 表名 values(0,1字段的值, 2字段的值, 3字段的值,..);按照約束向表中添加一條數據(所有插入)
insert into 表名(字段1,字段2..)values(值1,值2..)----------------------------------------(部分插入)
insert into 表名(字段1,字段2..)values(值1,值2),(值1,值2),(值1,值2)... 一次插入多條數據--(多行插入)
insert into 表名 values(全部值),(全部值),... 一次插入多行徹底信息-------------------(全列多行插入)

alter table 代表 drop 字段名 刪除表中的字段

delete from 表名; 刪除表中全部數據
truncate 表名; 清空表 主鍵也抹去至0`
drop table 表名; 刪除表,表結構也也刪除 慎用 不要用,沒學過
rename table test to test1; 修改表的名字

insert into 表名 values(0,1字段的值, 2字段的值, 3字段的值,.);按照約束向表中添加一條數據(增)

update 表名 set 字段="新值",字段="新值",... where id=須要修改的人的id 更新表數據------(改)

select 字段 as 別名,... from 表名;-----------------------------------------------------(查)

delete from 表名 where 條件; 刪除條件指定的表中的數據 ---------------------------------(刪)

查的強化拓展

給表起別名 select 表別名.字段1,表別名.字段2,.... from 表名 as 表別名;
若是給表起了別名,可是非要用原表名那是不行的.!!

 

去重 select distinct 字段 from 表; 查詢字段中的數據並去重

條件查詢
select 字段1,字段2 from 表名 where 條件; >,>=,=,<,<=,(!=,<>) <>不通用 ----------算術運算符
select * from 表名 where 條件1 and 條件2; and,or,not,----------------------------邏輯運算符
select * from 表名 where 字段 like "條件"; %-->任意個字符,_一個任意字符 ---------模糊查詢
select * from 表名 where 字段 rlike "^小.*月$";"^以什麼開頭 .*任意個字符 以什麼結尾$"------正則
select * from 表名 where 字段 in (18,30,45); 非連續範圍,可取反--------------------範圍查詢
select * from 表名 where 字段 between 值and 值;連續範圍,可取反 -------------------範圍查詢
select * from 表名 where 字段 not between 值and 值;連續範圍取反 ------------------範圍查詢
select * from 表名 where 字段 is null;判斷某個字段的值爲空------------------------空判斷
select * from 表名 where 字段 is not null;判斷某個字段的值不爲空------------------判斷不爲空

排序
select * from 表名 where (age between 18 and 30 ) and gender = "女" order by age desc;
order by 多個條件時優先知足前面的條件
asc 升序(默認)
desc 降序

聚合函數
select count(*) as 別名 from 表名 where 條件; count() 總數
select max(字段) as 別名 from 表名; max()最大值min()最小值
select sum(字段) from 表名; sum()求和
select avg(字段) from 表名; avg()求平均
select round(avg(字段),保留的小數位數) from 表名; avg()求平均round()保留小數位數(四捨五入)

分組
select 字段1,字段2 from 表名 group by 字段1,字段2;按照字段1字段2進行分組
select gender,count(*) from students group by gender;查看分組中的人數

group_concat組鏈接函數
select gender,count(*),group_concat(name) from students group by gender;顯示分組中具體的人物信息

having
select gender,group_concat(name,age) from students group by gender having avg(age)>30;查詢平均年齡超過30歲的性別,以及姓名

rollup 彙總
select gender,count(*) from students group by gender with rollup;按性別分組查看每組的人數和總人數

limit 起始位置,每頁顯示的數據個數 分頁顯示
limit (第n頁-1)*每頁要顯示的個數,每頁要顯示的個數
select * from students limit 0,5; 第一頁,顯示五個數據
select * from students limit 5,5; 第二頁,顯示五個數據
select * from students limit 10,5;第三頁,顯示五個數據
limit 必須 放置在語句最後

連接查詢
外連接
左外連接
以左表爲主沒有查詢到的數據補null
select * from students left join classes on students.cls_id = classes.id;
右外連接
以右表爲主沒有查詢到的數據補null
select * from students right join classes on students.cls_id = classes.id;

內連接 兩張表有交集
inner join on
select * from 表名inner join 表名; 笛卡爾積;
select * from 表名1inner join 表名2 on 表名1.字段1=表名2.字段2;
select students.* ,classes.name from students inner join classes on students.cls_id = classes.id;

select students.name as 姓名 ,classes.name as 班級 from students inner join classes on students.cls_id= classes.id group by classes.name desc;
+-----------+--------------+
| 姓名 | 班級 |
+-----------+--------------+
| 小月月 | python_02期 |
| 劉亦菲 | python_02期 |
| 劉德華 | python_02期 |
| 程坤 | python_02期 |
| 鳳姐 | python_02期 |
| 周杰倫 | python_01期 |
| 黃蓉 | python_01期 |
| 王祖賢 | python_01期 |
| 小明 | python_01期 |
| 彭于晏 | python_01期 |
+-----------+--------------+
select c.name,s.name
from students as s inner join classes as c on s.cls_id = c.id order by c.name ,s.id asc;

多表聯合查詢
select * from students , classes where students.cls_id = classes.id;

行子查詢
select 語句中嵌套select 語句
select * from students where age >(select avg(age) from students);
大於平均年齡的人

列子查詢
select id from classes where id = 1;
select * from students where students.cls_id in(select id from classes);
select * from students where students.cls_id in(select id from classes where id =1);

自關聯 將多張表合到一張表中本質就是一張表
能夠解決無限分表的問題 層次關係分明時使用
select * from -----areas as county -----inner join----areas as city----on----county.pid = city.aid and city.atitle="武漢市";

 


拆分表
字段改名時使用 便於表的維護

流程
1創建空表good_cates 兩個字段 id name
create table goods_cates(id int unsigned not null primary key auto_increment,name varchar(40) not null);

2把原表裏的字段cate_name的數據查詢出來插入到新表good_cates中
###select cate name from goods group by cate_name;
insert into goods_cates(name) select cate_name from goods group by cate_name;

3經過good_cates表的數據更新原表的數據, 把新表的id替換給原表的字段的值
selsect * from goods inner join goods_cates on goods.cate_name = goods_cates.name;
update (goods inner join goods_cates on goods.cate_name = goods_cates.name) set goods.cate_name = goods_cates.id;
4修改原表的字段的類型 和新表的主鍵的類型一致 而且要把原表字段名改成_id
alter table goods change name cate_name cate_id int unsigened notnull;-->更名

 

1 創建空表goods_brands 兩個字段 id name 插入數據
create table goods_brands (id int unsigned not null primary key auto_increment,
name varchar(40) not null) select brand_name as name from goods group by brand_name;

2 同步數據
select * from goods inner join goods_brabds on goods.brand_name = goods_brands.name:

3 改變類型
update (goods_brands inner join goods on goods_brands.name = goods.brand_name) set goods.brand_name = goods_brands.id;

4 修改表結構
alter table goods change brand_name brand_id int unsigned not null;


外鍵的使用 限制非法數據的插入 使用外鍵致使數據庫更新數據的性能大大下降
添加外鍵約束
alter table 要修改的表名 add foreign key (要修改的表的外鍵字段) references 參考表(主鍵字段);
建立表的時候就能夠添加外鍵約束
取消外鍵約束
show create table 表名; 獲得外鍵名稱
alter table goods drop foreign key 外鍵名稱;

不使用外鍵 添加約束的方法
使用應用程序 獲取表中的id 使用 for 循環 判斷新插入的數據是否合法(在內存中判斷)

 

數據庫編程
流程
開始--->建立鏈接對象---->建立遊標cursor對象--->執行sql--->關閉cursor對象--->關閉connection--->結束

建立鏈接對象
conn = connect(host="localhost",port=3306,user="root",password="mysql",database="jing_dong",charset="utf8")

host: 鏈接的MySQL主機
port:MySQL主機的端口默認3306
database:數據庫的名稱
user:鏈接的用戶
password :用戶的密碼
charset: utf8

調用Connection對象的cursor()方法
cur =conn.cursor()

定義要執行的sql語句
sql = "sql語句"

經過鏈接對象獲取遊標對象 cursor
遊標對象=鏈接對象.cursor()

使用遊標對象操做sql語句
sql語句的結果=遊標對象.execute(sql語句)
print(sql語句的結果)

經過遊標對象獲取數據
遊標對象.fetchall()獲取全部結果集 格式是元組套元組
遊標對象.fetchone()獲取下一條結果集
遊標對象.fetchmany(要獲取的行數)獲取多行結果集 格式是元組套元組

若是sql語句更新了數據庫中的數據須要提交
conn.commit()

遊標對象 cur.close()
關閉鏈接 conn.close()
提交數據 conn.commit()
撤銷數據 conn.rollback()


sql注入
sql語句不進行過濾 經過非法語句能夠攻進數據庫獲取全部數據
經過sql注入 where後的條件語句恆爲真
語法
' or 1=1 or '1
' or 1=1 or '1== True
防止sql注入
select * from goods where name = %s;---設置參數化列表機制
使用execute()函數本身拼接sql語句
execut(sql,[錄入的數據])


數據庫備份
mysqldump –uroot –p 數據庫名 > python.sql;

數據庫恢復
首先建立 新數據庫名 設置編碼
執行 數據庫備份的代碼
mysql -uroot –p 新數據庫名 < python.sql

> 重定向覆蓋寫入

 

視圖
把複雜的aql語句封裝起來的虛表,在物理內存中並不存在 能夠直接對視圖進行查詢

提升重用性,像函數
對數據庫進行重構更改,不影響程序運行
提升安全性,對用戶展現指定字段,屏蔽重要的其它字段
讓數據更加清晰

建立視圖
create view v_視圖名 as select 語句;
建立視圖時不容許有相同的字段名,須要給字段起別名
原表的數據發生變化,視圖裏的內容也會發生相應的變化

視圖能夠指向新的數據 就是 修改視圖
alter view v_視圖名 as 新的select語句;

刪除視圖
drop view v_視圖名;

事務 InnoDB引擎的數據庫才支持事務
Transaction 做爲一個基本工做單元執行的一系列sql語句要麼所有執行成功,要麼所有失敗
四大特性
原子性 一整個單位不能拆分
一致性 客戶端的操做的結果一致
隔離性 多個客戶端都開啓事務操做同一數據,一方不提交就會阻塞,另外一方就沒法操做數據,是行級鎖機制
持久性 一旦提交所做的修改會永久保存到數據庫

開啓事務
begin 或者 start transaction;
提交事務 沒有提交以前數據是在緩存區,一旦提交數據就會保存到數據庫文件中
commit
回滾事務 在沒有提交以前是能夠回滾地,可是提交以後是沒法回滾的,回滾是無效地
rollback
mysql 客戶端默認是開啓事務,默認提交
pyrthon程序中默認開啓事務,須要手動提交

 

索引
查看錶中是否存在索引
show index from 表名;
建立索引 建立索引時會建立B樹數據結構因此時間比較慢
create index 索引名 on 表名(字段名);
刪除索引
drop index 索引名 on 表名;
查詢
set profiling =1; 設置時間監測
查找數據地sql語句
show profiles; 查看用時時長
索引會佔用磁盤空間

 

MySQL用戶管理
建立特定的帳戶,給予這個帳戶特定的權限
建立用戶 並授予權限
使用root帳戶登錄
grant 權限列表 on 數據庫名 to "用戶名" @ "訪問主機" identified by "新建立的帳戶地密碼";
訪問主機一般使用 百分號% 表示此帳戶可使用任何ip的主機登陸訪問此數據庫
訪問主機能夠設置成 localhost或具體的ip,表示只容許本機或特定主機訪問
刷新權限:flush privileges;
給用戶配置權限
grant 權限 on 數據庫 to 用戶名@localhost with grant option;
修改用戶密碼
update user set authentication_string=password('新密碼') where user='用戶名';
修改用戶名
rename '用戶名'@'主機' to '新用戶名'@'主機';
回收權限
reveke 權限 on 數據庫 from "用戶名"@"主機";
刪除用戶
drop user "用戶名"@"主機";
delete from user where user = "要刪除的用戶名";

每一個權限修改命令執行以後須要刷新權限
flush privileges;


數據庫設計

三範式
第一範式---列的原子性, 列不能拆分
第二範式---表必須有主鍵,非主鍵字段必須依賴主鍵,而不能只依賴於主鍵的一部分
第三範式---非主鍵字段必須直接依賴於主鍵,不能存在傳遞依賴A-->B-->C-->主鍵 傳遞依賴容易產生數據冗餘
範式必須同時知足 不知足就拆表

E-R實體關係模型
一對一 任何以訪添加字段表示兩張表關係均可以

一對多 須要在多的一方添加字段表示兩張表的關係

多對多 須要添加中間表,表中添加兩個字段,分別是兩張表的主鍵

 


數據庫主從配置

策略型服務器 負載均衡
主服務器存儲數據 從服務器用來備份
寫數據往主服務器寫 --> 寫到二進制日誌文件中 --> 從服務器讀取日誌文件數據保存在本地保持和主服務器數據一致 -|-|-|- 讀取數據時從 從服務器讀取 達到 讀寫分離 ,負載均衡,數據備份

主從配置的機制
數據庫備份
數據庫恢復
主服務器的配置文件mysqld.cnf 的 43 註釋掉 84行85行 不能註釋 84server-id 不能與從服務器同樣
從服務器配置文件mysqld.cnf 84行的log_bin註釋掉
把主服務器數據導入到從服務器中
建立一個同步帳戶slave
獲取主服務器的二進制配置文件信息
從服務器鏈接主服務器 開啓同步 start slave
查看同步狀態 show slave status /G;

 

 

 

 

 

 

 

 


命令行中sql語句必需要以分號結尾,來表示語句結束

ctrl+a 行首
ctrl+e 行尾
數據庫引擎 InnoDB支持事務.行級鎖, MyISM 不支持

添加字段(列名) ALTER TABLE people ADD COLUMN name VARCHAR(100) DEFAULT NULL COMMENT '姓名'

相關文章
相關標籤/搜索