您好!此筆記的文本和代碼以網盤形式分享於文末!
因個人能力有限,錯誤處歡迎大家交流和指正!基礎部分內容簡單,但多且零散!
"""
數據庫 是一個可以在一臺機器上獨立工作的,並且可以給我們提供高效、
便捷的方式對數據進行增刪改查的一種工具
數據庫的優勢:
1.程序穩定性:這樣任意一臺服務所在的機器崩潰了都不會影響數據和另外的服務。
2.數據一致性:所有的數據都存儲在一起,所有的程序操作的數據都是統一的,
就不會出現數據不一致的現象
3.併發:數據庫可以良好的支持併發,所有的程序操作數據庫都是通過網絡,
而數據庫本身支持併發的網絡操作,不需要我們自己寫socket
4.效率:使用數據庫對數據進行增刪改查的效率要高出我們自己處理文件很多。
描述事物的符號記錄稱爲數據,數據庫即存放數據的倉庫;
數據庫是長期存放在計算機內、有組織、可共享的數據集合。
數據庫中的數據按一定的數據模型組織、描述和儲存,
具有較小的冗餘度、較高的數據獨立性和易擴展性,並可爲各種 用戶共享
科學地組織和存儲數據,如何高效獲取和維護數據成了關鍵--系統軟件---數據庫管理系統:
如mysql、oracle、PostgreSQL、SQL Server
數據庫服務器、數據管理系統、數據庫、表與記錄的關係(重點):
記錄:1 朱葛 13234567890 22(多個字段的信息組成一條記錄,即文件中的一行內容)
表:userinfo,studentinfo,courseinfo(即文件)
數據庫:db(即文件夾)
數據庫管理系統:如mysql(是一個軟件)
數據庫服務器:一臺計算機(對內存要求比較高)
總結:
數據庫服務器-:運行數據庫管理軟件
數據庫管理軟件:管理-數據庫
數據庫:即文件夾,用來組織文件/表
表:即文件,用來存放多行內容/多條記錄
數據庫系統的特點:
1 數據結構化(如上圖odboy_stu)
2 數據共享,冗餘度低,易擴充
3 數據獨立性高
4 數據由DBMS統一管理和控制
a:數據的安全性保護
b:數據的完整性檢查
c:併發控制
d:數據庫恢復
"""
"""
MySQL
關係型數據庫需要有表結構,非關係型數據庫是key-value存儲的,沒有表結構
關係型:如sqllite,db2,oracle,access,sql server,MySQL,
注意:sql語句通用
非關係型:mongodb,redis,memcache
MySQL是一個關係型數據庫管理系統,在 WEB 應用方面,MySQL是最好的 RDBMS ,
mysql的安裝、啓動和下載
# mysql的賬號操作
#進入mysql客戶端
$mysql
mysql> select user(); #查看當前用戶
mysql> exit # 也可以用\q quit退出
# 默認用戶登陸之後並沒有實際操作的權限
# 需要使用管理員root用戶登陸
$ mysql -uroot -p # mysql5.6默認是沒有密碼的
#遇到password直接按回車鍵
mysql> set password = password('root'); # 給當前數據庫設置密碼
# 創建賬號
mysql> create user 'eva'@'192.168.10.%' IDENTIFIED BY '123';# 指示網段
mysql> create user 'eva'@'192.168.10.5' # 指示某機器可以連接
mysql> create user 'eva'@'%' #指示所有機器都可以連接
mysql> show grants for 'eva'@'192.168.10.5';查看某個用戶的權限
# 遠程登陸
$ mysql -uroot -p123 -h 192.168.10.3
# 給賬號授權
mysql> grant all on *.* to 'eva'@'%';
mysql> flush privileges; # 刷新使授權立即生效
# 創建賬號並授權
mysql> grant all on *.* to 'eva'@'%' identified by '123'
SQL : 結構化查詢語言
SQL語言主要用於存取數據、查詢數據、更新數據和管理關係數據庫系統.
1、DDL語句 數據庫定義語言: 數據庫、表、視圖、索引、存儲過程,
例如CREATE DROP ALTER
2、DML語句 數據庫操縱語言: 插入數據INSERT、刪除數據DELETE、
更新數據UPDATE、查詢數據SELECT
3、DCL語句 數據庫控制語言: 例如控制用戶的訪問權限GRANT、REVOKE
1. 操作文件夾(庫)
增:create database db1 charset utf8;
查:show databases;
改:alter database db1 charset latin1;
刪除: drop database db1;
2. 操作文件(表)
先切換到文件夾下:use db1
增:create table t1(id int,name char);
查:show tables;
改:alter table t1 modify name char(3);
alter table t1 change name name1 char(2);
刪:drop table t1;
3. 操作文件中的內容(記錄)
增:insert into t1 values(1,'egon1'),(2,'egon2'),(3,'egon3');
查:select * from t1;
改:update t1 set name='sb' where id=2;
刪:delete from t1 where id=1;
清空表:
delete from t1; #如果有自增id,新增的數據,
仍然是以刪除前的最後一樣作爲起始。
truncate table t1;數據量大,刪除速度比上一條快,且直接從零開始.
*auto_increment 表示:自增
*primary key 表示:約束(不能重複且不能爲空);加速查找
"""
"""
mysql中的存儲引擎
mysql5.6支持的存儲引擎包括InnoDB、MyISAM、MEMORY、CSV、BLACKHOLE、
FEDERATED、MRG_MYISAM、ARCHIVE、PERFORMANCE_SCHEMA。
其中NDB和InnoDB提供事務安全表
常用存儲引擎及適用場景
InnoDB
用於事務處理應用程序,支持外鍵和行級鎖。
有效的降低由刪除和更新導致的鎖定,還可以確保事務的完整提交和回滾.
MyISAM
如果應用是以讀操作和插入操作爲主,只有很少的更新和刪除操作,
並且對事務的完整性、併發性要求不高,那麼可以選擇這個存儲引擎。
MyISAM
如果應用是以讀操作和插入操作爲主,只有很少的更新和刪除操作,
並且對事務的完整性、併發性要求不高,那麼可以選擇這個存儲引擎。
# 查看當前的默認存儲引擎:
#
# mysql> show variables like "default_storage_engine";
#
# 查詢當前數據庫支持的存儲引擎
#
# mysql> show engines \G;
指定存儲引擎建表
1、在建表時指定
mysql> create table ai(id bigint(12),name varchar(200)) ENGINE=MyISAM;
mysql> create table country(id int(4),cname varchar(50)) ENGINE=InnoDB;
也可以使用alter table語句,修改一個已經存在的表的存儲引擎。
mysql> alter table ai engine = innodb;
2、在配置文件中指定
#my.ini文件
[mysqld]
default-storage-engine=INNODB
MySQL架構總共四層
1、最上層:授權認證安全;最上層的服務並不是MySQL獨有的,
如:連接處理、授權認證、安全等。
2、第二層:查詢解析、分析、優化、緩存以及所有的內置函數,包括大多數的MySQL的核心服務。
如:日期、時間、數學和加密函數,
所有的跨存儲引擎的功能都在這一層實現:存儲過程、觸發器、視圖等
3、第三層:數據的存儲和提取,包含了存儲引擎,
4、第四層:存儲數據、表信息、用戶操作日誌,包含了文件系統。
"""
"""
mysql支持的數據類型:
# MySQL支持所有標準SQL數值數據類型
嚴格數值數據類型(INTEGER、SMALLINT、DECIMAL和NUMERIC),
以及近似數值數據類型(FLOAT、REAL和DOUBLE PRECISION)
關鍵字INT是INTEGER的同義詞,關鍵字DEC是DECIMAL的同義詞。
# int整數示例
# 創建表一個是默認寬度的int,一個是指定寬度的int(5)
mysql> create table t1 (id1 int,id2 int(5));
Query OK, 0 rows affected (0.02 sec)
# 像t1中插入數據1,1
mysql> insert into t1 values (1,1);
Query OK, 1 row affected (0.01 sec)
# 可以看出結果上並沒有異常
mysql> select * from t1;
+------+------+
| id1 | id2 |
+------+------+
| 1 | 1 |
+------+------+
1 row in set (0.00 sec)
# 那麼當我們插入了比寬度更大的值,會不會發生報錯呢?
mysql> insert into t1 values (111111,111111);
Query OK, 1 row affected (0.00 sec)
# 答案是否定的,id2仍然顯示了正確的數值,沒有受到寬度限制的影響
mysql> select * from t1;
+------------+--------+
| id1 | id2 |
+------------+--------+
| 0000000001 | 00001 |
| 0000111111 | 111111 |
+------------+--------+
2 rows in set (0.00 sec)
# 修改id1字段 給字段添加一個unsigned表示無符號
mysql> alter table t1 modify id1 int unsigned;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc t1;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id1 | int(10) unsigned | YES | | NULL | |
| id2 | int(5) | YES | | NULL | |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
# 當給id1添加的數據大於214748364時,可以順利插入
mysql> insert into t1 values (2147483648,2147483647);
Query OK, 1 row affected (0.00 sec)
# 當給id2添加的數據大於214748364時,會報錯
mysql> insert into t1 values (2147483647,2147483648);
ERROR 1264 (22003): Out of range value for column 'id2' at row 1
# 小數示例
# 創建表的三個字段分別爲float,double和decimal參數表示一共顯示5位,小數部分佔2位
mysql> create table t2 (id1 float(5,2),id2 double(5,2),id3 decimal(5,2));
Query OK, 0 rows affected (0.02 sec)
# 向表中插入1.23,結果正常
mysql> insert into t2 values (1.23,1.23,1.23);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
+------+------+------+
1 row in set (0.00 sec)
# 向表中插入1.234,會發現4都被截斷了
mysql> insert into t2 values (1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
| 1.23 | 1.23 | 1.23 |
+------+------+------+
2 rows in set (0.00 sec)
# 向表中插入1.235發現數據雖然被截斷,但是遵循了四捨五入的規則
mysql> insert into t2 values (1.235,1.235,1.235);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
| 1.23 | 1.23 | 1.23 |
| 1.24 | 1.24 | 1.24 |
+------+------+------+
3 rows in set (0.00 sec)
# 建新表去掉參數約束
mysql> create table t3 (id1 float,id2 double,id3 decimal);
Query OK, 0 rows affected (0.02 sec)
# 分別插入1.234
mysql> insert into t3 values (1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.00 sec)
# 發現decimal默認值是(10,0)的整數
mysql> select * from t3;
+-------+-------+------+
| id1 | id2 | id3 |
+-------+-------+------+
| 1.234 | 1.234 | 1 |
+-------+-------+------+
1 row in set (0.00 sec)
# 當對小數位沒有約束的時候,輸入超長的小數,會發現float和double的區別
mysql> insert into t3 values (1.2355555555555555555,1.2355555555555555555,1.2355555555555555555555);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from t3;
+---------+--------------------+------+
| id1 | id2 | id3 |
+---------+--------------------+------+
| 1.234 | 1.234 | 1 |
| 1.23556 | 1.2355555555555555 | 1 |
+---------+--------------------+------+
2 rows in set (0.00 sec)
# # 日期和時間類型
表示時間值的日期和時間類型爲DATETIME、DATE、TIMESTAMP、TIME和YEAR。
# # 字符串類型
字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。
CHAR 和 VARCHAR 類型類似,但它們保存和檢索的方式不同
在存儲或檢索過程中不進行大小寫轉換
# # ENUM和SET類型
ENUM中文名稱叫枚舉類型,它的值範圍需要在創建表時通過枚舉方式顯示。
ENUM只允許從值集合中選取單個值,而不能一次取多個值。
set類型可以允許值集合中任意選擇1或多個元素進行組合。
# # mysql表的完整性約束
# NOT NULL :非空約束,指定某列不能爲空;
# UNIQUE : 唯一約束,指定某列或者幾列組合不能重複
# PRIMARY KEY :主鍵,指定該列的值可以唯一地標識該列記錄
# FOREIGN KEY :外鍵,指定該行記錄從屬於主表中的一條記錄,主要用於參照完整性
"""
"""
表介紹
表就相當於文件,表中的一條記錄就相當於文件的一行內容,不同的是,
表中的一條記錄有對應的標題,稱爲表的字段
#語法:
create table 表名(
字段名1 類型[(寬度) 約束條件],
字段名2 類型[(寬度) 約束條件],
字段名3 類型[(寬度) 約束條件]
);
#注意:
1. 在同一張表中,字段名是不能相同
2. 寬度和約束條件可選
3. 字段名和類型是必須的
# 建表
create database staff;
use staff;
create table staff_info (id int,name varchar(50),age int(3),sex enum('male','female'),phone bigint(11),job varchar(11));
show tables;
desc staff_info;
select id,name,sex from staff_info;
select * from staff_info;
# 插入數據
insert into staff_info (id,name,age,sex,phone,job) values (1,'Alex',83,'female',13651054608,'IT');
insert into staff_info values (2,'Egon',26,'male',13304320533,'Teacher');
insert into staff_info values (3,'nezha',25,'male',13332353222,'IT'),(4,'boss_jin',40,'male',13332353333,'IT');
select * from staff_info;
# 查看錶結構
describe [tablename];這種方法和desc [tablename];
describe staff_info;
desc staff_info;
show create table staff_info\G;
# 表的數據類型
# 表的完整性約束
# 修改表的結構
語法:
1. 修改表名
ALTER TABLE 表名
RENAME 新表名;
2. 增加字段
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…],
ADD 字段名 數據類型 [完整性約束條件…];
3. 刪除字段
ALTER TABLE 表名
DROP 字段名;
4. 修改字段
ALTER TABLE 表名
MODIFY 字段名 數據類型 [完整性約束條件…];
ALTER TABLE 表名
CHANGE 舊字段名 新字段名 舊數據類型 [完整性約束條件…];
ALTER TABLE 表名
CHANGE 舊字段名 新字段名 新數據類型 [完整性約束條件…];
5.修改字段排列順序/在增加的時候指定字段位置
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…] FIRST;
ALTER TABLE 表名
ADD 字段名 數據類型 [完整性約束條件…] AFTER 字段名;
ALTER TABLE 表名
CHANGE 字段名 舊字段名 新字段名 新數據類型 [完整性約束條件…] FIRST;
ALTER TABLE 表名
MODIFY 字段名 數據類型 [完整性約束條件…] AFTER 字段名;
# alter操作非空和唯一
create table t(id int unique,name char(10) not null);
#去掉null約束
alter table t modify name char(10) null;
# 添加null約束
alter table t modify name char(10) not null;
# 去掉unique約束
alter table t drop index id;
# 添加unique約束
alter table t modify id int unique;
alter處理null和unique約束
# # alter操作主鍵
1、首先創建一個數據表table_test:
create table table_test(
`id` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`name`)
);
2、如果發現主鍵設置錯了,應該是id是主鍵,但如今表裏已經有好多數據了,
不能刪除表再重建了,僅僅能在這基礎上改動表結構。
先刪除主鍵
alter table table_test drop primary key;
然後再增加主鍵
alter table table_test add primary key(id);
注:在增加主鍵之前,必須先把反覆的id刪除掉。
# # 爲表添加外鍵
創建press表
CREATE TABLE `press` (
`id` int(11) NOT NULL,
`name` char(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ;
創建book表
CREATE TABLE `book` (
`id` int(11) DEFAULT NULL,
`bk_name` char(12) DEFAULT NULL,
`press_id` int(11) NOT NULL,
KEY `press_id` (`press_id`)
) ;
爲book表添加外鍵
alter table book add constraint fk_id foreign key(press_id) references press(id);
刪除外鍵
alter table book drop foreign key fk_id;
# # 小示例
# 表重命名
alter table staff_info rename staff;
desc staff;
# 刪除sex列
alter table staff drop sex;
desc staff;
# 添加列
alter table staff add sex enum('male','female');
# 修改id的寬度
alter table staff modify id int(4);
desc staff;
# 修改name列的字段名
alter table staff change name sname varchar(20);
desc staff;
# 修改sex列的位置
alter table staff modify sex enum('male','female') after sname;
desc staff;
# 創建自增id主鍵
alter table staff modify id int(4) primary key auto_increment;
desc staff;
# 刪除主鍵,可以看到刪除一個自增主鍵會報錯
alter table staff drop primary key;
# 需要先去掉主鍵的自增約束,然後再刪除主鍵約束
alter table staff modify id int(11);
desc staff;
alter table staff drop primary key;
# 添加聯合主鍵
alter table staff add primary key (sname,age);
# 刪除主鍵
alter table staff drop primary key;
# 創建主鍵id
alter table staff add primary key (id);
desc staff;
# 爲主鍵添加自增屬性
alter table staff modify id int(4) auto_increment;
desc staff;
# # 刪除表
DROP TABLE 表名;
"""
"""
多表結構的創建與分析
# 尋找兩張表之間的關係
分析步驟:
#1、先站在左表的角度去找
是否左表的多條記錄可以對應右表的一條記錄,如果是,
則證明左表的一個字段foreign key 右表一個字段(通常是id)
#2、再站在右表的角度去找
是否右表的多條記錄可以對應左表的一條記錄,如果是,
則證明右表的一個字段foreign key 左表一個字段(通常是id)
#3、總結:
#多對一:
如果只有步驟1成立,則是左表多對一右表
如果只有步驟2成立,則是右表多對一左表
#多對多
如果步驟1和2同時成立,則證明這兩張表時一個雙向的多對一,
即多對多,需要定義一個這兩張表的關係表來專門存放二者的關係
#一對一:
如果1和2都不成立,而是左表的一條記錄唯一對應右表的一條記錄,反之亦然。
這種情況很簡單,就是在左表foreign key右表的基礎上,
將左表的外鍵字段設置成unique即可
建立表之間的聯繫 關聯方式:foreign key
=====================多對一=====================
# 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)
# ;
=====================多對多=====================
關聯方式:foreign key+一張新的表
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');
#每個作者與自己的代表作如下
egon:
九陽神功
九陰真經
九陰白骨爪
獨孤九劍
降龍十巴掌
葵花寶典
alex:
九陽神功
葵花寶典
yuanhao:
獨孤九劍
降龍十巴掌
葵花寶典
wpq:
九陽神功
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)
;
=====================一對一=====================
關聯方式:foreign key+unique
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
-> );
#增加客戶
mysql> insert into customer(name,qq,phone) values
-> ('韓蕾','31811231',13811341220),
-> ('楊瀾','123123123',15213146809),
-> ('翁惠天','283818181',1867141331),
-> ('楊宗河','283818181',1851143312),
-> ('袁承明','888818181',1861243314),
-> ('袁清','112312312',18811431230)
mysql> #增加學生
mysql> insert into student(class_name,customer_id) values
-> ('脫產1班',3),
-> ('週末1期',4),
-> ('週末1期',5)
-> ;
"""
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
記錄操作
MySQL數據操作: DML
在MySQL管理軟件中,可以通過SQL語句中的DML語言來實現數據的操作,包括
1、使用INSERT實現數據的插入
2、UPDATE實現數據的更新
3、使用DELETE實現數據的刪除
4、使用SELECT查詢數據以及。
"""
"""
# 插入數據
1. 插入完整數據(順序插入)
語法一:
INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n);
語法二:
INSERT INTO 表名 VALUES (值1,值2,值3…值n);
2. 指定字段插入數據
語法:
INSERT INTO 表名(字段1,字段2,字段3…) VALUES (值1,值2,值3…);
3. 插入多條記錄
語法:
INSERT INTO 表名 VALUES
(值1,值2,值3…值n),
(值1,值2,值3…值n),
(值1,值2,值3…值n);
4. 插入查詢結果
語法:
INSERT INTO 表名(字段1,字段2,字段3…字段n)
SELECT (字段1,字段2,字段3…字段n) FROM 表2
WHERE …;
# 更新數據update
語法:
UPDATE 表名 SET
字段1=值1,
字段2=值2,
WHERE CONDITION;
示例:
UPDATE mysql.user SET password=password(‘123’)
where user=’root’ and host=’localhost’;
# 刪除數據delete
語法:
DELETE FROM 表名
WHERE CONITION;
示例:
DELETE FROM mysql.user
WHERE password=’’;
練習:
更新MySQL root用戶密碼爲mysql123
刪除除從本地登錄的root用戶以外的所有用戶
"""
"""
查詢數據 search
# 單表查詢
語法:
SELECT DISTINCT 字段1,字段2... FROM 表名
WHERE 條件
GROUP BY field
HAVING 篩選
ORDER BY field
LIMIT 限制條數
關鍵字執行的優先級
from :找到表:from
where :拿着where指定的約束條件,去文件/表中取出一條條記錄
group by :將取出的一條條記錄進行分組group by,如果沒有group by,則整體作爲一組
select :執行select(去重)
distinct :
having :將分組的結果進行having過濾
order by :將結果按條件排序:order by
limit :限制結果的顯示條數
# 簡單查詢:
1、建表
2、簡單查詢
#簡單查詢
SELECT id,emp_name,sex,age,hire_date,post,post_comment,salary,office,depart_id
FROM employee;
SELECT * FROM employee;
SELECT emp_name,salary FROM employee;
#避免重複DISTINCT
SELECT DISTINCT post FROM employee;
#通過四則運算查詢
SELECT emp_name, salary*12 FROM employee;
SELECT emp_name, salary*12 AS Annual_salary FROM employee;
SELECT emp_name, salary*12 Annual_salary FROM employee;
#定義顯示格式
CONCAT() 函數用於連接字符串
SELECT CONCAT('姓名: ',emp_name,' 年薪: ', salary*12) AS Annual_salary
FROM employee;
CONCAT_WS() 第一個參數爲分隔符
SELECT CONCAT_WS(':',emp_name,salary*12) AS Annual_salary
FROM employee;
結合CASE語句:
SELECT
(
CASE
WHEN emp_name = 'jingliyang' THEN
emp_name
WHEN emp_name = 'alex' THEN
CONCAT(emp_name,'_BIGSB')
ELSE
concat(emp_name, 'SB')
END
) as new_name
FROM
employee;
# where約束
1. 比較運算符:> < >= <= <> !=
2. between 80 and 100 值在80到100之間
3. in(80,90,100) 值是80或90或100
4. like 'e%'
通配符可以是%或_,
%表示任意多字符
_表示一個字符
5. 邏輯運算符:在多個條件直接可以使用邏輯運算符 and or not
#1:單條件查詢
SELECT emp_name FROM employee
WHERE post='sale';
#2:多條件查詢
SELECT emp_name,salary FROM employee
WHERE post='teacher' AND salary>10000;
#3:關鍵字BETWEEN AND
SELECT emp_name,salary FROM employee
WHERE salary BETWEEN 10000 AND 20000;
SELECT emp_name,salary FROM employee
WHERE salary NOT BETWEEN 10000 AND 20000;
#4:關鍵字IS NULL(判斷某個字段是否爲NULL不能用等號,需要用IS)
SELECT emp_name,post_comment FROM employee
WHERE post_comment IS NULL;
SELECT emp_name,post_comment FROM employee
WHERE post_comment IS NOT NULL;
SELECT emp_name,post_comment FROM employee
WHERE post_comment=''; 注意''是空字符串,不是null
ps:
執行
update employee set post_comment='' where id=2;
再用上條查看,就會有結果了
#5:關鍵字IN集合查詢
SELECT emp_name,salary FROM employee
WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
SELECT emp_name,salary FROM employee
WHERE salary IN (3000,3500,4000,9000) ;
SELECT emp_name,salary FROM employee
WHERE salary NOT IN (3000,3500,4000,9000) ;
#6:關鍵字LIKE模糊查詢
通配符’%’
SELECT * FROM employee
WHERE emp_name LIKE 'eg%';
通配符’_’
SELECT * FROM employee
WHERE emp_name LIKE 'al__';
# group by
單獨使用GROUP BY關鍵字分組
SELECT post FROM employee GROUP BY post;
注意:我們按照post字段分組,那麼select查詢的字段只能是post,想要獲取組內的其他相關信息,需要藉助函數
GROUP BY關鍵字和GROUP_CONCAT()函數一起使用
SELECT post,GROUP_CONCAT(emp_name) FROM employee GROUP BY post;#按照崗位分組,並查看組內成員名
SELECT post,GROUP_CONCAT(emp_name) as emp_members FROM employee GROUP BY post;
GROUP BY與聚合函數一起使用
# 按照崗位分組,並查看每個組有多少人
select post,count(id) as count from employee group by post;
# 聚合函數
#強調:聚合函數聚合的是組的內容,若是沒有分組,則默認一組
示例:
SELECT COUNT(*) FROM employee;
SELECT COUNT(*) FROM employee WHERE depart_id=1;
SELECT MAX(salary) FROM employee;
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過濾
執行優先級從高到低:where > group by > having
#1. Where 發生在分組group by之前,因而Where中可以有任意字段,但是絕對不能使用聚合函數。
#2. Having發生在分組group by之後,因而Having中可以使用分組的字段,
無法直接取到其他字段,可以使用聚合函數
# 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條
# 使用正則表達式查詢
SELECT * FROM employee WHERE emp_name REGEXP '^ale';
SELECT * FROM employee WHERE emp_name REGEXP 'on$';
SELECT * FROM employee WHERE emp_name REGEXP 'm{2}';
小結:對字符串匹配的方式
WHERE emp_name = 'egon';
WHERE emp_name LIKE 'yua%';
WHERE emp_name REGEXP 'on$';
"""
"""
1、建表
# 多表連接查詢
#重點:外鏈接語法
SELECT 字段列表
FROM 表1 INNER|LEFT|RIGHT JOIN 表2
ON 表1.字段 = 表2.字段;
1 交叉連接:不適用任何匹配條件。生成笛卡爾積
select * from employee,department;
2 內連接:只連接匹配的行
#找兩張表共有的部分,相當於利用條件從笛卡爾積結果中篩選出了正確的結果
#department沒有204這個部門,因而employee表中關於204這條員工信息沒有匹配出來
select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id;
或
select employee.id,employee.name,employee.age,employee.sex,department.name from employee,department where employee.dep_id=department.id;
3 外鏈接之左連接:優先顯示左表全部記錄
#以左表爲準,即找出所有員工信息,當然包括沒有部門的員工
#本質就是:在內連接的基礎上增加左邊有右邊沒有的結果
select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
4 外鏈接之右連接:優先顯示右表全部記
#以右表爲準,即找出所有部門信息,包括沒有員工的部門
#本質就是:在內連接的基礎上增加右邊有左邊沒有的結果
select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
5 全外連接:顯示左右兩個表全部記錄
全外連接:在內連接的基礎上增加左邊有右邊沒有的和右邊有左邊沒有的結果
#注意: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;
# # 子查詢
#1:子查詢是將一個查詢語句嵌套在另一個查詢語句中。
#2:內層查詢語句的查詢結果,可以爲外層查詢語句提供查詢條件。
#3:子查詢中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字
#4:還可以包含比較運算符:= 、 !=、> 、<等
1 帶IN關鍵字的子查詢
#查詢平均年齡在25歲以上的部門名
select id,name from department
where id in
(select dep_id from employee group by dep_id having avg(age) > 25);
#查看技術部員工姓名
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);
2 帶比較運算符的子查詢
#比較運算符:=、!=、>、>=、<、<=、<>
#查詢大於所有人平均年齡的員工名與年齡
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;
3 帶EXISTS關鍵字的子查詢
EXISTS關字鍵字表示存在,
"""
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
索引
索引在MySQL中也叫是一種“鍵”,是存儲引擎用於快速找到記錄的一種數據結構。
索引優化應該是對查詢性能優化最有效的手段了。索引能夠輕易將查詢性能提高好幾個數量級。
一 索引的目的在於提高查詢效率,通過不斷地縮小想要獲取數據的範圍來篩選出最終想要的結果,
同時把隨機的事件變成順序的事件,也就是說,有了這種索引機制,
我們可以總是用同一種查找方式來鎖定數據。
數據庫:等值查詢、範圍查詢(>、<、between、in)、模糊查詢(like)、並集查詢(or)
二、磁盤IO與預讀
當一次IO時,不光把當前磁盤地址的數據,而是把相鄰的數據也都讀取到內存緩衝區內。
每一次IO讀取的數據我們稱之爲一頁(page)
三 索引的數據結構
樹狀圖是一種數據結構,它是由n(n>=1)個有限結點組成一個具有層次關係的集合
樹狀圖特點:
每個結點有零個或多個子結點;沒有父結點的結點稱爲根結點;
每一個非根結點有且只有一個父結點;除了根結點外,每個子結點可以分爲多個不相交的子樹
B+樹 :B+樹是通過二叉查找樹,再由平衡二叉樹,B樹演化而來
1.索引字段要儘量的小:
2.索引的最左匹配特性:
四 聚集索引與輔助索引
在數據庫中,B+樹的高度一般都在2~4層,這也就是說查找某一個鍵值的行記錄時最多隻需要2到4次IO。
數據庫中的B+樹索引可以分爲聚集索引(clustered index)和輔助索引(secondary index)
聚集索引與輔助索引相同的是:不管是聚集索引還是輔助索引,其內部都是B+樹的形式,
即高度是平衡的,葉子結點存放着所有的數據。
聚集索引與輔助索引不同的是:葉子結點存放的是否是一整行的信息
1、聚集索引
InnoDB存儲引擎表是索引組織表,即表中數據按照主鍵順序存放。
聚集索引(clustered index)就是按照每張表的主鍵構造一棵B+樹,
同時葉子結點存放的即爲整張表的行記錄數據,也將聚集索引的葉子結點稱爲數據頁。
同B+樹數據結構一樣,每個數據頁都通過一個雙向鏈表來進行鏈接。
如果未定義主鍵,MySQL取第一個唯一索引(unique)而且只含非空列(NOT NULL)作爲主鍵,
InnoDB使用它作爲聚簇索引。
如果沒有這樣的列,InnoDB就自己產生一個這樣的ID值,它有六個字節,
而且是隱藏的,使其作爲聚簇索引。
由於實際的數據頁只能按照一棵B+樹進行排序,因此每張表只能擁有一個聚集索引。
聚集索引的好處之一:它對主鍵的排序查找和範圍查找速度非常快,
葉子節點的數據就是用戶所要查詢的數據
聚集索引的好處之二:範圍查詢(range query),即如果要查找主鍵某一範圍內的數據,
通過葉子節點的上層中間節點就可以得到頁的範圍,之後直接讀取數據頁即可
2、輔助索引
輔助索引的葉子節點不包含行記錄的全部數據。
節點除了包含鍵值以外,每個葉子節點中的索引行中還包含一個書籤。
書籤用來告訴InnoDB存儲引擎去哪裏可以找到與索引相對應的行數據。
輔助索引的存在並不影響數據在聚集索引中的組織,
因此每張表上可以有多個輔助索引,但只能有一個聚集索引。
聚集索引
1.紀錄的索引順序與無力順序相同
因此更適合between and和order by操作
2.葉子結點直接對應數據
從中間級的索引頁的索引行直接對應數據頁
3.每張表只能創建一個聚集索引
非聚集索引
1.索引順序和物理順序無關
2.葉子結點不直接指向數據頁
3.每張表可以有多個非聚集索引,需要更多磁盤和內容
多個索引會影響insert和update的速度
五 MySQL索引管理
# # 功能
#1. 索引的功能就是加速查找
#2. mysql中的primary key,unique,
聯合唯一也都是索引,這些索引除了加速查找以外,還有約束的功能
# # MySQL常用的索引
普通索引INDEX:加速查找
唯一索引:
-主鍵索引PRIMARY KEY:加速查找+約束(不爲空、不能重複)
-唯一索引UNIQUE:加速查找+約束(不能重複)
聯合索引:
-PRIMARY KEY(id,name):聯合主鍵索引
-UNIQUE(id,name):聯合唯一索引
-INDEX(id,name):聯合普通索引
# # 索引的兩大類型hash與btree
#我們可以在創建上述索引的時候,爲其指定索引類型,分兩類
hash類型的索引:查詢單條快,範圍查詢慢
btree類型的索引:b+樹,層數越多,數據量指數級增長(我們就用它,因爲innodb默認支持它)
#不同的存儲引擎支持的索引類型也不一樣
InnoDB 支持事務,支持行級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
MyISAM 不支持事務,支持表級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
Memory 不支持事務,支持表級別鎖定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;
NDB 支持事務,支持行級別鎖定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;
Archive 不支持事務,支持表級別鎖定,不支持 B-tree、Hash、Full-text 等索引;
# # 創建/刪除索引的語法
#方法一:創建表時
CREATE TABLE 表名 (
字段名1 數據類型 [完整性約束條件…],
字段名2 數據類型 [完整性約束條件…],
[UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY
[索引名] (字段名[(長度)] [ASC |DESC])
);
#方法二:CREATE在已存在的表上創建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名
ON 表名 (字段名[(長度)] [ASC |DESC]) ;
#方法三:ALTER TABLE在已存在的表上創建索引
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX
索引名 (字段名[(長度)] [ASC |DESC]) ;
#刪除索引:DROP INDEX 索引名 ON 表名字;
#方式一
create table t1(
id int,
name char,
age int,
sex enum('male','female'),
unique key uni_id(id),
index ix_name(name) #index沒有key
);
create table t1(
id int,
name char,
age int,
sex enum('male','female'),
unique key uni_id(id),
index(name) #index沒有key
);
#方式二
create index ix_age on t1(age);
#方式三
alter table t1 add index ix_sex(sex);
alter table t1 add index(sex);
#查看
mysql> show create table t1;
| t1 | CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`name` char(1) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` enum('male','female') DEFAULT NULL,
UNIQUE KEY `uni_id` (`id`),
KEY `ix_name` (`name`),
KEY `ix_age` (`age`),
KEY `ix_sex` (`sex`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
六 測試索引
1、準備數據
2、在沒有索引的前提下測試查詢速度
select * from s1 where id=333333333;
3、在表中已經存在大量數據的前提下,爲某個字段段建立索引,建立速度會很慢
create index a on s1<id>;
4、在索引建立完畢後,以該字段爲查詢條件時,查詢速度提升明顯
select * from s1 where id=333333333;
總結:
1. 一定是爲搜索條件的字段創建索引,
比如select * from s1 where id = 333;就需要爲id加上索引
2. 在表中已經有大量數據的情況下,建索引會很慢,且佔用硬盤空間,建完後查詢速度加快。
3. 需要注意的是:innodb表的索引會存放於s1.ibd文件中,
而myisam表的索引則會有單獨的索引文件table1.MYI
MySAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。
而在innodb中,表數據文件本身就是按照B+Tree組織的一個索引結構,
這棵樹的葉節點data域保存了完整的數據記錄
七 正確使用索引
# # 索引未命中,若想利用索引達到預想的提高查詢速度的效果,我們在添加索引時,必須遵循以下問題:
1 範圍問題,或者說條件不明確,條件中出現這些符號或關鍵字:>、>=、<、<=、!= 、
between...and...、like、
2 儘量選擇區分度高的列作爲索引,區分度的公式是count(distinct col)/count(*),
表示字段不重複的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,
3 索引列不能在條件中參與計算,保持列“乾淨”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,
原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。
4 and/or
and與or的邏輯
條件1 and 條件2:所有條件都成立纔算成立,但凡要有一個條件不成立則最終結果不成立
條件1 or 條件2:只要有一個條件成立則最終結果就成立
對於連續多個and:mysql會按照聯合索引,從左到右的順序找一個區分度高的索引字段
對於連續多個or:mysql會按照條件的順序,從左到右依次判斷
5 最左前綴匹配原則,非常重要的原則,對於組合索引mysql會一直向右匹配直到遇到範圍查詢就停止匹配,
6
- 使用函數
select * from tb1 where reverse(email) = 'egon';
- 類型不一致
如果列是字符串類型,傳入條件是必須用引號引起來,不然...
select * from tb1 where email = 999;
#排序條件爲索引,則select字段必須也是索引字段,否則無法命中
- order by
select name from s1 order by email desc;
當根據索引排序時候,select查詢的字段如果不是索引,則速度仍然很慢
select email from s1 order by email desc;
特別的:如果對主鍵排序,則還是速度很快:
select * from tb1 order by nid desc;
- 組合索引最左前綴
如果組合索引爲:(name,email)
name and email -- 命中索引
name -- 命中索引
email -- 未命中索引
- count(1)或count(列)代替count(*)在mysql中沒有差別了
- create index xxxx on tb(title(19)) #text類型,必須制定長度
# # 其他注意事項
- 避免使用select *
- 使用count(*)
- 創建表時儘量使用 char 代替 varchar
- 表的字段順序固定長度的字段優先
- 組合索引代替多個單列索引(由於mysql中每次只能使用一個索引,所以經常使用多個條件查詢時更適合使用組合索引)
- 儘量使用短索引
- 使用連接(JOIN)來代替子查詢(Sub-Queries)
- 連表時注意條件類型需一致
- 索引散列值(重複少)不適合建索引,例:性別不適合
八 聯合索引與覆蓋索引
聯合索引是指對錶上的多個列合起來做一個索引。
創建聯合索引
mysql> create table t(
-> a int,
-> b int,
-> primary key(a),
-> key idx_a_b(a,b)
-> );
聯合索引的好處是在第一個鍵相同的情況下,已經對第二個鍵進行了排序處理
聯合索引舉例
# # 覆蓋索引
InnoDB存儲引擎支持覆蓋索引,
"""
願有更多的朋友,在網頁筆記結構上分享更邏輯和易讀的形式:
鏈接:暫無
提取碼:暫無