Python之路--Python基礎14--MySQL

1、數據庫介紹

一、數據庫是啥 

  數據庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫,每一個數據庫都有一個或多個不一樣的API用於建立,訪問,管理,搜索和複製所保存的數據。咱們也能夠將數據存儲在文件中,可是在文件中讀寫數據速度相對較html

慢。因此,如今咱們使用關係型數據庫管理系統(RDBMS)來存儲和管理的大數據量。所謂的關係型數據庫,是創建在關係模型基礎上的數據庫,藉助於集合代數等數學概念和方法來處理數據庫中的數據。java

RDBMS即關係數據庫管理系統(Relational Database Management System)的特色:
  1.數據以表格的形式出現
  2.每行爲,各類記錄名稱
  3.每列爲,記錄名稱所對應的數據域
  4.許多的行和列組成一張表單
  5.若干的表單組成databasepython

 

二、RDBMS術語

在咱們開始學習MySQL 數據庫前,讓咱們先了解下RDBMS的一些術語:mysql

  • 數據庫: 數據庫是一些關聯表的集合。.linux

  • 數據表: 表是數據的矩陣。在一個數據庫中的表看起來像一個簡單的電子表格。程序員

  • 列: 一列(數據元素) 包含了相同的數據, 例如郵政編碼的數據。web

  • 行:一行(=元組,或記錄)是一組相關的數據,例如一條用戶訂閱的數據。算法

  • 冗餘存儲兩倍數據,冗餘可使系統速度更快。(表的規範化程度越高,表與表之間的關係就越多;查詢時可能常常須要在多個表之間進行鏈接查詢;而進行鏈接操做會下降查詢速度。例如,學生的信息存儲在student表中,院系信息存儲在department表中。經過student表中的dept_id字段與department表創建關聯關係。若是要查詢一個學生所在系的名稱,必須從student表中查找學生所在院系的編號(dept_id),而後根據這個編號去department查找系的名稱。若是常常須要進行這個操做時,鏈接查詢會浪費不少的時間。所以能夠在student表中增長一個冗餘字段dept_name,該字段用來存儲學生所在院系的名稱。這樣就不用每次都進行鏈接操做了。)sql

  • 主鍵:主鍵是惟一的。一個數據表中只能包含一個主鍵。你可使用主鍵來查詢數據。數據庫

  • 外鍵:外鍵用於關聯兩個表。

  • 複合鍵:複合鍵(組合鍵)將多個列做爲一個索引鍵,通常用於複合索引。

  • 索引:使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構。相似於書籍的目錄。

  • 參照完整性: 參照的完整性要求關係中不容許引用不存在的實體。實體完整性是關係模型必須知足的完整性約束條件,目的是保證數據的一致性。

 

三、Mysql數據庫

  Mysql是最流行的關係型數據庫管理系統,在WEB應用方面MySQL是最好的RDBMS(Relational Database Management System:關係數據庫管理系統)應用軟件之一。由瑞典MySQL AB公司開發,目前屬於Oracle公司。MySQL是一種關聯數據庫管理系統,關聯數據庫將數據保存在不一樣的表中,而不是將全部數據放在一個大倉庫內,這樣就增長了速度並提升了靈活性。

  • Mysql是開源的,因此你不須要支付額外的費用。

  • Mysql支持大型的數據庫。能夠處理擁有上千萬條記錄的大型數據庫。

  • MySQL使用標準的SQL數據語言形式。

  • Mysql能夠容許於多個系統上,而且支持多種語言。這些編程語言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。

  • Mysql對PHP有很好的支持,PHP是目前最流行的Web開發語言。

  • MySQL支持大型數據庫,支持5000萬條記錄的數據倉庫,32位系統表文件最大可支持4GB,64位系統支持最大的表文件爲8TB。

  • Mysql是能夠定製的,採用了GPL協議,你能夠修改源碼來開發本身的Mysql系統。

 

想要使用MySQL來存儲並操做數據,則須要作幾件事情:
  a. 安裝MySQL服務端
  b. 安裝MySQL客戶端
  b. 【客戶端】鏈接【服務端】
  c. 【客戶端】發送命令給【服務端MySQL】服務的接受命令並執行相應操做(增刪改查等)

 

2、安裝MySQL

Windows安裝MySQL

一、安裝

MySQL Community Server 5.7.16
 
http://dev.mysql.com/downloads/mysql/

二、解壓

  若是想要讓MySQL安裝在指定目錄,那麼就將解壓後的文件夾移動到指定目錄,如:C:\mysql-5.7.16-winx64

三、初始化

  MySQL解壓後的 bin 目錄下有一大堆的可執行文件,執行以下命令初始化數據:

cd D:\mysql-5.7.16-winx64\bin mysqld --initialize-insecure

四、啓動MySQL服務

a.將MySQL可執行文件添加到環境變量中,從而執行執行命令便可

  【右鍵計算機】--》【屬性】--》【高級系統設置】--》【高級】--》【環境變量】--》【在第二個內容框中找到 變量名爲Path 的一行,雙擊】 --> 【將MySQL的bin目錄路徑追加到變值值中,用 ; 分割】

如此一來,之後再啓動服務並鏈接時,僅需

# 啓動MySQL服務,在終端輸入
mysqld # 鏈接MySQL服務,在終端輸入:
mysql -u root -p

b.將MySQL服務製做成windows服務

上一步解決了一些問題,但不夠完全,由於在執行【mysqd】啓動MySQL服務器時,當前終端會被hang住,那麼作一下設置便可解決此問題:

# 製做MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --install # 移除MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --remove

註冊成服務以後,之後再啓動和關閉MySQL服務時,僅需執行以下命令:

# 啓動MySQL服務
net start mysql # 關閉MySQL服務
net stop mysql

 

centos7安裝MySQL

1. 下載mysql的repo源

wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm

2. 安裝mysql-community-release-el7-5.noarch.rpm包

sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm

安裝這個包後,會得到兩個mysql的yum repo源:/etc/yum.repos.d/mysql-community.repo,/etc/yum.repos.d/mysql-community-source.repo。

3. 安裝mysql

sudo yum install mysql-server

4. 重置密碼

mysql -u root

登陸時有可能報這樣的錯:ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock‘ (2),緣由是/var/lib/mysql的訪問權限問題。下面的命令把/var/lib/mysql的擁有者改成當前用戶:

sudo chown -R openscanner:openscanner /var/lib/mysql

而後,重啓服務:

service mysqld restart
mysql -u root

接下來登陸重置密碼:

mysql > use mysql;
mysql > update user set password=password(‘1‘) where user=‘root‘;

5. 須要更改權限才能實現遠程鏈接MYSQL數據庫

mysql> select host, user, password from user;
+-----------+------+-------------------------------------------+
| host      | user | password                                  |
+-----------+------+-------------------------------------------+
| localhost | root | *4ACFE3202A5FF5CF467898FC58AAB1D615029441 |
| 127.0.0.1 | root | *4ACFE3202A5FF5CF467898FC58AAB1D615029441 |
| localhost |      |                                           |
+-----------+------+-------------------------------------------+
4 rows in set (0.01 sec)

由此能夠看出,只能以localhost的主機方式訪問MySQL。

解決方法:

mysql> Grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;  ( % 表示全部的IP均可以訪問 )
mysql> flush privileges;    (運行此句才生效,或者重啓MySQL)

再次查看:

mysql> select host, user, password from user;
+-----------+------+-------------------------------------------+
| host      | user | password                                 |
+-----------+------+-------------------------------------------+
| localhost | root | *4ACFE3202A5FF5CF467898FC58AAB1D615029441 |
| 127.0.0.1 | root | *4ACFE3202A5FF5CF467898FC58AAB1D615029441 |
| localhost |     |                                          |
| %        | root | *4ACFE3202A5FF5CF467898FC58AAB1D615029441 |
+-----------+------+-------------------------------------------+
4 rows in set (0.01 sec)

6. 遠程鏈接mysql

mysql -h 192.168.219.22 -u user -p

 

3、數據庫操做

管理MySQL的命令,如下列出了使用Mysql數據庫過程當中經常使用的命令:

  • use 數據庫名 :選擇要操做的Mysql數據庫,使用該命令後全部Mysql命令都只針對該數據庫。

  • show databases: 列出 MySQL 數據庫管理系統的數據庫列表。

  • show tables: 顯示指定數據庫的全部表,使用該命令前須要使用 use命令來選擇要操做的數據庫。

  • show columns from 數據表名: 顯示數據表的屬性,屬性類型,主鍵信息 ,是否爲 NULL,默認值等其餘信息。

  • create database testdb charset "utf8": #建立一個叫testdb的數據庫,且讓其支持中文 

  • drop database 數據庫名: #刪除數據庫

  • show index from 數據表名:顯示數據表的詳細索引信息,包括PRIMARY KEY(主鍵)。

 

一、顯示數據庫

SHOW DATABASES;

默認有的數據庫:

  • mysql   - 用戶權限相關數據
  • test       - 用於用戶測試數據
  • information_schema - MySQL自己架構相關數據

 

二、建立數據庫

# utf-8
CREATE DATABASE 數據庫名稱 DEFAULT CHARSET utf8 COLLATE utf8_general_ci; # gbk
CREATE DATABASE 數據庫名稱 DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;

 

三、使用數據庫

USE db_name;

顯示當前使用的數據庫中全部表:SHOW TABLES;

 

四、用戶管理

建立用戶 create user '用戶名'@'IP地址' identified by '密碼'; 刪除用戶 drop user '用戶名'@'IP地址'; 修改用戶 rename user '用戶名'@'IP地址'; to '新用戶名'@'IP地址';; 修改密碼 set password for '用戶名'@'IP地址' = Password('新密碼')

PS:用戶權限相關數據保存在mysql數據庫的user表中,因此也能夠直接對其進行操做(不建議

 

五、受權管理

show grants for '用戶'@'IP地址'                  -- 查看權限 grant 權限 on 數據庫.表 to '用戶'@'IP地址'      -- 受權 revoke 權限 on 數據庫.表 from '用戶'@'IP地址'      -- 取消權限
Grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;

 

4、數據表操做

一、建立表

create table 表名( 列名 類型 是否能夠爲空, 列名 類型 是否能夠爲空 )ENGINE=InnoDB DEFAULT CHARSET=utf8

數據庫引擎:

  • innodb:支持事務,原子性操做。(事務是一個原子操做單元,其對數據的修改,要麼全都執行,要麼全都不執行。)
  • myisam: 存儲速度快,支持全局索引

 

是否能夠爲空:

not null     - 不可空
null         - 可空,非字符串

 

默認值:

  建立列時,能夠指定默認值,當插入數據時,沒有主動設置,則自動添加默認值

create table tb1(
    nid int not null defalut 2,
    num int not null
)

 

自增:

  若是設置某列爲自增列,插入數據時無需設置此列數據,默認將自增(表中只能有一個自增列)

create table tb1(
    nid int not null auto_increment primary key,
    num int null
)

或

create table tb1(
    nid int not null auto_increment,
    num int null,
    index(nid)
)

注意:
    1、對於自增列,必須是索引(含主鍵)。
    2、對於自增能夠設置步長和起始值

基於會話的:
show session variables like 'auto_inc%';
set session auto_increment_increment=2;
set session auto_increment_offset=10;

基於全局的:
shwo global  variables like 'auto_inc%';
set global auto_increment_increment=2;
set global auto_increment_offset=10;

 

主鍵:

  一種特殊的惟一索引,不容許有空值,若是主鍵是單列,則它的值必須惟一,若是是多列,則它的組合必須惟一。

create table tb1(
    nid int not null auto_increment primary key,
    num int null
)
            
或

create table tb1(
    nid int not null,
    num int not null,
    primary key(nid,num)
)

 

外鍵:

  一個特定的索引,只能是被指定的內容。

 creat table color(
    nid int not null primary key,
    name char(16) not null
)

create table fruit(
    nid int not null primary key,
    smt char(32) null ,
    color_id int not null,
    constraint fk_cc foreign key (color_id) references color(nid)
)

 

二、刪除表

drop table 表名;

 

三、清空表

delete from 表名; 清空以後,id自增的話,增長新數據id不是從1開始 truncate table 表名; 清空以後,id自增的話,增長新數據id是從1開始,若是數據量很大的話,速度會比上面的快

 

四、修改表

添加列:alter table 表名 add 列名 類型; 刪除列:alter table 表名 drop column 列名;
修改列:alter table 表名 modify column 列名 類型;
-- 類型 alter table 表名 change 原列名 新列名 類型; -- 列名,類型 添加主鍵:alter table 表名 add primary key(列名);
刪除主鍵:alter table 表名 drop primary key; alter table 表名 modify 列名 int, drop primary key; 添加外鍵:alter table 從表 add constraint 外鍵名稱(形如:FK_從表_主表) foreign key 從表(外鍵字段) references 主表(主鍵字段); 刪除外鍵:alter table 表名 drop foreign key 外鍵名稱 修改默認值:ALTER TABLE testalter_tbl ALTER i SET DEFAULT
1000; 刪除默認值:ALTER TABLE testalter_tbl ALTER i DROP DEFAULT;

 

五、基本數據類型

MySQL中定義數據字段的類型對數據庫的優化是很是重要的。

MySQL支持多種類型,大體能夠分爲三類:數值日期/時間字符串(字符)類型。

 

數值類型

MySQL支持全部標準SQL數值數據類型。

這些類型包括嚴格數值數據類型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似數值數據類型(FLOAT、REAL和DOUBLE PRECISION)。

關鍵字INT是INTEGER的同義詞,關鍵字DEC是DECIMAL的同義詞。

BIT數據類型保存位字段值,而且支持MyISAM、MEMORY、InnoDB和BDB表。

做爲SQL標準的擴展,MySQL也支持整數類型TINYINT、MEDIUMINT和BIGINT。下面的表顯示了須要的每一個整數類型的存儲和範圍。

類型 大小 範圍(有符號) 範圍(無符號) 用途
TINYINT 1 字節 (-128,127) (0,255) 小整數值
SMALLINT 2 字節 (-32 768,32 767) (0,65 535) 大整數值
MEDIUMINT 3 字節 (-8 388 608,8 388 607) (0,16 777 215) 大整數值
INT或INTEGER 4 字節 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整數值
BIGINT 8 字節 (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 極大整數值
FLOAT 4 字節 (-3.402 823 466 E+38,1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 單精度
浮點數值
DOUBLE 8 字節 (1.797 693 134 862 315 7 E+308,2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 雙精度
浮點數值
DECIMAL 對DECIMAL(M,D) ,若是M>D,爲M+2不然爲D+2 依賴於M和D的值 依賴於M和D的值 小數值

 

日期和時間類型

表示時間值的日期和時間類型爲DATETIME、DATE、TIMESTAMP、TIME和YEAR。

每一個時間類型有一個有效值範圍和一個"零"值,當指定不合法的MySQL不能表示的值時使用"零"值。

TIMESTAMP類型有專有的自動更新特性,將在後面描述。

類型 大小
(字節)
範圍 格式 用途
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 '-838:59:59'/'838:59:59' HH:MM:SS 時間值或持續時間
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8

1000-01-01 00:00:00/

9999-12-31 23:59:59

YYYY-MM-DD HH:MM:SS 混合日期和時間值
TIMESTAMP 4 1970-01-01 00:00:00/2037 年某時 YYYYMMDD HHMMSS 混合日期和時間值,時間戳

 

字符串類型

字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。該節描述了這些類型如何工做以及如何在查詢中使用這些類型。

類型 大小 用途
CHAR 0-255字節 定長字符串,
VARCHAR 0-65535 字節 變長字符串
TINYBLOB 0-255字節 不超過 255 個字符的二進制字符串
TINYTEXT 0-255字節 短文本字符串
BLOB 0-65 535字節 二進制形式的長文本數據
TEXT 0-65 535字節 長文本數據
MEDIUMBLOB 0-16 777 215字節 二進制形式的中等長度文本數據
MEDIUMTEXT 0-16 777 215字節 中等長度文本數據
LONGBLOB 0-4 294 967 295字節 二進制形式的極大文本數據
LONGTEXT 0-4 294 967 295字節 極大文本數據

BINARY和VARBINARY類相似於CHAR和VARCHAR,不一樣的是它們包含二進制字符串而不要非二進制字符串。也就是說,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,而且排序和比較基於列值字節的數值。

BLOB是一個二進制大對象,能夠容納可變數量的數據。有4種BLOB類型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它們只是可容納值的最大長度不一樣。

有4種TEXT類型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。這些對應4種BLOB類型,有相同的最大長度和存儲需求。

 

char與varchar的區別:

  一、char的長度是不可變的,而varchar的長度是可變的

  二、定義一個char[10]和varchar[10],若是存進去的是‘abcd’,那麼char所佔的長度依然爲10,除了字符‘abcd’外,後面跟六個空格,而varchar就立馬把長度變爲4了,取數據的時候,char類型的要用trim()去掉多餘的空格,而varchar是不須要的

  三、char的存取數度仍是要比varchar要快得多,由於其長度固定,方便程序的存儲與查找;可是char也爲此付出的是空間的代價,由於其長度固定,因此不免會有多餘的空格佔位符佔據空間,可謂是以空間換取時間效率,而varchar是以空間效率爲首位的。

  四、char的存儲方式是,對英文字符(ASCII)佔用1個字節,對一個漢字佔用兩個字節;而varchar的存儲方式是,對每一個英文字符佔用2個字節,漢字也佔用2個字節,二者的存儲數據都非unicode的字符數據。

 

5、表內容操做

一、增

insert into 表 (列名,列名...) values (值,值,值...); insert into 表 (列名,列名...) values (值,值,值...),(值,值,值...); insert into 表 (列名,列名...) select (列名,列名...) from 表;

 

二、刪

delete from 表 delete from 表 where id=1 and name='YL'

 

三、改

update 表 set name = 'alex' where id>1

 

四、查

select * from 表 select * from 表 where id > 1 select nid,name,gender as gg from 表 where id > 1

 

五、其餘操做

a、條件 select * from 表 where id > 1 and name != 'YL' and num = 12; select * from 表 where id between 5 and 16; select * from 表 where id in (11,22,33) select * from 表 where id not in (11,22,33) select * from 表 where id in (select nid from 表) b、通配符 select * from 表 where name like 'ale%'  - ale開頭的全部(多個字符串) select * from 表 where name like 'ale_'  - ale開頭的全部(一個字符) c、限制 select * from 表 limit 5;            - 前5行 select * from 表 limit 4,5;          - 從第4行開始的5行 select * from 表 limit 5 offset 4    - 從第4行開始的5行 d、排序 select * from 表 order by 列 asc              - 根據 「列」 從小到大排列 select * from 表 order by 列 desc             - 根據 「列」 從大到小排列 select * from 表 order by 列1 desc,列2 asc    - 根據 「列1」 從大到小排列,若是相同則按列2從小到大排序 e、分組 select num from 表 group by num select num,nid from 表 group by num,nid select num,nid from 表 where nid > 10 group by num,nid order nid desc select num,nid,count(*),sum(score),max(score),min(score) from 表 group by num,nid select num from 表 group by num having max(id) > 10 特別的:group by 必須在where以後,order by以前  f、連表 無對應關係則不顯示,笛卡爾積 select A.num, A.name, B.name from A,B Where A.nid = B.nid 無對應關係則不顯示,出現null時,一行隱藏 select A.num, A.name, B.name from A inner join B on A.nid = B.nid A表全部顯示,若是B中無對應關係,則值爲null select A.num, A.name, B.name from A left join B on A.nid = B.nid B表全部顯示,若是B中無對應關係,則值爲null select A.num, A.name, B.name from A right join B on A.nid = B.nid g、組合,上下連表 組合,自動去掉重合數據 select nickname from A union select name from B 組合,不處理重合 select nickname from A union all select name from B

 

6、視圖

  視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,併爲其命名】,用戶使用時只需使用【名稱】便可獲取結果集,並能夠將其看成表來使用。

臨時表搜索: SELECT
    *
FROM ( SELECT nid, NAME FROM tb1 WHERE nid > 2 ) AS A WHERE A. NAME = 'alex';

 

一、建立視圖

--格式:CREATE VIEW 視圖名稱 AS SQL語句
CREATE VIEW v1 AS SELET nid, name FROM A WHERE nid > 4

 

二、刪除視圖

--格式:DROP VIEW 視圖名稱

DROP VIEW v1

 

三、修改視圖

-- 格式:ALTER VIEW 視圖名稱 AS SQL語句

ALTER VIEW v1 AS
SELET A.nid,
    B. NAME
FROM
    A
LEFT JOIN B ON A.id = B.nid
LEFT JOIN C ON A.id = C.nid
WHERE
    A.id > 2
AND C.nid < 5

 

四、使用視圖

  使用視圖時,將其看成表進行操做便可,因爲視圖是虛擬表,因此沒法使用其對真實表進行建立、更新和刪除操做,僅能作查詢用。

select * from v1

 

7、觸發器

   當對某張表作「增刪改」操做時,可使用觸發器自定義關聯行爲

一、建立觸發器

# 插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 插入後
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END


# 刪除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW BEGIN ... END # 刪除後 CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW BEGIN ... END

# 更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW BEGIN ... END # 更新後 CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW BEGIN ... END

 

插入數據前的觸發:

delimiter //
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN

IF NEW. NAME == 'yl' THEN
    INSERT INTO tb2 (NAME)
VALUES
    ('aa')
END IF

END//
delimiter ;

 

插入數據後觸發:

delimiter //
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
    IF NEW. num = 666 THEN
        INSERT INTO tb2 (NAME)
        VALUES
            ('666'),('666') ;
    ELSEIF NEW. num = 555 THEN
        INSERT INTO tb2 (NAME)
        VALUES
            ('555'),('555') ;
    END IF;
END//
delimiter ;

tips:

  建立觸發器的時候,須要將結束符臨時更改,而後再改回去,用delimiter

  NEW表示即將插入的數據行,OLD表示即將刪除的數據行。

 

二、刪除觸發器

DROP TRIGGER tri_after_insert_tb1;

 

三、使用觸發器

insert into tb1(num) values(666);

(插入,修改,刪除)數據後,自動觸發觸發器

 

8、存儲過程

  存儲過程是一個SQL語句集合,當主動去調用存儲過程時,其中內部的SQL語句會按照邏輯執行。

 

優勢:

  •   實現程序代碼與SQL的解耦,替代程序嵌入的SQL語句
  •   基於網絡傳輸,傳輸存儲過程的名字數據量小,而直接傳輸SQL語句數據量大

缺點:

  •   程序員擴展功能不方便

 

程序與數據庫結合使用的三種方式:

#方式一:
    MySQL:存儲過程
    程序:調用存儲過程

#方式二:
    MySQL:
    程序:程序+SQL語句

#方式三:
    MySQL:
    程序:類和對象,即ORM(本質仍是純SQL語句)

 

一、建立存儲過程

delimiter //
create procedure p1()
BEGIN
    select * from blog;
    INSERT into blog(name,sub_time) values("xxx",now());
END //
delimiter ;

#在mysql中調用 call p1()
#在python中基於pymysql調用 cursor.callproc('p1') print(cursor.fetchall())

對於存儲過程,能夠接收參數,其參數有三類:

  • in          僅用於傳入參數用
  • out        僅用於返回值用
  • inout     既能夠傳入又能夠看成返回值

 

有參數的存儲過程:

IN 傳入參數 
delimiter //
create procedure p2(
    in n1 int,
    in n2 int
)
BEGIN
    select * from blog where id > n1;
END //
delimiter ;


#在mysql中調用
call p2(3,2)


#在python中基於pymysql調用
cursor.callproc('p2',(3,2))
print(cursor.fetchall())
OUT 返回值

delimiter //
create procedure p3(
    in n1 int,
    out res int
)
BEGIN
    select * from blog where id > n1;
    set res = 1;
END //
delimiter ;

#在mysql中調用
set @res=0; #0表明假(執行失敗),1表明真(執行成功) call p3(3,@res); select @res;
#在python中基於pymysql調用
cursor.callproc('p3',(3,0)) #0至關於set @res=0 print(cursor.fetchall()) #查詢select的查詢結果 cursor.execute('select @_p3_0,@_p3_1;') #@p3_0表明第一個參數@p3_1表明第二個參數,即返回值 print(cursor.fetchall())
INOUT 既能夠傳入又能夠返回

delimiter //
create procedure p4(
    inout n1 int
)
BEGIN
    select * from blog where id > n1;
    set n1 = 1;
END //
delimiter ;


#在mysql中調用
set @x=3;
call p4(@x);
select @x;


#在python中基於pymysql調用
cursor.callproc('p4',(3,))
print(cursor.fetchall()) #查詢select的查詢結果

cursor.execute('select @_p4_0;') 
print(cursor.fetchall())

 

返回結果集的存儲過程:

delimiter //
create procedure p1()
begin
    select * from v1;
end //
delimiter ;

 

返回結果集+out值的存儲過程:

delimiter //
create procedure p2(
    in n1 int,
    inout n3 int,
    out n2 int,
)
begin
    declare temp1 int ;
    declare temp2 int default 0;

    select * from v1;
    set n2 = n1 + 100;
    set n3 = n3 + n1 + 100;
end //
delimiter ;

tips: 在存儲過程當中聲明變量用declare

 

使用遊標的存儲過程:?

            delimiter //
                    create procedure p3()
                    begin 
                        declare ssid int; -- 自定義變量1  
                        declare ssname varchar(50); -- 自定義變量2  
                        DECLARE done INT DEFAULT FALSE;


                        DECLARE my_cursor CURSOR FOR select sid,sname from student;
                        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
                        
                        open my_cursor;
                            xxoo: LOOP
                                fetch my_cursor into ssid,ssname;
                                if done then 
                                    leave xxoo;
                                END IF;
                                insert into teacher(tname) values(ssname);
                            end loop xxoo;
                        close my_cursor;
                    end  //
                    delimter ;

 

動態執行SQL的存儲過程:

delimiter \\
CREATE PROCEDURE p4 (
    in nid int
)
BEGIN
    PREPARE prod FROM 'select * from student where sid > ?';
    EXECUTE prod USING @nid;
    DEALLOCATE prepare prod; 
END\\
delimiter ;

 

支持事物的存儲過程:

#介紹
            delimiter //
            create procedure p4(
                out status int
            )
            BEGIN
                聲明若是出現異常則執行{
                    set status = 1;
                    rollback;
                }
                   
                開始事務
                    -- A帳戶減去100
                    -- B帳戶加90
                    -- C帳戶加10
                    commit;
                結束
                
                set status = 2;
                
                
            END //
            delimiter ;

#實現
delimiter //
create PROCEDURE p5(
    OUT p_return_code tinyint
)
BEGIN 
    DECLARE exit handler for sqlexception 
    BEGIN 
        -- ERROR 
        set p_return_code = 1; 
        rollback; 
    END; 

    DECLARE exit handler for sqlwarning 
    BEGIN 
        -- WARNING 
        set p_return_code = 2; 
        rollback; 
    END; 

    START TRANSACTION; 
        DELETE from tb1; #執行失敗
        insert into blog(name,sub_time) values('yyy',now());
    COMMIT; 

    -- SUCCESS 
    set p_return_code = 0; #0表明執行成功

END //
delimiter ;


#在mysql中調用存儲過程
set @res=123;
call p5(@res);
select @res;


#在python中基於pymysql調用存儲過程
cursor.callproc('p5',(123,))
print(cursor.fetchall()) #查詢select的查詢結果

cursor.execute('select @_p5_0;')
print(cursor.fetchall())

 

二、執行存儲過程

在MySQL中執行:

-- 無參數
call proc_name()

-- 有參數,全in
call proc_name(1,2)

-- 有參數,有in,out,inout
set @t1=0;
set @t2=3;
call proc_name(1,2,@t1,@t2)

在python中用pymysql執行:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 執行存儲過程
cursor.callproc('p1', args=(1, 22, 3, 4))
# 獲取執行完存儲的參數
cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")
result = cursor.fetchall()

conn.commit()
cursor.close()
conn.close()

print(result)

 

三、刪除存儲過程

drop procedure proc_name;

 

9、函數

MySQL中提供了許多內置函數,例如:

1、數學函數
    ROUND(x,y)
        返回參數x的四捨五入的有y位小數的值
        
    RAND()
        返回0到1內的隨機值,能夠經過提供一個參數(種子)使RAND()隨機數生成器生成一個指定的值。

2、聚合函數(經常使用於GROUP BY從句的SELECT查詢中)
    AVG(col)返回指定列的平均值
    COUNT(col)返回指定列中非NULL值的個數
    MIN(col)返回指定列的最小值
    MAX(col)返回指定列的最大值
    SUM(col)返回指定列的全部值之和
    GROUP_CONCAT(col) 返回由屬於一組的列值鏈接組合而成的結果    
    
3、字符串函數

    CHAR_LENGTH(str)
        返回值爲字符串str 的長度,長度的單位爲字符。一個多字節字符算做一個單字符。
    CONCAT(str1,str2,...)
        字符串拼接
        若有任何一個參數爲NULL ,則返回值爲 NULL。
    CONCAT_WS(separator,str1,str2,...)
        字符串拼接(自定義鏈接符)
        CONCAT_WS()不會忽略任何空字符串。 (然而會忽略全部的 NULL)。

    CONV(N,from_base,to_base)
        進制轉換
        例如:
            SELECT CONV('a',16,2); 表示將 a 由16進制轉換爲2進制字符串表示

    FORMAT(X,D)
        將數字X 的格式寫爲'#,###,###.##',以四捨五入的方式保留小數點後 D 位, 並將結果以字符串的形式返回。若  D 爲 0, 則返回結果不帶有小數點,或不含小數部分。
        例如:
            SELECT FORMAT(12332.1,4); 結果爲: '12,332.1000'
    INSERT(str,pos,len,newstr)
        在str的指定位置插入字符串
            pos:要替換位置其實位置
            len:替換的長度
            newstr:新字符串
        特別的:
            若是pos超過原字符串長度,則返回原字符串
            若是len超過原字符串長度,則由新字符串徹底替換
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一個出現位置。

    LEFT(str,len)
        返回字符串str 從開始的len位置的子序列字符。

    LOWER(str)
        變小寫

    UPPER(str)
        變大寫
   
    REVERSE(str)
        返回字符串 str ,順序和字符順序相反。
        
    SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
        不帶有len 參數的格式從字符串str返回一個子字符串,起始於位置 pos。帶有len參數的格式從字符串str返回一個長度同len字符相同的子字符串,起始於位置 pos。 
     使用 FROM的格式爲標準 SQL 語法。也可能對pos使用一個負值。倘若這樣,則子字符串的位置起始於字符串結尾的pos 字符,而不是字符串的開頭位置。在如下格式的函數中能夠對pos 使用一個負值。 mysql
> SELECT SUBSTRING('Quadratically',5); -> 'ratically' mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar' mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica' mysql> SELECT SUBSTRING('Sakila', -3); -> 'ila' mysql> SELECT SUBSTRING('Sakila', -5, 3); -> 'aki' mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2); -> 'ki' 4、日期和時間函數 CURDATE()或CURRENT_DATE() 返回當前的日期 CURTIME()或CURRENT_TIME() 返回當前的時間 DAYOFWEEK(date) 返回date所表明的一星期中的第幾天(1~7) DAYOFMONTH(date) 返回date是一個月的第幾天(1~31) DAYOFYEAR(date) 返回date是一年的第幾天(1~366) DAYNAME(date) 返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE); FROM_UNIXTIME(ts,fmt) 根據指定的fmt格式,格式化UNIX時間戳ts HOUR(time) 返回time的小時值(0~23) MINUTE(time) 返回time的分鐘值(0~59) MONTH(date) 返回date的月份值(1~12) MONTHNAME(date) 返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE); NOW() 返回當前的日期和時間 QUARTER(date) 返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE); WEEK(date) 返回日期date爲一年中第幾周(0~53) YEAR(date) 返回日期date的年份(1000~9999) 重點: DATE_FORMAT(date,format) 根據format字符串格式化date值 mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); -> 'Sunday October 2009' mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00', -> '%D %y %a %d %m %b %j'); -> '4th 00 Thu 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', -> '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52' mysql> SELECT DATE_FORMAT('2006-06-00', '%d'); -> '00' 5、加密函數 MD5() 計算字符串str的MD5校驗和 PASSWORD(str) 返回字符串str的加密版本,這個加密過程是不可逆轉的,和UNIX密碼加密過程使用不一樣的算法。 6、控制流函數 CASE WHEN[test1] THEN [result1]...ELSE [default] END 若是testN是真,則返回resultN,不然返回default CASE [test] WHEN[val1] THEN [result]...ELSE [default]END 若是test和valN相等,則返回resultN,不然返回default IF(test,t,f) 若是test是真,返回t;不然返回f IFNULL(arg1,arg2) 若是arg1不是空,返回arg1,不然返回arg2 NULLIF(arg1,arg2) 若是arg1=arg2返回NULL;不然返回arg1 7、控制流函數小練習 #7.一、準備表 /* Navicat MySQL Data Transfer Source Server : localhost_3306 Source Server Version : 50720 Source Host : localhost:3306 Source Database : student Target Server Type : MYSQL Target Server Version : 50720 File Encoding : 65001 Date: 2018-01-02 12:05:30 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `c_id` int(11) NOT NULL, `c_name` varchar(255) DEFAULT NULL, `t_id` int(11) DEFAULT NULL, PRIMARY KEY (`c_id`), KEY `t_id` (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of course -- ---------------------------- INSERT INTO `course` VALUES ('1', 'python', '1'); INSERT INTO `course` VALUES ('2', 'java', '2'); INSERT INTO `course` VALUES ('3', 'linux', '3'); INSERT INTO `course` VALUES ('4', 'web', '2'); -- ---------------------------- -- Table structure for score -- ---------------------------- DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `id` int(11) NOT NULL AUTO_INCREMENT, `s_id` int(10) DEFAULT NULL, `c_id` int(11) DEFAULT NULL, `num` double DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of score -- ---------------------------- INSERT INTO `score` VALUES ('1', '1', '1', '79'); INSERT INTO `score` VALUES ('2', '1', '2', '78'); INSERT INTO `score` VALUES ('3', '1', '3', '35'); INSERT INTO `score` VALUES ('4', '2', '2', '32'); INSERT INTO `score` VALUES ('5', '3', '1', '66'); INSERT INTO `score` VALUES ('6', '4', '2', '77'); INSERT INTO `score` VALUES ('7', '4', '1', '68'); INSERT INTO `score` VALUES ('8', '5', '1', '66'); INSERT INTO `score` VALUES ('9', '2', '1', '69'); INSERT INTO `score` VALUES ('10', '4', '4', '75'); INSERT INTO `score` VALUES ('11', '5', '4', '66.7'); -- ---------------------------- -- Table structure for student -- ---------------------------- DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `s_id` varchar(20) NOT NULL, `s_name` varchar(255) DEFAULT NULL, `s_age` int(10) DEFAULT NULL, `s_sex` char(1) DEFAULT NULL, PRIMARY KEY (`s_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of student -- ---------------------------- INSERT INTO `student` VALUES ('1', '魯班', '12', ''); INSERT INTO `student` VALUES ('2', '貂蟬', '20', ''); INSERT INTO `student` VALUES ('3', '劉備', '35', ''); INSERT INTO `student` VALUES ('4', '關羽', '34', ''); INSERT INTO `student` VALUES ('5', '張飛', '33', ''); -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS `teacher`; CREATE TABLE `teacher` ( `t_id` int(10) NOT NULL, `t_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of teacher -- ---------------------------- INSERT INTO `teacher` VALUES ('1', '大王'); INSERT INTO `teacher` VALUES ('2', 'alex'); INSERT INTO `teacher` VALUES ('3', 'egon'); INSERT INTO `teacher` VALUES ('4', 'peiqi'); #7.二、統計各科各分數段人數.顯示格式:課程ID,課程名稱,[100-85],[85-70],[70-60],[ <60] select score.c_id, course.c_name, sum(CASE WHEN num BETWEEN 85 and 100 THEN 1 ELSE 0 END) as '[100-85]', sum(CASE WHEN num BETWEEN 70 and 85 THEN 1 ELSE 0 END) as '[85-70]', sum(CASE WHEN num BETWEEN 60 and 70 THEN 1 ELSE 0 END) as '[70-60]', sum(CASE WHEN num < 60 THEN 1 ELSE 0 END) as '[ <60]' from score,course where score.c_id=course.c_id GROUP BY score.c_id;

 

重點掌握的函數:

#1 基本使用 mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); -> 'Sunday October 2009' mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00', ->                 '%D %y %a %d %m %b %j'); -> '4th 00 Thu 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', ->                 '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52' mysql> SELECT DATE_FORMAT('2006-06-00', '%d'); -> '00' #2 準備表和記錄 CREATE TABLE blog ( id INT PRIMARY KEY auto_increment, NAME CHAR (32), sub_time datetime ); INSERT INTO blog (NAME, sub_time) VALUES ('第1篇','2015-03-01 11:31:21'), ('第2篇','2015-03-11 16:31:21'), ('第3篇','2016-07-01 10:21:31'), ('第4篇','2016-07-22 09:23:21'), ('第5篇','2016-07-23 10:11:11'), ('第6篇','2016-07-25 11:21:31'), ('第7篇','2017-03-01 15:33:21'), ('第8篇','2017-03-01 17:32:21'), ('第9篇','2017-03-01 18:31:21'); #3. 提取sub_time字段的值,按照格式後的結果即"年月"來分組 SELECT DATE_FORMAT(sub_time,'%Y-%m'),COUNT(1) FROM blog GROUP BY DATE_FORMAT(sub_time,'%Y-%m'); #結果 +-------------------------------+----------+
| DATE_FORMAT(sub_time,'%Y-%m') | COUNT(1) |
+-------------------------------+----------+
| 2015-03                       |        2 |
| 2016-07                       |        4 |
| 2017-03                       |        3 |
+-------------------------------+----------+
3 rows in set (0.00 sec)

更多函數:官方介紹猛擊這裏

 

一、自定義函數

                   !!!注意!!!
#函數中不要寫sql語句(不然會報錯),函數僅僅只是一個功能,是一個在sql中被應用的功能
#若要想在begin...end...中寫sql,請用存儲過程
eg:自定義無參函數:

delimiter // create function f1( i1 int, i2 int) returns int BEGIN declare num int; set num = i1 + i2; return(num); END // delimiter ;
eg:自定義有參函數

delimiter //
create function f5(
    i int
)
returns int
begin
    declare res int default 0;
    if i = 10 then
        set res=100;
    elseif i = 20 then
        set res=200;
    elseif i = 30 then
        set res=300;
    else
        set res=400;
    end if;
    return res;
end //
delimiter ;

 

二、刪除函數

drop function func_name;

 

三、執行函數

# 獲取返回值
select UPPER('egon') into @res;
SELECT @res;


# 在查詢中使用
select f1(11,nid) ,name from tb2;

 

10、事物

  事務用於將某些操做的多個SQL做爲原子性操做,一旦有某一個出現錯誤,便可回滾到原來的狀態,從而保證數據庫數據完整性。

create table user(
id int primary key auto_increment,
name char(32),
balance int
);

insert into user(name,balance)
values
('wsb',1000),
('egon',1000),
('ysb',1000);

#原子操做
start transaction;
update user set balance=900 where name='wsb'; #買支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
update user set balance=1090 where name='ysb'; #賣家拿到90元
commit;

#出現異常,回滾到初始狀態
start transaction;
update user set balance=900 where name='wsb'; #買支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
uppdate user set balance=1090 where name='ysb'; #賣家拿到90元,出現異常沒有拿到
rollback;
commit;
mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
|  1 | wsb  |    1000 |
|  2 | egon |    1000 |
|  3 | ysb  |    1000 |
+----+------+---------+
rows in set (0.00 sec)

 

11、索引,流程控制,數據備份,python操做mysql,SQLAlchemy

猛戳這裏

相關文章
相關標籤/搜索