1.數據庫概述
簡 而言之,數據庫(DataBase)就是一個存儲數據的倉庫。爲了方便數據的存儲和管理,將數據按照特定的規律存儲在磁盤上。經過數據庫管理系統,能夠有 效的組織和管理存儲在數據庫中的數據。現在,已經存在的Oracle、SQLServer、MySQL等諸多優秀的數據庫。
詳解內容:
數據存儲方式
數據庫在開發中的做用
數據庫訪問技術
MySQL數據庫的介紹
數據庫泛型
SQL語言
常見數據庫系統
若是學習數據庫
1.1 數據庫理論基礎
數據庫可以將數據按照特定的規律組織起來。那麼,數據是如何存儲的、數據庫要遵照什麼規則、數據庫在什麼地方使用,這些都是首先要了解的問題。
1.1.1 數據存儲方式
現在數據庫已經無處不在了。
一個網站須要有數據庫來存儲數據。
一個學校須要用數據庫來存儲學生和教師的信息。
一個公司須要用數據庫來存儲員工的信息和公司的資料。
要學習數據庫,必須先了解數據庫是如何存儲數據的。
數據發展分爲三個階段:
1. 人工管理階段
2. 文件系統階段
3. 數據庫系統階段
1.1.2 數據庫泛型
數據庫泛型就是數據庫應該遵循的規則。數據庫泛型也稱爲範式。目前關係數據庫最經常使用的四種範式分別是:
第一範式(1NF)
第二範式(2NF)
第三範式(3NF)
BCN範式(BCNF)
在設計數據庫時,數據庫須要知足的最低要求的範式是第一範式。第一範式的要求表中不能有重複字段,而且每一個字段不能再拆分。若是有一個數據庫連第一範式都不知足的話,那就不能稱之爲關係型數據庫了。只有知足了第一範式的要求,纔可能在這個關係數據庫中建立表。
在知足第一範式的基礎上,能夠將數據庫中進行一步的細化。細化後能夠使數據庫知足第二範式的要求。依次進行細化,能夠獲得第三範式、BCN範式。
1.1.3 數據庫在開發中做用
如今大部分的管理系統和軟件都須要使用數據庫來存儲數據。在開發過程當中,數據庫已經成爲必不可少的一部分。本小節將爲讀者簡單介紹一下數據庫在開發中的做用。
在 軟件開發過程當中,常常須要使用數據庫來存儲數據。好比,一個學校的學生管理系統就須要數據庫來存儲學生的學籍信息、考試信息、教師的信息、課程信息等。再 好比,銀行的管理系統也須要數據庫來存儲信息。用戶的銀行賬戶、存款量、存款和取款的記錄等信息都是存儲在數據庫中的。當用戶向本身的賬戶裏存款時,管理 系統會在數據庫中更新該用戶的存款量。
1.2 數據庫系統
1.2.1 數據庫系統
很 多讀者認爲數據庫就是數據庫系統(DataBase System, 簡稱爲DBS)。其實,數據庫系統的範圍比數據庫大不少。數據庫系統不是一個單純的數據庫,而是由數據庫、數據庫管理系統、應用開發工具構成。不少時候, 數據庫管理員和用戶能夠當成數據庫系統的一份子。
數據庫就是存儲數據的地方。
數 據庫管理系統(DataBase Management System, 簡稱爲DBMS)是用來定義數據、管理和維護數據的軟件。它是數據庫系統的一個重要組成部分。應用系統是須要使用數據庫的軟件。好比學員管理系統就是一個 應用系統,這個應用系統須要數據庫管理它的數據。應用開發工具就是用來開發應用系統的。
1.2.2 SQL語言
SQL(Structured Query Language)語言的全稱是結構化查詢語言。數據庫管理系統經過SQL語言來管理數據庫中的數據。
SQL語言分爲三個部分:
數據定義語言(Data Definition Language, 簡稱爲DDL)
數據操做語言(Data Manipulation Language, 簡稱爲DML)
數據控制語言(Data Control Language, 簡稱爲DCL)
數據查詢語言(Data Query Language, 簡稱DQL)
1.2.3 數據庫訪問技術
應用程序中,程序語言須要使用數據庫訪問技術來訪問數據庫。只有使用了數據庫訪問技術,程序中嵌入的SQL語句纔會起做用。不一樣程序語言訪問數據庫的方式是不同的。
JDBC是一種用於執行SQL語句的Java API。經過JDBC能夠訪問多種關係數據庫。JDBC由一組用Java語言編寫的類和接口組成。使用JDBC時,必需要安裝驅動程序Connector/J。
PHP中爲程序員提供了MySQL功能模塊,PHP5之後開始提供mysqli接口。PHP能夠經過MySQL功能模塊和mysqli接口來訪問MySQL數據庫。
1.3 常見數據庫
1.3.1 常見數據庫系統
現在已經在不少優秀的商業數據庫
如甲骨文(Oracle)公司的Oracle數據庫
IBM公司的DB2數據庫
微軟公司的SQL Server數據庫和Access數據庫。
還有不少優秀的開源數據庫,如MySQL數據庫、PostgreSQL數據庫等。
1. 甲骨文的Oracle
2. IBM的DB2
3. 微軟的Access和SQL Server
4. 開源PostgreSQL
6. 開源MySQL
1.3.2 爲何要使用MySQL
如 今不少大型網站已經選擇MySQL數據庫來存儲數據。那麼,MySQL到底有什麼優點呢?MySQL數據庫的使用很是普遍,尤爲是在Web應用方面。因爲 MySQL數據庫發展勢頭迅猛,SUN公司於2008年收購了MySQL數據庫。這筆交易的收購價格高達10億美圓。這中以說明MySQL數據庫價值。
MySQL數據庫的優點:
1. 開源代碼
2. 跨平臺性
3. 價格優點
4. 功能強大且使用方便
1.3.3 MySQL版本和獲取
MySQL數據庫能夠在Windows、UNIX、Linux和Mac OS等操做系統上運行。所以,MySQL有不一樣操做系統的版本。並且,根據發佈的前後順序,如今已經在開發MySQL的6.0版了。
根據MySQL的開發狀況,能夠將MySQL分爲Alpha、Beta、Gamma和Generally Available(GA)等版本。
- Alpha(開發過程當中)
- Beta(測試版)
- Gamma(比Beta版更高級)
- Generally Available(GA)(穩定版)
1.4 若是學習數據庫
數據庫已經成爲軟件系統的一部分,那麼學好數據庫將是軟件開發的一個必要條件。如何才能學好數據庫,這個問題沒有確切的答案。
學好數據庫的方法:
1. 多上機實踐
2. 多編寫SQL語句
3. 經過Java或PHP程序語言操做數據庫
4. 數據庫理論知識不能丟
1.5 常見問題及解答
1. 如何選擇數據庫?
2. 如何選擇MySQL版本?
1.6 本章習題
1. 數據存儲的發展過程經歷了哪幾個階段?
2. 經常使用數據庫系統有哪些?
3. MySQL數據庫如何分類?
2.Windows平臺下安裝與配置MySQL
在 Windows系列的操做系統下,MySQL數據庫的安裝包分爲圖形化界面安裝和免安裝(noinstall)這兩種安裝包。這兩種安裝包的安裝方式不 同,並且配置方式也不一樣。圖形化界面安裝包有完整的安裝嚮導,安裝和配置很方便。免安裝的安裝包直接解壓便可使用,可是配置起來很不方便。
安裝MySQL數據庫
配置MySQL數據庫
經常使用圖形管理工具介紹
配置和使用免安裝的MySQL數據庫
2.1 安裝與配置MySQL
2.1.1 安裝MySQL
MySQL 圖形化安裝包有一個完整的安裝嚮導,根據安裝嚮導能夠很方便的安裝MySQL數據庫。在Windows操做系統下,有兩種MySQL圖形化安裝包。這兩種 安裝包分別是"Windows Essentials"和"Windows MSI Installer"。前者包含了MySQL中最主要和最經常使用的功能,可是不包含一些不經常使用的功能。後者包含了MySQL所有功能,包括不經常使用的功能。
http://dev.mysql.com/downloads/mysql/#downloads
選擇Microsoft Windows選項
mysql-5.1.40-win32.msi(圖形界面安裝)
mysql-essential-5.1.40-win32.msi (圖形界面安裝)
mysql-noinstall-5.1.40-wind32.zip (免安裝)
安裝步驟:
1. Next
2. Typical Complete Custom(O)
3. MySQL Server
Client Programs
C Includes Files / Lib Files(X)
Change: ?????
4. Install
Setup Type: Custom
Destination Folder(程序安裝路徑):
Data Folder(數據存儲的路徑):
5. Next->Next->
(O)Configure the MySQL Serer now
(O)Register the MySQL Server now
6. Finish
2.1.2 配置MySQL
安裝完成時,選上了Configure the MySQL Server now選項,圖形化安裝嚮導將進入MySQL配置歡迎界面。經過配置嚮導,能夠設置MySQL數據庫的各類參數。
1. Next
2. (O)Detailed Configuration
(X)Standard Configuration
3. (O)Developer Machine(開發者)
Server Machine(服務器)
Dedicated MySQL Server Machine(專用的數據庫服務器)
4. (O)Multifunctional Database(多功能型數據庫)
Transactional Database Only(事務型的數據庫, InnoDB)
Non-Transactional Database Only(只支持MyISaM類型數據庫,非事務)
5. InnoDB Tablespace Settings (配置表空間)
6. 設置服務器的鏈接數
Decision Support(DSS) / OLAP
Online Transaction Processing(OLTP)
(O)Manual Setting
Concurrent Connections: 10
7. MySQL服務的端口號:
(O)Add firewall exception for this port(容許防火牆)
(X)Enable Strict Mode(是區分大寫)
8. 設置字符集
Standard Character Set
Best Support for Multilingualism
(O)Manual Selected Default Character Set / Collation
utf-8
9. Install As Windws Service 服務選項
Service Name: MySQL
(O)Lanch the MySQL Server automatically(服務是否自動啓動)
(O)Include Bin Directory in Windows PATH(添加到path路徑當中)
10. Modify Security Setting:
New root password:
confirm:
(X)Enable root access from remote machines(不否遠程訪問root)
11. Execute
12. Finish
2.2 啓動服務並登陸MySQL數據庫
MySQL數據庫分爲服務器端(Server)和客戶端(Client)兩部分。只有服務器端的服務開戶之後,才能夠經過客戶端來登陸到MySQL數據庫。
2.2.1 啓動MySQL服務
開始->設置->控制面板->管理工具->服務
2.2.2 登陸MySQL服務器
1. 開始->運行->cmd
mysql -h localhost -u root -p
mysql>
2. 開始->運行->mysql -h 127.0.0.1 -u root -p
2.2.3 配置path變量
若是MySQL的應用程序的目錄沒有添加到Windows系統的path環境變量中,能夠手工的將MySQL的目錄添加到path中。
將 MySQL的應用程序的目錄添加到Windows系統的path環境變量中,能夠使之後的操做更加方便。例如,能夠直接從運行對話框輸入MySQL數據庫 命令。並且,之後在編程時也會更加方便。配置path路徑很簡單,只要將MySQL的應用程序的目錄添加到系統的path環境變量中就能夠了。
1. 右擊【個人電腦】->【屬性】
2. 在系統環境變量中選中path變量,而後單擊編輯按鈕進入編輯環境變量的對話框。
3. 把MySQL應用程序的目錄添加到path環境變量名值的後面。已經存在的目錄用分號隔開。
2.3 更改MySQL的配置
MySQL數據庫安裝好了之後,可能根據實際狀況更改MySQL的某些配置。通常能夠經過兩種方式來更改。一種是經過配置嚮導來更改配置,另外一種是手工來更改配置。
2.3.1 經過配置嚮導來更改配置
MySQL Server Instance Config Wizard與初始配置時
1.Reconfigure Instance (修改配置信息)
Remove Instance (刪除配置信息)
2.Detailed Configuration
......
.....
2.3.2 手工更改配置
用戶能夠經過修改MySQL配置文件方式來進行配置。這種配置方式更加靈活,可是相對初學者來講比較困難。
在進行手工配置以前,須要對MySQL的文件有所瞭解。MySQL的文件安裝在?????
數據庫的數據文件安裝在?????
bin 可執行目錄
data 數據目錄
scripts
share 字符集目錄
mysql.ini 基本配置文件
my-huge.ini 配置大型數據庫
my-large.ini ..
my-innodb-heavy-4g 配置innodb
my-medium.ini 中型數據庫配置文件
my-small.ini 小型數據庫配置文件
my-template.ini 配置文件模板
mysql.ini:
port = 3306 # 端口號
default-character-set = gbk # 默認的字符集
basedir = .... # 安裝文件夾
datadir = ..... # 數據庫文件夾
default-storage-engine = INNODB # 默認的存儲引擎
2.4 MySQL經常使用圖形管理工具
MySQL圖形管理工具能夠在圖形界面上操做MySQL數據庫。在命令行中操做MySQL數據庫時,須要使用不少的命令。而圖形管理工具則只是使用鼠標點便可,這使MySQL數據庫的操做更加簡單。
MySQL的圖形管理工具不少。經常使用的有MySQL GUI Toools、phpMyAdmin、Navicat等。經過這些圖像管理工具,能夠使MySQL的管理更加方便。每種圖形管理工具各有特色。
1. MySQL GUI Tools
2. phpMyAdmin
3. Navicat
4. SQLyog
5. MySQLDumper
6. MySQL ODBC/Connector
2.5 使用免安裝MySQL
Windows操做系統下有免安裝的MySQL軟件包。用戶直接解壓這個軟件包,進行簡單的配置就能夠使用了。免安裝包省略了安裝過程,使用起來也很方便。
1. 解壓軟件包
2. 建立my.ini文件
3. 修改my.ini文件
[mysqld]
socket ....
basedir = "c:/mysql/"
datadir = "c:/mysql/data"
[WindowsMySQLServer]
Server = "c:/mysql/bin/mysqld.exe"
* my.ini文件複製到C:/WINDOWS文件夾
4. 設置MySQL服務
c:/mysql/bing/mysqld.exe --install
5. 配置系統Path變量
6. 啓動和關閉服務
運行服務:運行-> net start mysql 啓動服務
net stop mysql 中止服務
2.6 上機操做
1. 經過圖形化方式安裝MySQL數據庫
2. 配置免安裝的MySQL
2.7 常見問題及解答
1. 如何選擇字符集?
2. 如何刪除MySQL數據庫?
2.8 習題
1. 練習使用圖形化安裝MySQL數據庫。
2. 練習使用配置嚮導配置MySQL數據庫。
3. 練習使用免安裝的MySQL軟件包安裝。
4. 練習經過手工修改my.ini文件的方式更改配置。
3.Linux平臺下安裝與配置MySQL
在Linux系列的操做系統下,通常都使用命令來安裝MySQL數據庫。由於Linux操做系統的發行版比較多,因此相應的MySQL版本也比較多。相同Linux發行版也有不一樣的MySQL軟件包。根據本身的操做系統的版原本下載和安裝不一樣的MySQL版本。
- Linux操做系統下的MySQL版本介紹
- 安裝和配置MySQL的RPM包
- 安裝和配置MYSQL的二進制包
- 安裝和配置MySQL的源碼包
3.1 Linux操做系統下的MySQL版本介紹
Linux操做系統的發行版不少,不一樣Linux發行版的MySQL版本是不一樣的。MySQL數據庫主要支持Linux版本是Red Hat Enterprise Linux和SUSE Linux Enterprise Server。這兩個版本下也有不一樣的安裝包。
Linux操做系統的MySQL軟件包通常分爲三類,分別是RPM軟件包,二進制軟件包和源碼包。
RPM軟件包:
二進制包:
源碼包:
1. Red Hat Enterprise Linux發行版
2. SUSE LInux Enterprise Server發行版
Linux版本 推薦安裝的MySQL版本
Red Hat Enterprise Linux RPM軟件包
SUSE Linux Enterprise Server RPM軟件包
Fedora RPM軟件包
Ubuntu 源碼包
CentOS RPM軟件包
3.2 安裝和配置MySQL的RPM包
大部分Linux版本的MySQL軟件是以RPM包的形式發佈的。RPM包的安裝和卸載都很方便,經過簡單的命令就能夠實現RPM包的安裝與卸載。可能經過手工修改配置文件的方式來進行配置。
MySQL官方網站下載RPM包,http://dev/mysql.com/downloads/mysql/5.1.html。在該網站上有不少種類的RPM安裝包,根據本身的操做系統和處理器類型來選擇。
Red Hat Enterprise Linux 5 RPM(x86)
3.3 安裝和配置MySQL的二進制包
Linux操做系統下有以二進制形式發佈的MySQL軟件包。這些二進制的MySqL軟件包比RPM包要靈活,可是安裝沒有RPM包那麼容易。
http://dev/mysql.com/downloads/mysql/5.1.html。
單擊Linux(non RPM packages)連接,就可跳轉到下載二進制包的位置。
3.4 安裝和配置MySQL的源碼包
Linux 操做系統下有以源碼的形式發佈的MySQL軟件包。這樣軟件包中是MySQL的源代碼,須要用戶本身進行編譯。這種MySQL軟件包的靈活性最高,用戶可 以根據本身的須要進行控制。並且, 感興趣的用戶能夠查看MySQL的源代碼。可是編譯代碼耗費的時候比較長。
http://dev.mysql.com/downloads/mysql/5.1.html
單擊Source連接,就能夠跳轉到下載源碼包的位置。
3.5 上機實踐
1. 在Linux操做系統下用RPM包來安裝MySQL數據庫
2. 在Linux操做每戶下用二進制包安裝MySQL數據庫
3. 在Linux操做系統下用源碼包來安裝MySQL數據庫
3.6 常見問題及解答
1. 如何選擇Linux操做系統下的MySQL數據庫?
2. Linux下如何卸載MySQL數據庫?
3.7 本意習題
1. 練習使用RPM軟件包安裝MySQL數據庫。
2. 練習使用二進制軟件包安裝MySQL數據庫。
3. 練習使用源碼包安裝MySQL數據庫。
4. 練習手動配置MySQL的配置文件。
4.MySQL數據類型
數據類型是數據的一種屬性,其能夠決定數據存儲格式、有效範圍和相應的限制。MySQL的數據類型包括整數類型、浮點數類型、定點數類型、日期和時間類型、字符串類型和二進制類型。
- 整數類型、浮點數類型和定點數類型
- 日期與時間類型
- 字符串類型
- 二進制類型
- 如何選擇數據類型
4.1 MySQL數據類型介紹
MySQL數據庫提供了多種數據類型。不一樣的類型有各自的特色,使用範圍不相同。並且,存儲方式也不同。
4.1.1 整型
整數類型是數據庫中最基本的數據類型。標準SQL中支持INTEGER和SMALLINT這兩種整數類型。MySQL數據庫除了支持這兩種類型外,還擴展支持了TINYINT、MEDIUMINT和BIGInT。
各類整數類型的取值範圍、存儲的字節數、特色。
整型 字節數 無符號數的取值範圍 有符號數的取值範圍
TINYINT 1 0~255 -128~127
SMALLINT 2 0~65535 -32768~12767
MEDIUMINT 3 0~16777215 -8388608~8388607
INT 4 0~4294967295 -2147483648~2147483647
INTEGER 4 0~4294967295 -2147483648~2147483647
BIGINT 8 0~18446744073709551615 -9223372036954775808~9223372036854775807
MySQL命令不區分大小寫,一般使用大寫表示MySQL關鍵字,使用小寫表示用戶定義的值。
例如:
# 設置密碼
mysql -h localhost -u root -p
USE `databasename`;
DESC `tablename`;
MySQ整數類型默認長度
1. tinyint(4)
2. smallint(6)
3. mediumint(9)
4. int(11)
5. bigint(20)
Mysql註釋支持如下幾種:
一、#
二、--
三、/* */
實例一:
# 若是數據庫中不存在test數據庫,則建立test數據庫。
CREATE DATABASE IF NOT EXISTS `test`;
-- 選擇數據庫
USE `test`;
/* 若是test數據庫中不存在int_tbl_1表,則建立int_tbl_1表 */
CREATE TABLE IF NOT EXISTS `test`.`int_tbl_1` (
`a` TINYINT,
`b` SMALLINT,
`c` MEDIUMINT,
`d` INT,
`e` BIGINT
);
INSERT INTO `test`.`int_tbl_1` VALUES(1,1,1,1,1);
INSERT INTO `test`.`int_tbl_1` VALUES(2,2,2,2,2);
INSERT INTO `test`.`int_tbl_1` VALUES(3,3,3,3,3);
INSERT INTO `test`.`int_tbl_1` VALUES(4,4,4,4,4);
INSERT INTO `test`.`int_tbl_1` VALUES(5,5,5,5,5);
SELECT * FROM `int_tbl_1`;
實例二:
CREATE TABLE IF NOT EXISTS `test`.`int_tbl_2` (
`a` TINYINT UNSIGNED ZEROFILL NOT NULL ,
`b` SMALLINT UNSIGNED ZEROFILL NOT NULL ,
`c` MEDIUMINT UNSIGNED ZEROFILL NOT NULL ,
`d` INT UNSIGNED ZEROFILL NOT NULL ,
`e` BIGINT UNSIGNED ZEROFILL NOT NULL
);
INSERT INTO `test`.`int_tbl_2` VALUES(1,1,1,1,1);
INSERT INTO `test`.`int_tbl_2` VALUES(2,2,2,2,2);
INSERT INTO `test`.`int_tbl_2` VALUES(3,3,3,3,3);
INSERT INTO `test`.`int_tbl_2` VALUES(4,4,4,4,4);
INSERT INTO `test`.`int_tbl_2` VALUES(5,5,5,5,5);
SELECT * FROM `int_tbl_2`;
使用UNSIGNED或UNSIGNED ZEROFILL以後MySQ整數類型默認長度:
1. tinyint(3)
2. smallint(5)
3. mediumint(8)
4. int(10)
5. bigint(19)
實例三:
CREATE TABLE IF NOT EXISTS `test`.`int_tbl_3` (
`a` INT(4) NOT NULL ,
`b` INT(11) NOT NULL
) ENGINE = INNODB;
INSERT INTO `test`.`int_tbl_3` VALUES(111111,22222222);
SELECT * FROM `int_tbl_3`;
-- 數據111111成功插入到字段a中,無論字段a長度是設置了多少。由於INT類型的默認最大長度爲11,所以即便插入的數據超出了指定長度的範圍,也會插入到數據表中。
如何爲字段選擇整數類型?
1. TINYINT : 若是字段的最大值不超過255,那選擇TINYINT類型就足夠了。
2. INT: 若是須要範圍比較大的值,使用INT類型便可。如會員表中的編號字段等。
4.1.2 浮點數類型和定點數類型
MySQL使用浮點數類型和定點數類型來表示小數。浮點數類型包括單精度浮點數(FLOAT類型)和雙精度浮點數(DOUBLE類型)。定點數類型就是DECIMAL型。
FLOAT型、DOUBLE型、DECIMAL型的取值範圍、存儲的字節數、特色。
小數類型 字節數 負數取值範圍 無符號取值範圍
FLOAT 4 -3.402823466E+38~ 0和1.175494351E-38~
-1.175494351E-38 3.402823466E+38
DOUBLE 8 1.7976931348623157E+308~ 0和2.2250738585072014E~
-2.2250738585072014E-308 1.7976931348623157E+308
DECIMAL(M,D) M+2 DOUBLE型 同DOUBLE型
或DEC(M,D)
M:最大長度(包括小數部分,但不包括小數點)
D:小數點後保留長度
FLOAT(6,2)表示數據長度爲6個,小數點保留2位。1234.56符合要求。
若是插入值的精度高於實際定義的精度,系統會自動進行四捨五入處理,使值的精度達到要求。不一樣的是,FLOAT型和DOUBLE型在四捨五入時不會報錯,而DECIMAL型會警告。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`decimal_tbl_1` (
`a` FLOAT(6,2),
`b` DOUBLE(6,2),
`c` DECIMAL(6,2)
) ENGINE = MyISAM;
INSERT INTO `test`.`decimal_tbl_1` VALUES(3.143, 3.145, 3.1434);
SHOW WARNINGS; -- 查看警告
# DECIMAL型有警告
SELECT * FROM `decimal_tbl_1`;
若是不指定精度,浮點數和定點數有其默認的精度。FLOAT型和DOUBLE型默認會保存實際精度,但這與操做系統和硬件的精度有關。DECIMAL型默認整數位爲10,小位位爲0,即默認爲整數。
實例二:
CREATE TABLE IF NOT EXISTS `test`.`decimal_tbl_2` (
`a` FLOAT,
`b` DOUBLE,
`c` DECIMAL
) ENGINE = MyISAM;
INSERT INTO `test`.`decimal_tbl_2` VALUES(3.143, 3.145, 3.1434);
SHOW WARNINGS; -- 查看警告
SELECT * FROM `decimal_tbl_2`;
在MySQL中,定點數以字符串形式存儲。所以,其精度比浮點數要高。並且,浮點數會出現偏差,這是浮點數一塊兒存在的缺陷。若是要對數據的精度要求比較高,仍是選擇定點數(DECIMAL)比較安全。
不要使用"="作浮點數操做。
4.1.3 日期和時間類型
日期和時間類型是爲了方便在數據庫中存儲日期和時間而設計的。MySQL中有多種表示日期和時間的數據類型。其中,YEAR類型表示年份;DATE類型表示日期;TIME類型表示時間;DATETIME和TIMESTAMP表示日期和時間。
日期和時間類型的存儲字節數、取值範圍和特色
1. YEAR類型
2. TIME類型
3. DATE類型
4. DATETIME類型
5. TIMESTAMP類型
4.1.3.1 YEAR類型
(1) 使用4位字符串或數字表示。
使用字節 取值範圍 輸入格式 超出範圍
1 1901~2155 YYYY | 'YYYY' | "YYYY" 0000
實例一:
CREATE TABLE IF NOT EXISTS `test`.`year_tbl_1`(`a` YEAR);
INSERT INTO `test`.`year_tbl_1` VALUES(1997),('1998'),("1990"),(2200);
SELECT * FROM `year_tbl_1`;
(2) 使用2位整數或字符串表示。'00'到"69"轉換爲2000到2069,'70'到"99"轉換爲1970到1999。例如輸入'35', YEAR值會轉換爲2035;輸入'90', YEAR值會轉換爲1990。
'0'和"00"的效果是同樣的。
實例二:
INSERT INTO `test`.`year_tbl_1` VALUES('24'),("86"),("0"),('00');
SELECT * FROM `year_tbl_1`;
INSERT INTO `test`.`year_tbl_1` VALUES(50),(0);
注意:插入0,轉換後的YEAR值不是2000,而是0000。
由於YEAR類型只佔一個字節。若是隻須要記錄年份,選擇YEAR類型能夠節約空間。
4.1.3.2 TIME類型
類型 字節 表示形式 取值範圍
TIME 3 HH:MM:SS '-839:59:59'到'838:59:59'
HH:時
MM:分(0~59)
SS:秒(0~59)
(1)'D HH:MM:SS' 格式的字符串表示。其中,D表示天數,取值範圍是0~34。保存時,小時的值等於(D*24+HH)。例如,輸入'2 11:30:50',TIME類型會轉換爲59:30:50。固然輸入時能夠不嚴格按照這個格式,也能夠是"HH:MM:SS"、"HH:MM"、"D HH:MM"、"D HH"或者"SS"等形式。例如,輸入'30',TIME類型會轉化爲00:00:30。
實例一:
向表中插入"2 23:50:50", '22:22:22', '11:11', '2 20:20', '2 20' 和 '30'
CREATE TABLE IF NOT EXISTS `test`.`time_tbl_1`(`a` TIME);
INSERT INTO `test`.`time_tbl_1` VALUES ("2 23:50:50"), ('22:22:22'), ('11:11'), ('2 20:20'), ('2 20'), ('30');
SELECT * FROM `time_tbl_1`;
(2) 'HHMMSS'格式的字符串或者HHMMSS格式的數值表示。例如,輸入'345454', TIME類型會轉化爲34:54:54,TIME類型會轉化爲34:54:54。若是輸入0和'0',那麼TIME類型會轉化爲0000:00:00。
實例二:
INSERT INTO `test`.`time_tbl_1` VALUES (121212), ('131313'), ('0'),(0);
SELECT * FROM `time_tbl_1`;
(3) 使用CURRENT_TIME或者NOW()輸入當前系統時間。
實例三:
INSERT INTO `test`.`time_tbl_1` VALUES (CURRENT_TIME),(NOW());
SELECT * FROM `time_tbl_1`;
TIME類型專門用來存儲時間數據,並且只佔3個字節。若是隻須要記錄時間,選擇TIME類型是最合適的。
4.1.3.3 DATE類型
類型 字節數 顯示形式 取值範圍 賦值方式
DATE 4 YYYY-MM-DD '1000-01-01' 'YYYY-MM-DD'或
到'9999-12-31' 'YYYYMMDD'
(1) MySQL中支持一些不嚴格的語法格式,任何標點均可以用來作間隔符。如'YYYY/MM/DD'、'YYYY@MM@DD'、'YYYY.MM.DD'等分隔形式。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`date_tbl_1`(`a` DATE);
INSERT INTO `test`.`date_tbl_1`
VALUES ('1949-10-01'), ('1950#2#3'),('1951@3@4'),('19520101');
SELECT * FROM `date_tbl_1`;
(2) 'YY-MM-DD'或者'YYMMDD'格式的字符串表示。其中'YY'的取值,'00'到'69'轉換爲2000到2069,'70'到'99'轉換 爲1970到1999.與YEAR類型相似,例如,輸入'35-01-02',DATE類型將轉換爲2035-01-02;輸入 '800102',DATE類型將轉換爲1980-01-02。
MySQL也支持一些不嚴格的語法格式,如'YY/MM/DD'、'YY@MM@DD'、'YY.MM.DD'等分隔形式。例如,輸入'89@3@8', DATE類型轉換爲1989-03-08。
實例二:
INSERT INTO `test`.`date_tbl_1`
VALUES ('53-01-01'), ('78@1@1'),('540101'),('790101');
SELECT * FROM `date_tbl_1`;
(3) YYYYMMDD或YYMMDD格式的數字表示。其中'YY'的取值,'00'到'69'轉換爲2000到2069.'70'到'99'轉換爲1970到 1999。例如,輸入20080808,DATE類型轉換爲2008-08-08;輸入790808,DATE類型將轉換爲1979-08-08。若是輸 入的值爲0,那麼DATE類型會轉換爲0000-00-00
實例三:
INSERT INTO `test`.`date_tbl_1`
VALUES (20080808), (800101), (090101), (0);
SELECT * FROM `date_tbl_1`;
(4) 使用CURRENT_DATE或者NOW()來輸入函數系統日期。
INSERT INTO `test`.`date_tbl_1`
VALUES (CURRENT_DATE),(NOW());
SELECT * FROM `date_tbl_1`;
4.1.3.4 DATETIME類型
類型 字節 顯示形式 取值範圍
DATETIME 8 YYYY-MM-DD HH:MM:SS '1000-01-01 00:00:00'到
'9999-12-31 23:59:59'
(1) 'YYYY-MM-DD HH:MM:SS'或者'YYYYMMDDHHMMSS'格式的字符串表示
這 種方式能夠表達的範圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。例如,輸入'2008-08-08 08:08:08',DATETIME類型轉換爲2008-08-08 08:08:08;輸入’20080808080808‘, 一樣轉換爲2008-08-08 08:08:08。
MySQL 支持一些不嚴格的語法格式,任何標點均可以用來作間隔符。狀況與DATE類型相同。並且,時間部分也能夠使用任意分隔符隔開,這與TIME類型不一樣。 TIME類型只能使用':'隔開。例如:輸入'2008@08@08@ 08*08*08', 一樣轉換爲2008-08-08 08:08:08。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`datetime_tbl_1`(`a` DATETIME);
INSERT INTO `test`.`datetime_tbl_1`
VALUES ('1949-10-01 11:11:11'),('1950#2#2 11+11+11'), ('19510101121212');
SELECT * FROM `datetime_tbl_1`;
(2) 'YY-MM-DD HH:MM:SS'或者'YYMMDDHHMMSS'格式的字符串表示。其中'YY'的取值,'00'到'69'轉換爲2000到2069,'70'到'99'轉換爲1970到1999。與YEAR型和DATE型相同。
實例二:
INSERT INTO `test`.`datetime_tbl_1`
VALUES ('52-01-01 11:11:11'),('53@1@1 11*11*'), ('790101121212');
SELECT * FROM `datetime_tbl_1`;
(3)YYYYMMDDHHMMSS 或YYMMDDHHMMSS格式的數字表示。例如,輸入20080808080808,DATETIME類型轉換爲2008-08-08 08-08-08;輸入080808080808,一樣轉換爲2008-08-08 08:08:08。若是輸入的值爲0,那麼DATETIME類型轉換爲0000-00-00 00:00:00。
實例三:
INSERT INTO `test`.`datetime_tbl_1`
VALUES (20080808080808),(090101080808), (790101080808),(0);
SELECT * FROM `datetime_tbl_1`;
(4) 使用NOW()來輸入當前系統日期和時間
實例四:
INSERT INTO `test`.`datetime_tbl_1`
VALUES (NOW());
SELECT * FROM `datetime_tbl_1`;
4.1.3.5 TIMESTAMP類型
TIMESTAMP 類型使用4個字節來表示日期和時間。TIMESTAMP類型的範圍從1970-01-001 08:00:01到2038-01-19 11:14:07。MySQL中也是以'YYYY-MM-DD HH:MM:SS'的形式顯示TIMESTAMP類型的值。從其形式能夠看出,TIMESTAMP類型與DATETIME類型顯示的格式同樣的。給 TIMESTAMP類型的字段賦值的表示方法基本與DATETIME類型相同。值的注意的是,TIMESTAMP類型範圍比較小,沒有DATETIME類 型的範圍大。所以,輸入值時要保證在TIMESTAMP類型時有效範圍內。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`timestamp_tbl_1`(`a` TIMESTAMP);
INSERT INTO `test`.`timestamp_tbl_1`
VALUES ('1970-10-01 11:11:11'),('1970#2#3 11+11+11'), ('19710101121212'),('28-01-01 11:11:11'), ('33@1@1 11*11*11'), ('790101121212'),('20080808080808'), ('090101080808'), (0),(NOW());
SELECT * FROM `timestamp_tbl_1`;
TIMESTAMP類型的幾種與DATETIME類型不一樣的形式。
(1) 使用CURRENT_TIMESTAMP來輸入系統日期與時間
(2) 輸入NULL時,系統會輸入系統當前日期與時間
(3) 無任何輸入時,系統會輸入系統當前日期與時間
實例二:
INSERT INTO `test`.`timestamp_tbl_1` VALUES();
INSERT INTO `test`.`timestamp_tbl_1` VALUES('');
INSERT INTO `test`.`timestamp_tbl_1` VALUES(CURRENT_TIMESTAMP);
INSERT INTO `test`.`timestamp_tbl_1` VALUES(NOW());
INSERT INTO `test`.`timestamp_tbl_1` VALUES(NULL);
TRUNCATE TABLE `timestamp_tbl_1`; -- 清空表
TIMESTAMP類型還有一個很大的特色,說是時間是根據時區來顯示的。
須要顯示日期與時間,TIMESTAMP類型可以根據不一樣地區的時區來轉換時間。可是,TIMESTAMP類型的範圍過小。其最大時間爲2038-01-19 11:14:07
4.1.4 字符串類型
字符串類型是在數據庫中存儲字符串的數據類型。字符串類型包括CHAR、VARCHAR、BLOB、TEXT、ENUM、SET。
1. CHAR類型和VARCHAR類型
2. TEXT類型
3. ENUM類型
4. SET類型
4.1.4.1 CHAR類型和VARCHAR類型
CHAR類型和VARCHAR類型都是在建立表是指定最大長度,其基本形式以下:
字符串類型(M)
例如,CHAR(4)就是指數據類型爲CHAR類型,其最大長度爲4。
CHAR類型的長度是固定的,在建立表時就指定了。其長度能夠是0~255的任意值。
例如,CHAR(100)就是指定CHAR類型的長度爲100。
VARCHAR 類型的長度是可變的,在建立時指定了最大長度。定義時,其最大值能夠取0~65535之間的任意值。指定VARCHAR類型的最大值之後,其長度能夠在0 到最大長度之間。例如,VARCHAR(100)的最大長度是100。可是,不是每條記錄都要佔100個位置。而是在這個最大值範圍內,使用多少分配多 少。VARCHAR類型實際佔用的空間爲字符串的實際長度加1。這樣,能夠有效的節約系統的空間。
CHAR(5)與VARCHAR(5)對比
插入值 CHAR(5) 佔用字節數 VARCHAR(5) 佔用字節數
'' '' 5個字節 '' 1個字節
'1' '1' 5個字節 '1' 2個字節
'123' '1' 5個字節 '123' 4個字節
'123 ' '123' 5個字節 '123 ' 5個字節
'12345' '12345' 5個字節 '12345' 6個字節
CHAR(5) 所佔用的空間都是5個字節。這表示CHAR(5)的固定長度就是5個字節。而VARCHAR(5)所佔的字節數是實際長度的基本上加一。由於字符串的結束 標誌符佔用一個字節。從表的第三行能夠看到,VARCHAR將字符串'123 '最後面空格依然保留着。爲了確認空格是否保留,將全部數據後面加上'*'字符。結果顯示以下:
實例一:
CREATE TABLE IF NOT EXISTS `test`.`string_tbl_1`(
`a` CHAR(5),
`b` VARCHAR(5)
);
INSERT INTO `test`.`string_tbl_1`
VALUES('',''),('1', '1'),('123','123'),('123 ', '123 '),('12345', '12345');
SELECT * FROM `string_tbl_1`;
char_part varchar_part
* *
1* 1*
123* 123*
123* 123 *
12345* 12345*
因而可知,VARCHA類型將'123'最後面的空格保留着。而CHAR類型中將'123'後面的空格自動刪除。
4.1.4.2 TEXT類型
TEXT類型是一種特殊的字符串類型。TEXT只能保存字符數據,如文章等。TEXT類型包含TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。
類型 容許的長度 存儲空間
TINYTEXT 0~255字節 值的長度+2個字節
TEXT 0~65535字節 值的長度+2個字節
MEDIUMTEXT 0~167772150字節 值的長度+3個字節
LONGTEXT 0~4294967295字節 值的長度+4個字節
從表能夠看出,各類TEXT類型的區別在於容許的長度和存儲空間不一樣。所以在這幾種TEXT中,根據需求選取既能知足須要以最節約空間的類型便可。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`string_tbl_2`(
`a` CHAR(10),
`b` VARCHAR(20),
`c` TEXT
);
INSERT INTO `test`.`string_tbl_2`
VALUES('','',''),('1', '1','1'),('123','123','123'),('123 ', '123 ', '123 '),('12345', '12345','12345');
SELECT * FROM `string_tbl_2`;
4.1.4.3 ENUM類型(枚舉類型)
ENUM類型又稱爲枚舉類型。在建立表時,ENUM類型的取值範圍就以列表的形式指定了。
屬性名 ENUM('值1', '值2',...., '值n');
其中, '屬性名'參數指定字段名稱;'值n'參數表示列表中的第n個值,這些值末尾的空格將會被系統直接刪除。
ENUm類型的值只能列表中的一個元素。其取值列表中最多能有65535個值。列表中的每一個值都有一個順序排序的編號,MySQL中存入的是這個編號,而不列表中的值。
若是ENUm類型加上了NOT NULL屬性,其默認值爲取值列表的第1個元素。若是不加NOT NULL屬性,ENUm類型將容許插入NULL,並且NULL爲默認值。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`enum_tbl`(
`a` ENUM('male','female'),
`b` ENUM('true','false') NOT NULL
);
INSERT INTO `test`.`enum_tbl`
VALUES('male', 'true'),(NULL, 'false'), (NULL, NULL),(20, 20);
SELECT * FROM `enum_tbl`;
4.1.4.4 SET類型
基本形式以下:
屬性名 set('值1','值2','值3'...'值n');
其中,'屬性名'參數指定字段名稱;'值n'參數列表中的第n個值,這些值末尾的空格將會被系統直接刪除。其基本形式與ENUM類型同樣。
SET類型的值能夠取列表中一個元素或者多個元素的組合。取多個元素時,不一樣元素之間用逗號隔開。SET類型的值最多隻能是64個元素構成的組合。列表中的每個值都有一個順序排列的編號。MySQL中存入的是這個編號,而不是列表中的值。
插入記錄時,SET字段裏的元素順序可有可無。存入MySQL數據庫後,數據庫系統會自動按照定義時的順序顯示。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`set_tbl`(
`a` SET('a','b','c','d','e','f','g')
);
INSERT INTO `test`.`set_tbl` VALUES('f'),('a,b,c'),('d,e,a');
INSERT INTO `test`.`set_tbl` VALUES('h');
SELECT * FROM `set_tbl`;
4.1.5 二進制類型
二進制類型是在數據庫中存儲二進制數據的數據類型。二進制類型包括BINARY、VARBINARY、BIT、TINYBLOB、BLOG、MEDIUMBLOB和LONGBLOG。
1. BINARY和VARBINARY類型
2. BIT類型
3. BLOB類型
二進制類型 取值範圍
BINARY(M) 字節數爲M,容許長度爲0~M的定長二進制字符串
VARBINARY(M) 容許長度爲0~M的變長二進制字符串,
字節數爲值的長度加一
BIT(M) M位二進制數據,M最大值爲64
TINYBLOB 可變長二進制數據,最多255個字節
BLOB 可變長二進制數據,最多(2[16]-1)個字節
MEDIUMBLOB 可變長二進制數據,最多(2[24]-1)個字節
LONGBLOB 可變長二進制數據,最多(2[32]-1)個字節
4.1.5.1 BINARY和VARBINARY類型
BINARY和VARBINARY類型都是在建立表時指定了最大長度,其基本形式以下 :
字符串類型(M)
這與CHAR類型和VARCHAR類型類似。
例如,BINARY(10)就是指數據類型爲BINARY類型,其最大長度爲10。
BINARY類型的長度是固定的,在建立表是就指定了。不足最大長度的空間由"\0"補全。例如,BINARY(50)就是指定BINARY類型的長度爲50。
VARBINARY 類型的長度是可變的,在建立表時指定了最大長度。指定好了VARBINARY類型的最大值之後,基長度能夠在0到最大長度之間。例 如,VARBINARY(50)的最大字節長度是50。可是,不是每條記錄的字節長度都是50。在這個最大範圍內,使用多少分配多少。VARBINARY 類型實際佔用的空間爲實際長度加一。這樣,能夠有效的節約系統的空間。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`binary_tbl`(
`a` BINARY(4),
`b` VARBINARY(4)
);
INSERT INTO `test`.`binary_tbl`
VALUES('d','d');
SELECT length(a), length(b) FROM `test`.`binary_tbl`;
SELECT a, a='d', a='d\0\0\0', b, b='d', b='b\0\0\0' FROM `test`.`binary_tbl`;
4.1.5.2 BIT類型
BIT類型也是建立表時指定了最大長度,其基本形式以下:
BIT(M)
其 中,'M'指定了該二進制的數的最大字節長度爲M,M的最大值爲64。例如,BIT(4)就是數據類型BIT類型,長度爲4.若字段的類型BIT(4), 存儲的數據是從0到15。由於,變成二進制之後,15的值爲1111,其長度爲4。若是插入的值爲16,其二進制數爲10000,長度爲5,超過了最大長 度。所以大於等於16的數是不能插入到BIT(4)類型的字段中的。在查詢BIT類型的數據時,要用BIN(字段名+0)來將值轉換爲二進制顯示。
向表中插入0、八、14等值後,查詢其結果。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`bit_tbl`(
`a` BIT(4)
);
INSERT INTO `test`.`bit_tbl`
VALUES(0),(8),(14);
SELECT * FROM `test`.`bit_tbl`;
SELECT bin(a+0) FROM `test`.`bit_tbl`;
4.1.5.3 BLOB類型
BLOB 類型是一種特殊的二進制類型。BLOB能夠用來保存數據量很大的二進制數據,如圖片等。BLOB類型包括TINYBLOB、BLOB、 MEDIUMBLOB和LONGBLOB。這幾種BLOB類型最大的區別就是可以保存的最大長度不一樣。LONGBLOB的長度最大,TINYBLOB的長 度最小。
BLOB類型與TEXT類型很相似。不一樣點在於BLOB類型用於存儲二進制數據,BLOB類型數據是根據其二進制編碼進行比較和排序。而TEXT類型是文本模式進行比較和排序的。
實例一:
CREATE TABLE IF NOT EXISTS `test`.`bit_tbl`(
`a` BIT(4)
);
INSERT INTO `test`.`bit_tbl`
VALUES(0),(8),(14);
SELECT * FROM `test`.`bit_tbl`;
SELECT bin(a+0) FROM `test`.`bit_tbl`;
4.2 如何選擇數據類型
在MySQ中建立表時,須要考慮爲字段選擇哪一種數據類型是最合適的。選擇合適的數據類型,會提升數據庫的效率。
1. 整數類型和浮點數類型
2. 浮點數類型和定點數類型
3. CHAR類型和VARCHAR類型
4. 時間和日期類型
5. ENUM類型和SET類型
6. TEXT類型和BLOB類型
4.2.1 整數類型和浮點數類型
整 數類型和浮點數類型最大的區別在於可否表達小數。整數類型不能表示小數,而浮點數類型能夠表示小數。不一樣的整數類型的取值範圍不一樣。TINYINT類型的 取值範圍是0~255。若是字段的最大值不超過255,那選擇TINYINT類型就足夠了。BIGINT類型的取值範圍最大,最經常使用的整數類型是INT類 型。
浮點型類型包括FLOAT類型和DOUBLE類型。DOUBLE類型的精度比FLOAT類型高。若是須要精確到小數點後10以上,就應該選擇DOUBLE類型,而不該該選擇FLOAT類型。
4.2.2 浮點類型和定點數類型
對於浮點數和定點數,當插入值的精度高於實際定義的精度,系統會自動進行四捨五入處理。其目的是爲了使該值的精度達到要求。浮點數進行四捨五入不會報警,定點數出現警告。
在未指定精度的狀況下,浮點數和定點數有其默認的精度。FLOAT類型和DOUBLE類型默認會保存實際精度。這個精度與操做系統和硬件的精度有關。DECIMAL類型默認整數位爲10, 小數位爲0,即默認爲整數。
在MySQL中,定點數精度比浮點數要高。並且,浮點數會出現偏差。若是要對數據的精度要求比較高,應該選擇定點數。
4.2.3 CHAR類型和VARCHAR類型
CHAR類型的長度是固定的,而VARCHAR類型的長度是在範圍內可變的。所以,VARCHAR類型佔用的空間比CHAR類型小。並且,VARCHAR類型比CHAR類型靈活。
對於長度變化比較大的字符串類型,最好選擇VARCHAR類型。
雖然,CHAR類型的佔用空間比較大,可是CHAR類型的處理速度比VARCHAR快。所以,對於長度變化不大和查詢速度要求較高的字符串類型,最好選擇CHAR類型。
4.2.4 時間和日期類型
YEAR類型只表示年份。若是要記錄年份,選擇YEAR類型能夠節約空間。TIME類型只表示時間。若是隻須要記錄時間,選擇TIME類型最合適的。DATE類型只表示日期。若是隻須要記錄日期,選擇DATE類型是最合適的。
如 果須要記錄日期和時間,能夠選擇DATETIME和TIMESTAMP類型。DATETIME類型表示的時間範圍比TIMESTAMP類型大。所以,若需 要的時候範圍比較大,選擇DATETIME類型比較合適。TIMESTAMP類型的時間是根據時區來顯示的。若是須要顯示的時間與時區對應,那就應該選擇 TIMESTAMP類型。
4.2.5 ENUM類型和SET類型
ENUm類型最多能夠有65535個成員,而SET類型最多隻能包含64個成員。二者的取值只能在成員列表中選取。ENUM類型只能從成員中選擇一個,而SET類型能夠選擇多個。
所以,對於多個值中選取一個的,能夠選擇ENUM類型。例如,"性別"字段就能夠定義成ENUM類型,由於只能在 "男"和"女"中選取其中一個。對於能夠選取多個值的字段,能夠選擇SET類型。例如,"愛好"字段就能夠選擇SET類型,由於可能有多種愛好。
4.2.6 TEXT類型和BLOB類型
TEXT類型和BLOB類型很相似。TEXT類型只能存儲字符數據。而BLOB類型能夠存儲二進制數據。若是要存儲文章等純文件的數據,應該選擇TEXT類型。若是須要存儲圖片等二進制的數據,應該選擇BLOB類型。
TEXT類型包括TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT類型容許的長度最大。BLOB類型也是如此。
4.3 常見問題及解答
1. MySQL中什麼數據類型可以儲存路徑?
答:MySQL中,CHAR、VARCHAR、TEXT等字符串類型均可以存儲路徑。可是,若是路徑中使用"\"符號時,這個符號會被過濾。解決辦法是,路徑中用"/"或者"\\"來代替"\"。這樣MySQL就不會自動過濾路徑分隔字符,能夠完整的表示路徑。
2. MySQL中如何使用布爾類型?
答: 在SQL標準中,存儲BOOL和BOOLEAN類型。MySQL爲了支持SQL標準,也是能夠定義BOOL和BOOLEAN類型的。可是,BOOL和 BOOLEAN類型最後換成是TINYINT(1)。也就是說,在MYSQL中,布爾類型等價於TINYINT(1)。所以,建立表時將一個字段定義成 BOOL和BOOLEAN類型,數據庫中真實定義的是TINYINT(1)。
CREATE TABLE IF NOT EXISTS `test`.`bool_tbl`(
`a` BOOL,
`b` BOOLEAN
);
INSERT INTO `test`.`bool_tbl`
VALUES(true, false), (false, false), (true, true);
SELECT * FROM `test`.`bool_tbl`;
3. MySQL中如何存儲JPG圖片和MP3音樂?
答:通常狀況下,數據庫中不直接存儲圖片和音樂文件。而是存儲圖片和文件的路徑。若是實在須要在MySQL數據庫中存儲圖片和音頻文件,就選擇BLOB類型。由於,BLOB類型能夠用來存儲二進制類型的文件。
4.4 幫助關鍵字
? show
? select
? datatype
? int
? update
? select
create table cats(
id int not null auto_increment,
pid int not null default 0,
name varchar(60) not null default '',
desn text not null default '',
primary key(id),
index name(name,pid)
) default charset=utf8;
create table products(
id int not null auto_increment,
cid int not null default 0,
name varchar(60) not null default '',
price double(7,2) not null default 0.00,
count int not null default 0,
desn text,
ptim int not null default 0,
primary key(id),
key pname(name,price)
)default charset=utf8;
# 插入數據
insert into cats values(null,0,'soft','this is soft');
insert into cats values(null,1,'java','this is java');
insert into cats values(null,1,'php','this is php');
insert into cats values(null,1,'C++','this is C++');
insert into cats values(null,0,'design','this is design');
insert into cats values(null,5,'ps','this is ps');
insert into cats values(null,5,'ai','this is ai');
# 刪除數據
truncate cats;
# 更新數據
# 查詢數據
SELECT [ALL | DISTINCE]
{*|TABLE.*|[table.]filed1[as alias1][,[table.]filed1[as alias1]][......]}
FROM tableName []
[WHERE ...]
[GROUP BY ...]
[HAVING ...]
[ORDER BY ...]
[LIMIT count]
5.操做數據庫
數據庫是指長期存儲在計算機、有組織的、可共享的數據集合。簡而言之,數據庫就是一個存儲數據的地方。只是,其存儲方式有特定的規律。這樣能夠方便處理數據。數據庫的操做包括建立數據庫和刪除數據庫。這些操做都是數據庫管理的基礎。
- 建立數據庫
- 刪除數據庫
- 數據庫的存儲引擎
- 如何選擇存儲引擎
5.1 建立數據庫
建立數據庫是指在數據庫系統中劃分一塊空間,用來存儲相應的數據。這是進行表操做的基礎,也是進行數據庫管理的基礎。
建立數據庫是經過SQL語言CREATE DATABASE命令實現的。
CREATE DATABASE 數據庫名;
-- MySQL命令以分號(;)或\g結束命令
SHOW DATABASES; -- 用列表顯示全部數據庫
CREATE DATABASE example; -- 建立數據庫
CREATE DATABASE IF NOT EXISTS example; -- 若是沒有example數據庫則建立example數據庫
5.2 刪除數據庫
刪除數據庫是指數據庫系統中刪除已經存在的數據庫。刪除數據庫以後,原來分配的空間將被收回。值得注意的是,刪除數據庫會刪除該數據庫中全部的表和全部數據。
刪除數據庫是經過SQL語句DROP DATABASE命令實現的。
DROP DATABASE 數據庫名
DROP DATABASE IF EXISTS example; -- 若是example數據庫存在的話刪除example數據庫
5.3 數據庫的存儲引擎
MySQL中提到了存儲引擎的概念。簡而方之,存儲引擎就是指表的類型。數據庫存儲引擎決定了表在計算機中的存儲方式。
type=InnoDB
engine=InnoDB
MyISAM:
優勢:
1. OPTIMIZE TABLE 表名; # 整理碎片
2. 強調快速讀取操做
缺點:有一些功能不支持
InnoDB:
優勢:
1. 支持多功能(事務、外鍵)
2. 強調快速讀取操做
缺點:速度不如MyISAM,佔用空間大
5.3.1 MySQL存儲引擎簡介
存儲引擎的概念是MySQL的特色,並且是一種插入式的存儲引擎概念。這決定了MySQL數據庫中的表能夠用不一樣的方式存儲。用戶能夠根據本身的不一樣要求,選擇不一樣的存儲方式、是進行事務處理等。
使用SHOw ENGINES語句能夠查看MySQL數據庫支持的存儲引擎類型。
SHOW ENGINES \G
Engine : MyISAM
Support: YES
Comment: Default Engine at of MySQL 3.23 with great performance(描述說明)
Transaction: NO (是否支持事務)
XA: NO (是不否支持分佈式XA規範)
Savepoints: NO (是否支持保存點)
SHOW VARIABLES LIKE 'have%';
SHWO VARIABLES LIKE 'storage_engine'; # 數據庫默認引擎[storage:存儲]
1. 能夠在mysql.ini配置文件中修改數據庫默認引擎
default-storage-engine = INNODB
5.3.2 InnoDB存儲引擎
InnoDB 是MySQL數據庫的一個存儲引擎。InnoDB給MySQL的表提供了事務、回滾、崩潰修復能力、多版本併發控制的事務安全。在MySQL從 3.23.34a開始包含InnoDB存儲引擎。InnoDB是MySQL上第一個提供外鍵約束的引擎。並且InnoDB對事務處理的能力,也是 MySQL其餘存儲引擎所沒法與之比擬的。
(1)InnoDB存儲引擎中支持自動增加列(AUTO_INCREMET)
自 動增加列的值不能爲空,且值必須唯一。MySQL中規定自增列必須爲主鍵。在插入值時,若是自動增加列不輸入值,則插入的值爲自動增加後的值;若是輸入的 值爲0或者空(NULL),則插入的值也爲自動增加後的值;若是插入某個肯定的值,且該值在前面沒有出現過,則能夠直接插入。
(2) InnoDB存儲引擎中支持外鍵(FOREIGN KEY)
(3) InnoDB存儲引擎中,建立表的表結構存儲在.frm文件中。數據和索引存儲innodb_data_home_dir和innodb_data_file_path定義的表空間中。
(4) InnoDB存儲引擎的優點在於提供良好的事務管理、崩潰修復能力和併發控制。
缺點是讀寫效率稍差,佔用的數據空間相對比較大。
5.3.3 MyISAM存儲引擎
MyISAM存儲引擎是MySQL中常見的存儲引擎,是之前MySQL的默認存儲引擎。MyISAM存儲引擎是基於ISAM存儲引擎發展起來的。MyISAM增長了不少用的擴展。
MyISAM存儲引擎的表存儲成三個文件。文件的名字與表名相同。擴展名包括frm、MYD和MYI。其中frm爲擴展名的文件存儲表的結構;MYD爲擴展名的文件存儲數據,基是MYData的縮寫;MYI爲擴展名的文件存儲索引,其是MyIndex的縮寫。
MyISAM存儲引擎的優點在於佔用空間小、處理速度快。
缺點是不支持事務的完整性和併發性。
5.3.4 MEMORY存儲引擎
MEMORY存儲引擎是MySQL中的一個特殊的存儲引擎。基使用存儲在內存中內容來建立表,並且全部數據也放在內存中。這些特性都與InnoDB存儲引擎、MyISAM存儲引擎不一樣。
每 個基於MEMORY存儲引擎的表實際對應一個磁盤文件。該文件的文件名與表名相同,類型爲frm類型。該文件的只存儲表的結構。而其數據文件,都是存儲在 內存中。這樣有利於對數據的快速的處理,提升整個表的處理效率。值得注意的是,服務器須要有足夠的內存來維持MEMORY存儲引擎的表的使用。若是不須要 使用了,能夠釋放這些內存,甚至能夠刪除不須要的表。
MEMORY表的大小是受到限制的。表的大小主要取決於兩個參數,分別是max_rows和max_heap_table_size。
5.3.5 存儲引擎的選擇
在實際工做中,選擇一個合適的存儲引擎是一個很複雜的問題。每種存儲引擎都有各自的優點,不能籠統的說誰比誰好。
存儲引擎的對比
特性 InnoDB MyISAM MEMORY
事務安全 支持 不支持 不支持
數據行鎖定 支持 不支持 不支持
外鍵約束 支持 不支持 不支持
存儲限制 64TB 有 有
空間佔用 高 低 低
全文索引 不支持 支持 不支持
內存使用 高 低 高
插入數據的速度 低 高 高
對外鍵的支持 支持 無 無
5.4 MySQL字符集
gb2312-80(雙字節6700個) 不推薦
gb13000(93年-23700多個) 不推薦
GBK 能夠用,不推薦
GB18030(2000年) 數據庫支持比較少
ANSI
ISO-8859-1/latin1
UTF-32
USC-2
UTF-16
UTF-8(1-4字節) 強調推薦
GBK 2個字節 UTF8 3個字節
name varchar(12) 6個漢字 GBK
name varchar(12) 4個漢字 UTF8
MySQL服務器,數據庫,數據表和字段
show character set;
數據庫中utf-8 => utf8
desc information_schema.character_sets;
MySQL的字符集包括:
字符集:用來定義MySQL存儲字符串的方式 36個
校對規則:比較字符串的關係 70
一對多的關係:1個字符集能夠對應多個校對規則
show collation like 'gbk%';
show collation like 'utf%';
gbk_chines_ci # ci:不區分大小寫 cs:區分大小寫
gbk_bin # bin: 二進制比較
\s
show variables like 'character_set_server';
show variables like 'collation_server';
# 保存數據是的字符集
create database demo default character set gbk collate gbk_chinese_ci;
create table t(id int) engine=InnoDB default character set gbk collate gbk_chinese_ci;
# 客戶端與服務器端交互時:
character_set_client # 客戶端字符集
character_set_connection # 鏈接字符集
character_set_results # 結果字符集
set names 字符集 同時修改以上三個的值
set names gbk;
alter database character set gbk;
alter table t character set utf8;
mysqldump -u root -p --default-character-set=gbk -d demo > c:/demo01.sql
5.5 本章實例
學校須要創建信息化的管理,必需要創建一個信息完備的數據庫系統。這個數據庫系統中存儲着學校的老師、學生、課程安排、考試成績等各類信息。創建一個名爲school的數據庫
1. 登陸數據庫系統
2. 查看已存在的數據庫
3. 查看默認存儲引擎
4. 建立數據庫
5. 刪除數據庫
Start:
1. mysql -h localhost -u root -p
2. SHOW DATABASES; -- 查看全部數據庫
3. SHOW ENGINES \g # 查看全部的存儲引擎
SHOW VARIABLES LIKE 'storage_engine'; /* 查看默認的存儲引擎 */
4. CREATE DATABASE [IF NOT EXISTS] school; # 若是沒有school數據庫建立school數據庫
5. SHOW DATABASES;
6. DROP DATABASE [IF EXISTS] school; -- 刪除school數據庫
5.6 上機實踐
題目要求:登陸數據庫系統之後,建立一個student數據庫和teacher數據庫。而後再刪除teacher數據庫。而後查看數據庫系統中還存在哪些數據庫。
過程以下:
(1) 登陸數據庫
(2) 查看數據庫系統中已存在的數據庫
(3) 查看該數據庫系統支持的存儲引擎類型
(4) 建立一個student數據庫和teacher數據庫
(5) 再次查看數據庫系統中已經存在的數據庫,確保student和teacher已經存在。
(6) 刪除teacher數據庫
(7) 再次查看數據庫系統已經存在的數據庫,確保teacher數據庫已經刪除。
(8) 刪除student數據庫
(9) 再次查看數據庫系統已經存在的數據庫,確保student數據庫已經刪除。
Start:
1. mysql -h localhost -u root -p
2. SHOW DATABASES;
3. SHOW ENGINES \G
4. CREATE DATABASE [] student \g
5. CREATE DATABASE [] teacher \g
6. SHOW DATABASES;
7. DROP DATABASE [IF EXISTS] teacher;
8. SHOW DATABASES;
7. DROP DATABASE [IF EXISTS] student;
8. SHOW DATABASES;
5.7 常見問題及解答
1. 如何修改默認存儲引擎?
(1) 使用配置嚮導,修改默認存儲引擎。
(2) 修改配置文件my.ini,default_storage_engine=INNODB修改便可
2. 如何選擇存儲引擎?
CREATE TABLE `test`.`test` (
`a` INT NOT NULL
) ENGINE = MYISAM ;
5.8 本章習題
1. 練習在MySQL數據庫系統中建立一個名爲worker的數據庫。建立成功後,刪除該數據庫。
2. 練習用三種不一樣的方法找出你所使用的MySQL數據庫默認存儲引擎。
3. 存儲引擎InnoDB、MyISAM和MEMORY各有什麼優缺點?
6.建立、修改和刪除表
表是數據庫存儲數據的基本單位、一個表包含若干個字段或記錄、表的操做包括建立新表、修改表和刪除表。這些操做都是數據庫管理中最基本,也是最重要的操做。在這一章中將講解如何在數據庫中操做表。
- 建立表方法
- 表的完整性約束條件
- 查看錶結構的方法
- 修改表的方法
- 刪除表的方法
6.1 建立表方法
建立表是指在已存在的數據庫中創建新表。這是創建數據庫最重要的一步,是進行其餘操做的基礎。
6.1.1 建立表的語法形式
MySQL中,建立表是經過SQL語句CREATE TABLE實現的。
CREATE TABLE 表名(
屬性名 數據類型 [完整性約束條件],
屬性名 數據類型 [完整性約束條件],
......
屬性名 數據類型 [完整性約束條件],
)[表類型] [表字符集];
SQL是不區分大小寫
命名規範:
1. 命名富有意義(英文或英文組合)
2. 自定義名稱使用小寫
3. MySQL語句使用大寫
1. mysql -h localhost -u root -p
2. SHOW DATABASES;
3. CREATE DATABASE IF NOT EXISTS example
4. CREATE TABLE IF NOT EXISTS text1 (
id INT,
name VARCHAR(20);
gender BOOLEAN,
) Engine = MyISAM;
5. DESCRIBE test1 \g -- 查看example表的結構
完整性約束條件表
PRIMARY KEY 標識該屬性爲該表的主鍵,能夠惟一的標識對應的元組
FOREIGN KEY 標識該屬性爲該表的外鍵,是與之聯繫的某表的主鍵
NOT NULL 標識該屬性不能爲空
UNIQUE 標識該屬性的值是惟一的
AUTO_INCREMENT 標識該屬性的值自動增長,這是MySQL的SQL語句的特點(null,0)
DEFAULT 標識該屬性設置默認值(not null defualt 0,not null default 0.0,not null default '')
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMAKRY KEY,
name VARCHAR(20) NOT NULL DEFUALT '',
height DOUBLE(10,2) NOT NULL DEFAULT 0.00,
age INT NOT NULL DEFUALT 0,
sex CHAR(4) NOT NULL DEFAULT '男',
6.1.2 設置表的主鍵
主鍵是表的一個特殊字段。該字段能唯一地標識該表中的每條信息。主鍵和記錄的關係,如同身份證和人的關係。主鍵用來標識每一個記錄,每一個記錄的主鍵值都不一樣。身份證是用來標明人的身份,每一個人都具備唯一的身份證號。設置表的主鍵指在建立表時設置表的某個字段爲該表的主鍵。
主鍵的主要目的是幫組MySQL以最快的速度查找到表中的某一條信息。
主鍵必須知足的條件:
1. 主鍵必須是惟一的,表中任意兩條記錄的主鍵字段的值不能相同;
2. 主鍵的值是非空值;
3. 主鍵能夠是單一的字段,也能夠是多個字段組合。
1. 單字段的主鍵:
CREATE TABLE student1 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB;
SHOW TABLES;
DESCRIBE student1;
2. 多字段主鍵:
CREATE TABLE student2 (
stu_id INT,
course_id INT,
grade FLOAT,
PRIMARY KEY(stu_id, course_id)
)Engine = InnoDB;
6.1.3 設置表的外鍵
外鍵是表的一個特殊字段。若是字段sno是一個表A的屬性,且依賴於表B的主鍵。那麼,稱表B爲父表,表A爲子表,sno爲表A的外鍵。經過sno字段將父表B和子表A創建關聯關係。設置表的外鍵指在建立表設置某個字段爲外鍵。
設置外鍵的原則:必須依賴於數據庫中已存在的父表的主鍵;外鍵能夠爲空值。
外 鍵的做用: 是創建該表與其父表的關聯關係。父表中刪除某條信息時,子表中與之對應的信息也必須有相應的改變。例如,stu_id就student表的主 鍵,stu_id是grade表的外鍵。當stu_id爲'123'同窗退學了,須要從student表中刪除該學生的信息。那麼,grade表中 stu_id爲'123'的全部信息也應該同時刪除。
CONSTRAINT 外鍵別名 FOREIGN KEY (屬性1.1, 屬性1.2...屬性1.n);
REFERENCES 表名(屬性2.1, 屬性2.2,...,屬性2.n)
CREATE TABLE student3 (
id INT PRIMARY KEY,
stu_id INT,
course_id INT,
# 設置外鍵
CONSTRAINT C_fk FOREIGN KEY(stu_id, course_id) REFERENCES student2(stu_id, course_id)
) Engine = InnoDB;
6.1.4 設置表的非空約束
非 空性是指字段的值不能爲空值(NULL)。非空約束將保證全部記錄中該字段都有值。若是用戶新插入的記錄中,該字段爲空值,則數據庫系統會報錯。例如,在 id字段加上非空約束,id字段的值就不能爲空。若是插入記錄的id字段的值爲空,該記錄將不能插入。設置表的非空約束是指在建立表時爲表的某些特殊字段 加上NOT NULL約束條件。設置非空約束的基本語法規則以下:
屬性名 數據類型 NOT NULL
CREATE TABLE student4 (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20) NOT NULL,
stu_id INT,
CONSTRAINT d_fk FOREIGN KEY(stu_id) REFERENCES student2(stu_id)
);
6.1.5 設置表的唯一性約束
唯 一性是指全部記錄中該字段的值不能重複出現。設置表的唯一性約束是指在建立表時爲表的某些特殊字段加上UNIQUE約束條件。惟一性約束將保證全部記錄中 該字段的值不能重複出現。例如,在id字段加上唯一性約束,因此記錄中id字段上不能出現相同的值。例如,在表的id字段加上唯一性約束,那麼每條記錄的 id值都是唯一的,不能出現重複的狀況。若是一條的記錄的id值都是唯一的,不能出現重複的狀況。若是一條的記錄的id爲'0001',那麼該表中就不能 出現另外一條記錄的id爲'0001'。設置唯一性約束的基本語法規則以下:
屬性名 數據類型 UNIQUE
CREATE TABLE student5 (
id INT NOT NULL PRIMARY KEY,
stu_id INT UNIQUE,
name VARCHAR(20) NOT NULL
);
INSERT INTO `student5` values(1, 10, 'Sue'), (2, 11, 'Lucy');
INSERT INTO `student5` values(2, 10, 'Jack');
6.1.6 設置表的屬性值自動增長
AUTO_INCREMENT 是MYSQL數據庫中一個特殊的約束條件。其主要用於爲表中插入的新記錄自動生成唯一的ID。一個表只能有一個字段使用AUTO_INCREMENT約 束,且該字段必須爲主鍵的一部分。AUTO_INCREMENT約束的字段能夠是任何整數類型(TINYINT、SMALLINT、INT、BIGINT 等)。默認狀況下,該字段的值是從1開始自增。
設置屬性值字段增長的基本語法規則以下:
屬性名 數據類型 AUTO_INCREMENT
CREATE TABLE student6 (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
stu_id INT UNIQUE,
name VARCHAR(20) NOT NULL
);
INSERT INTO `student6` values('', 10, 'Sue'), ('', 11, 'Lucy');
INSERT INTO `student6` values('', 12, 'Jack');
6.1.7 設置表的履的默認值
在建立表時能夠指定表中字段的默認值。若是插入一條新的記錄時沒有爲這個字段賦值,那麼數據庫系統會自動爲穿上字段插入默認值。默認值經過DEFAULT關鍵字來設置的。
屬性名 數據類型 DEFAULT 默認值
CREATE TABLE student7 (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
stu_id INT UNIQUE,
name VARCHAR(20) NOT NULL DEFAULT 'WHAT',
language VARCHAR(20) DEFAULT 'cn',
english VARCHAR(20) DEFAULT 'ZERO',
math FLOAT DEFAULT 0,
computer FLOAT DEFAULT 0
);
INSERT INTO `student7` VALUES('',10,'Sue', 'kr', 'one','','');
INSERT INTO `student7` VALUES('',11,'Jack', '', '','','');
6.2 查看錶結構
查看錶結構是指查看數據庫中已存在的表的定義。查看錶結構的語句包括DESCRIBE語句和SHOW CREATE TABLE語句。經過這兩個語句,能夠查看錶的字段名、字段的數據類型、完整性約束條件等。
6.2.1 查看錶基本結構語句DESCRIBE
MySQL中,DESCRIBE語句能夠查看錶的基本定義。其中包括、字段名、字段數據類型、是否爲主鍵和默認值等。
DESCRIBE 表名;
DESC或DESCRIBE student7;
6.2.2 查看錶詳細結構語句SHOW CREATETABLE
MySQL中,SHOW CREATE TABLE語句能夠查看錶的詳細定義。該語句能夠查看錶的字段名、字段的數據類型、完整性約束條件等信息。除此以外,還能夠查看錶默認的存儲引擎和字符編碼。SHOW CREATE TABLE語句的語法形式以下:
SHOW CREATE TABLE 表名;
SHOW CREATE TABLE student7;
6.3 修改表的方法
修 改表是指修改數據庫中已存在的表。修改表比從新定義表簡單,不須要從新加載數據,也不會影響正在進行的服務。MySQL中能過ALTER TABLE [alter:改變,更改]語句來修改表。修改表包括修改表名、修改字段數據類型、修改字段名、增長字段、刪除字段、修改字段的排列位置、更改表的存儲引 擎和刪除表的外鍵約束等。
6.3.1 修改表名
表 名能夠在一個數據庫中惟一的肯定一張表。數據庫系統經過表名來區分不一樣的表。例如,數據庫school中有student表。那麼student表就是惟 一的。在數據庫school中不可能存在另外一個名爲"student"的表。MySQL中,修改表名是經過SQL語句ALTER TABLE實現的。其語法形式以下:
ALTER TABLE 舊錶名 RENAME [TO] 新表名;
實例一:
CREATE TABLE student8 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB;
SHOW TABLES;
DESCRIBE student8;
ALTER TABLE student8 RENAME TO student8_changed;
6.3.2 修改字段的數據類型
字 段的數據類型包括整型、浮點數型、字符串型、二進制類型、日期和時間類型等。數據類型決定了數據的存儲格式、約束條件和有效範圍。表中每一個字段都有數據類 型。ALTER TABLE語句也能夠修改字段的數據類型。其基本語法以下:ALTER TABLE 表名 MODIFY 屬性名 數據類型;
實例一:
CREATE TABLE student9 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
content VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE student9 MODIFY stu_name char(20);
6.3.3 修改字段名[字段的數據類型, 完整性約束條件]
字 段名能夠在一張表中惟一肯定一個字段。數據庫系統經過字段名來區分表中的不一樣字段。例如,student表中包含id字段。那麼,id字段在 student表中是惟一的。student表中不可能存在另外一個名爲"id"的字段。MySQL中ALTER TABLE語句也能夠修改表的字段名。其基本語法以下:
ALTER TABLE 表名 CHNAGE 舊字段名 新字段名 新數據類型 [新完整性約束條件];
其中,"舊字段名"參數指修改前的字段名;"新字段名"參數指修改後的字段名;"新數據類型"參數修改後的數據類型,如不須要修改,則將新類型設置成與原來同樣。
1. 只修改字段名
2. 修改字段名和字段數據類型
3. 修改完整性約束條件
實例一:
CREATE TABLE student10 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
content VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE student10 CHANGE stu_name stu_name_changed VARCHAR(20);
ALTER TABLE student10 CHANGE content content_changed VARCHAR(50) NOT NULL DEFAULT 'XXXX';
6.3.4 增長字段
在建立表時,表中的字段就已經定義完成。若是要增長新的字段,能夠經過ALTER TABLE語句進行增長。
MySQL中,ALTER TABLE語句增長字段的基本語法以下:
ALTER TABLE 表名 ADD 新字段名 數據類型 [完整性約束條件] [FIRST | AFTER 已有字段名];
1. 增長無完整性約束條件的字段
2. 增長有完整性約束條件的字段
3. 表的第一個位置增長字段
4. 表的指定位置以後增長字段
實例一:
CREATE TABLE student11 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
content VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE student11 ADD phone VARCHAR(20);
ALTER TABLE student11 ADD birthday TIMESTAMP NOT NULL;
ALTER TABLE student11 ADD num INT(11) NOT NULL FIRST;
ALTER TABLE student11 ADD address VARCHAR(30) NOT NULL AFTER phone;
6.3.5 刪除字段
刪 除字段是指刪除已經定義好的表中的某個字段。在表建立好以後,若是發現某個字段須要刪除。能夠採用將整個表都刪除,若是發現某個字段須要刪除。能夠採用將 整個表都刪除,而後從新建立一張表的作法。這樣作是能夠達到目的,但必須會影響到表中的數據。並且,操做比較麻煩。MySQL中,ALTER TABLE語句也能夠刪除表中的字段。其基本語法以下:
ALTER TABLE 表名 DROP 字段名;
實例一:
CREATE TABLE student12 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
content VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE student12 DROP `content`;
6.3.6 修改字段的排列位置
創 建表的時候,字段在表中的排列位置就已經肯定了。若是要改變字段在表中的排列位置,則須要ALTER TABLE語句來處理。MySQL中,修改字段排列位置的ALTER TABLE語句的基本語法以下:ALTER TABLE 表名 MODIFY 字段名 數據類型 FIRST | AFTER 字段名2;
1. 字段修改到第一個位置
2. 字段修改到指定位置
實例一:
CREATE TABLE student13 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
content VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE student13 MODIFY content VARCHAR(20) FIRST;
ALTER TABLE STUDENT13 MODIFY stu_id INT AFTER stu_name;
6.3.7 更改表的存儲引擎
MySQL 存儲引擎是指MySQL數據庫中表的存儲類型。MySQL存儲引擎包括InnoDB、MyISAM、MEMORY等。不一樣的表類型有着不一樣的優缺點。在創 建表的時候,存儲引擎就已經設定好了。若是要改變,能夠經過從新建立一張表來實現。這樣作是能夠達到目的,但必然會影響到表中的數據。並且,操做比較麻 煩。
ALTER TABLE 表名 ENGINE=存儲引擎名;
實例一:
CREATE TABLE student14 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
content VARCHAR(20) NOT NULL,
stu_gender BOOLEAN
) Engine = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE student14 ENGINE=MyISAM;
6.3.8 刪除表的外鍵約束
外鍵是一個特殊字段,其將某一個表與其父表創建關係關係。在建立表的時候,外鍵約束就已經設定好了。因爲特殊須要,與父表之間的關係關係須要去除,要求刪除外鍵約束。MySQL中,ALTER TABLEy語句也能夠刪除表的外鍵約束。
ALTER TABLE 表名 DROP FOREIGN KEY 外鍵別名;
實例一:
CREATE TABLE `student15` (
`id` INT NOT NULL PRIMARY KEY,
`name` VARCHAR(20) NOT NULL,
`stu_id` INT,
CONSTRAINT st_fk FOREIGN KEY(stu_id) REFERENCES student7(stu_id)
) Engine = InnoDB ;
ALTER TABLE `test`.`student15` DROP FOREIGN KEY st_fk;
6.4 刪除表的方法
刪除表是指刪除數據庫已經存在的表。刪除表時,會刪除表中的全部數據。所以,在刪除表時特別注意。MySQL中經過DROP TABLE語句來刪除表。由建立表時可能存在外鍵約束,一些表成爲了與之關聯的表的父表。要刪除這些父表,狀況比較複雜。
6.4.1 刪除沒有關係的普通表和被其餘關聯的父表的方法。
CREATE TABLE student16 (
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
content VARCHAR(20) NOT NULL COMMENT '內容',
stu_gender BOOLEAN
) Engine = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
DROP TABLE [IF EXISTS] student16;
2.刪除被其餘表關聯的父表
數據庫中某些表之間創建了關聯關係。一些表成爲了父表,這些表被其子表關聯着。要刪除這些父表,狀況不像上一節那麼簡單。
CREATE TABLE `test`.`student17_parent` (
`id` INT NOT NULL PRIMARY KEY,
`stu_id` INT,
`name` VARCHAR(20) NOT NULL
) Engine = InnoDB ;
CREATE TABLE `student17_child` (
`id` INT NOT NULL PRIMARY KEY,
`stu_id` INT UNIQUE,
`name` VARCHAR(20) NOT NULL,
CONSTRAINT parent_fk FOREIGN KEY(stu_id) REFERENCES student17_parent(id) -- id必須是帶有索引
) Engine = InnoDB;
DROP TABLE `student17_parent`; -- 不能刪除,由於與這關聯的表有外鍵
# 先刪除外鍵,而後就能夠刪除表student17_parent
ALTER TABLE `student17_child` DROP FOREIGN KEY parent_fk;
DROP TABLE `student17_parent`;
6.5 本章實例
在example數據庫建立一個student表和一個grade表。
1. 登陸數據庫系統
2. 選擇example數據庫
3. 建立student表和grade表
4. 將grade表的course字段的數據類型改成VARCHAR(2)
5. 將s_num字段的位置改到course字段的前面
6. 將grade字段更名爲score
7. 刪除grade表的存儲引擎更改成MyISAM類型
8. 將grade表的存儲引擎更改成MyISAM類型
9. 將student表的address字段刪除
10.在studnet表中增長名爲phone的字段
11.將grade表更名爲gradeInfo
12.刪除student表
6.6 上機實踐
1. 操做teacher表
題目要求:本題將school數據庫建立一個teacher表。
teacher表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 編號 INT(4) 是 否 是 是 是
num 教工號 INT(10) 否 否 是 是 否
name 姓名 VARCHAR(20) 否 否 是 否 否
gender 姓別 TINYINT(1) 否 是 是 否 否
birthday出生日期 DATETIME/INT(11)否 否 否 否 否
address 家庭住址 VARCHAR(50) 否 否 否 否 否
按照下表要求進行操做:
(1) 建立數據庫school
(2) 建立teacher表
(3) 將teacher表的name字段的數據類型改成VARCHAR(30)
(4) 將birthday字段的位置改到gender字段的前面
(5) 將num字段更名爲t_id
(6) 將teacher表的address字段刪除
(7) 在teacher表中增長名爲wages的字段,數據類型爲FLOAT
(8) 將birthday字段類型改成DATE
(9) 將teacher表更名爲teacherInfo
(10) 將teacher表的存儲引擎更必爲MyISAM類型
/*
CREATE DATABASE IF NOT EXISTS school;
USE school;
CREATE TABLE IF NOT EXISTS teacher(
id INT(4) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT COMMENT '編號',
num INT(10) NOT NULL UNIQUE COMMENT '教工號',
name VARCHAR(20) NOT NULL COMMENT '姓名',
gender TINYINT(1) NOT NULL COMMENT '姓別',
birthday DATETIME COMMENT '出生日期',
address VARCHAR(50) COMMENT '家庭住址'
) Engine=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `school`.`teacher` MODIFY name VARCHAR(30);
ALTER TABLE `school`.`teacher` MODIFY birthday DATETIME AFTER name;
ALTER TABLE `school`.`teacher` CHANGE num t_id INT(10);
ALTER TABLE `school`.`teacher` DROP address;
ALTER TABLE `school`.`teacher` ADD wages FLOAT;
ALTER TABLE `school`.`teacher` MODIFY birthday DATE;
ALTER TABLE `teacher` RENAME teacherInfo;
SHOW GREATE TABLE teacher \G
ALTER TABLE `teacherInfo` ENGINE=MyISAM;
*/
2. 操做department表和worker表
題目要求:本題將example數據庫建立一個department表和一個worker表。
department表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
d_id 部門號 INT(4) 是 否 是 是 否
d_name 部門名 VARCHAR(20) 否 否 是 是 否
function部門職能 VARCHAR(50) 否 否 否 否 否
address 部門位置 VARCHAR(50) 否 否 否 否 否
workder表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 編號 INT(4) 是 否 是 是 是
num 員工編號 INT(10) 否 否 是 是 否
d_id 部門號 INT(50) 否 是 否 否 否
name 姓名 VARCHAR(20) 否 否 是 否 否
gender 姓別 BOOLEAN 否 否 是 否 否
birthday出生日期 DATE 否 否 否 否 否
address 家庭住址 VARCHAR(50) 否 否 否 否 否
按照下列要求進行表操做:
(1) example數據庫下建立department表和worker表
(2) 刪除department表
CREATE DATABASE IF NOT EXISTS example;
USE example;
CREATE TABLE IF NOT EXISTS department(
d_id INT(4) NOT NULL UNIQUE PRIMARY KEY COMMENT '部門號',
d_name VARCHAR(20) NOT NULL UNIQUE COMMENT '部門名',
`function` VARCHAR(50) COMMENT '部門職能',
address VARCHAR(50) COMMENT '家庭住址'
) Engine=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE IF NOT EXISTS worker(
id INT(4) NOT NULL UNIQUE PRIMARY KEY COMMENT '編號',
num INT(10) NOT NULL UNIQUE COMMENT '員工編號',
d_id INT(50) NOT NULL COMMENT '部門號',
name VARCHAR(20) NOT NULL COMMENT '姓名',
gender TINYINT(1) NOT NULL COMMENT '姓別',
birthday DATE COMMENT '出生日期',
address VARCHAR(50) COMMENT '家庭住址',
CONSTRAINT w_fk FOREIGN KEY(d_id) REFERENCES department(d_id) # 外鍵
) Engine=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
DROP TABLE IF EXISTS department; -- 不能刪除department表
# 刪除外鍵
ALTER TABLE worker DROP FOREIGN KEY w_fk;
DROP TABLE IF EXISTS department;
6.7 常見問題及解答
1. 字段更名後,爲何會有部分約束條件丟失?(change:須要設置原字段約束條件)
2. 如何設置外鍵? (CONSTARINT fk_name FREIGN KEY(filed_name) REFEREANCE P_TBL_NAME(p_fld_name));
3. 爲何自增字段不能設置默認值?
4. 如何刪除父表?(1.先刪除子表外鍵,而後再刪除父表)
7.索引
索引是一種特殊的數據庫結構,能夠用來快速查詢數據庫中的特定記錄。索引是提升數據庫性能的重要方式。MySQL中,全部的數據類型均可以被索引。MySQL的索引包括普通索引、唯一性索引、全文索引、單列索引、多列索引和空間索引等。
- 索引的含義和特色
- 索引的分類
- 如何設計索引
- 如何建立索引
- 如何刪除索引
7.1 索引簡介
索引由數據庫表中一列或多列組合而成,其做用是提升對數據的查詢速度。
本章將詳細講解索引的含義、做用、分類和設計索引的原則。
7.1.1 索引的含義和特色
索引是建立在表上的,是對數據庫中一列或多列的值進行排序的一種結構。索引能夠提升查詢的速度。本小節將詳細講解索引的含義、做用、優缺點。索引有明顯的優點,也有其不可避免的缺點。
索引的優勢和缺點
- 索引的優勢:
能夠提升檢索數據的速度,這是建立索引的最主要的緣由;對於有依賴關係的子表和父表之間聯合查詢時,能夠提升查詢速度;使用分組和排序子句進行數據查詢時,一樣能夠顯著節省查詢中分組和排序的時間。
- 索引的缺點:
建立和維護索引須要耗費時間,耗費時間的數量隨着數據量的增長而增長;索引須要佔用物理空間,每個索引要佔必定的物理空間;增長、刪除和修改數據時,要動態的維護索引,形成數據的維護速度下降了。
7.1.2 索引的分類
7.1.2.1 普通索引
在建立普通索引時,不附加任何限制條件。這類索引能夠建立在任何數據類型上,其值是否惟一和非空由字段自己的完整性約束條件決定。創建索引之後,查詢時能夠經過索引進行查詢。
7.1.2.2 唯一性索引
使用UNIQUE參數能夠設置索引爲唯一性索引。在建立唯一性索引時,限制該索引的值必須是唯一的。經過唯一性索引,能夠更快速的肯定某條記錄。主鍵就是一種特殊唯一性索引。
7.1.2.3 全文索引
使用FULLTEXT參數能夠設置索引爲全文索引。全文索引只能建立在CHAR、VARCHAR、TEXT類型的字段上。查詢數據量較大的字符串類型字段時,使用全文索引能夠提升查詢速度。(如新聞內容)
7.1.2.4 單列索引
在表中的單個字段上建立索引。單列單過只根據該字段進行索引。單列索引能夠是普通索引,也能夠是唯一性索引,還能夠是全文索引。只要保證索引只對應一個字段便可。
7.1.2.5 多列索引
多 列索引是在表的多個字段上建立一個索引。該索引指向建立時對應的多個字段,能夠經過這幾個字段進行查詢。可是,只有查詢條件中使用這些字段中第一個字段 時,索引纔會被使用。例如,在表中的id、name和gender字段上創建一個多列索引,那麼,只能查詢條件使用了id字段時該索引纔會被使用。
7.1.2.2 空間索引
使 用SPATIAL參數能夠設置索引爲空間索引。空間索引只能創建在空間數據類型上,這樣能夠提升系統獲取空間數據的效率。空間數據類型包括 CEOMETRY、POINT、LINESTRING、POLYGON等。目前只有MyISAM存儲引擎支持空間檢索。這類索引不多會用到。
7.1.3 索引的設計原則
爲了使索引的使用效率更高,在建立索引的時候必須考慮在哪些字段上建立索引和建立什麼類型的索引。
1. 選擇唯一性索引
唯一性索引的的值是唯一的,能夠更快的經過該索引來肯定某條記錄。例如,學生表中學號是具備唯一性的字段。爲該字段創建唯一性索引能夠很快的肯定某個學生的信息。若是使用姓名的話,可能存在同名現象,從而下降查詢速度。
2. 爲常常須要排序、分組和聯合操做的字段創建索引
常常須要排序、分組和聯合操做的字段,排序操做會浪費不少時間。若是爲其創建索引,能夠有效地避免排序操做。
3. 爲常做爲查詢條件的字段創建索引
若是某個字段常常用來作查詢條件,那麼該字段的查詢速度會影響整個表的查詢速度。所以,爲這樣的字段創建索引,能夠提升整個表的查詢速度。
4. 限制索引的數目
索引的數目不是越多越好。每一個索引都須要佔用磁盤空間,索引越多,須要的磁盤空間越大。修改表時,對索引的重構和更新很麻煩。越多的索引,會使更新表變得很浪費時間。
5. 儘可能使用數據量少的索引
若是索引的值很長,那麼查詢的速度會受到影響。例如,對一個CHAR(100)類型的字段進行全文檢索須要時間確定要比對CHAR(10)類型字段須要的時間要多。
6. 儘可能使用前綴來索引
若是索引字段的值很長,最好使用值的前綴來索引。例如,TEXT和BLoB類型的字段,進行全文檢索會浪費時間。若是隻檢索字段的前面的若干個字符,這樣能夠提升檢索速度。
7. 刪除再也不使用或者不多使用的索引
表中的數據被大量更新,或者數據的使用方式被改變後,原有的一些索引可能再也不被須要。數據庫管理員應當按期找出這些索引,將它們刪除,人而減小索引對更新操做的影響。
7.2 建立索引
建立索引是指在某個表的一列或多列上創建一個索引,以便提升對錶的訪問速度。建立索引有三種方式,這三種方式分別是建立表的時候建立索引、在已經存在的表上建立索引和使用ALTER TABLE語句來建立索引。
7.2.1 建立表的時候建立索引
建立表的時候能夠直接建立索引。
CREATE TABLE 表名(
字段名 數據類型[完整性約束條件],
字段名 類型類型[完整性約束條件]
);
index和key是同義詞
1. 建立普通索引
CREATE TABLE index_tbl_1 (
id INT,
name VARCHAR(20),
gender BOOLEAN,
INDEX(id)
);
2. 建立唯一性索引(用戶表的姓名字段上)
CREATE TABLE index_tbl_2 (
id INT UNIQUE,
name VARCHAR(20),
gender BOOLEAN,
UNIQUE INDEX unique_idx(id ASC) -- 通常不須要創建惟一性索引
);
3. 建立全文索引
CREATE TABLE index_tbl_3 (
id INT,
info VARCHAR(20),
FULLTEXT INDEX idx_info(info)
) ENGINE=MyISAM; -- MyISAM存儲引擎才能支持全文索引
4. 建立單列索引
CREATE TABLE index_tbl_4 (
id INT,
subject VARCHAR(30),
INDEX idx_sbj(subject(10))
);
5. 建立多列索引
CREATE TABLE index_tbl_5 (
id INT,
name VARCHAR(20),
subject VARCHAR(30),
INDEX idx_m(name(10), subject(10))
);
INSERT INTO `test`.`index_tbl_5` (`id`, `name`, `subject`) VALUES (NULL, 'php', 'this is php content'), (NULL, 'mysql', 'this is mysql content');
# 使用索引idex_m多列索引,由於name字段是第一個索引
EXPLAIN SELECT * FROM index_tbl_5 WHERE name='a' \G
analyze table來更新表的統計信息
6. 建立空間索引
CREATE TABLE index_tbl_6 (
id INT,
space GEOMETRY NOT NULL,
SPATIAL INDEX idx_sp(space)
) ENGINE=MyISAM;
7.2.2 已經存在的表上建立索引
在已經存在的表上,能夠直接爲表上的一個或幾個字段建立索引。基本形式以下 :
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX 索引名
ON 表名(字段[(長度)][ASC|DESC])
1. 建立普通索引
CREATE TABLE index1_tbl_1 (
id INT,
name VARCHAR(20),
gender BOOLEAN
);
CREATE INDEX idx on index1_tbl_1(id);
SHOW CREATE TABLE index1_tbl_1;
2. 建立唯一性索引
CREATE TABLE index1_tbl_2 (
id INT,
name VARCHAR(20),
gender BOOLEAN
);
CREATE UNIQUE INDEX u_idx ON index1_tbl_2(id ASC);
3. 建立全文索引
CREATE TABLE index1_tbl_3 (
id INT,
info VARCHAR(20)
) ENGINE=MyISAM;
CREATE FULLTEXT INDEX f_idx ON index1_tbl_3(info(10));
4. 建立單列索引
CREATE TABLE index1_tbl_4 (
id INT,
subject VARCHAR(30)
);
CREATE INDEX idx_sbj ON index1_tbl_4(subject(10));
5. 建立多列索引
CREATE TABLE index1_tbl_5 (
id INT,
name VARCHAR(20),
subject VARCHAR(30)
);
CREATE INDEX idx ON index1_tbl_5(name(5),subject(10));
6. 建立空間索引
CREATE TABLE index1_tbl_6 (
id INT,
space GEOMETRY NOT NULL
) ENGINE=MyISAM;
CREATE SPATIAL INDEX idx_sp ON index1_tbl_6(space);
7.2.3 ALTER TABLE語句來建立索引
在已經存在的表上,能夠經過ALTER TABLE語句直接爲表上的一個或幾個字段建立索引。基本形式以下:
ALTER TABLE 表名 ADD [UNIQUE|FULLTEXT|SPATIAL] INDEX
索引名 (字段名[(長度)][ASC|DESC]);
1. 建立普通索引
CREATE TABLE index2_tbl_1 (
id INT,
name VARCHAR(20),
gender BOOLEAN
);
ALTER TABLE index2_tbl_1 ADD INDEX
idx (id);
2. 建立唯一性索引
CREATE TABLE index2_tbl_2 (
id INT,
name VARCHAR(20),
gender BOOLEAN
);
ALTER TABLE index2_tbl_2 ADD UNIQUE INDEX
u_idx (id ASC);
3. 建立全文索引
CREATE TABLE index2_tbl_3 (
id INT,
info VARCHAR(20)
) ENGINE=MyISAM;
ALTER TABLE index2_tbl_3 ADD FULLTEXT INDEX
f_idx(info(10));
4. 建立單列索引
CREATE TABLE index2_tbl_4 (
id INT,
subject VARCHAR(30)
);
ALTER TABLE index2_tbl_4 ADD INDEX
idx_sbj(subject(10));
5. 建立多列索引
CREATE TABLE index2_tbl_5 (
id INT,
name VARCHAR(20),
subject VARCHAR(30)
);
ALTER TABLE index2_tbl_5 ADD INDEX
idx_m (name(5), subject(10));
6. 建立空間索引
CREATE TABLE index2_tbl_6 (
id INT,
space GEOMETRY NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
ALTER TABLE index2_tbl_6 ADD SPATIAL INDEX
idx_sp(space);
7.3 刪除索引
刪除索引是指將表中已經存在的索引刪除掉。一些再也不使用的索引會下降表的更新速度,影響數據庫的性能。對於這樣的索引,應該將其刪除。
對應已經存在的索引,能夠經過DROP語句來刪除索引。基本形式以下:
DROP INDEX 索引名 ON 表名;
7.4 本章實例
在job數據庫建立一個user表和一個information表。
1. 登陸數據庫系統並建立job數據庫
2. 建立user表
3. 建立information表
4. 在name字段建立名爲index_name的索引
5. 建立名爲index_bir的多列索引
6. 用ALTER TABLE語句建立名爲index_id的唯一性
7. 刪除user表上的index_user索引
8. 刪除information表上的index_name索引
user表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
userid 編號 INT(10) 是 否 是 是 是
username用戶名 VARCHAR(20) 否 否 是 否 否
passwd 密碼 VARCHAR(20) 否 否 是 否 否
info 附加信息 TEXT 否 否 否 否 否
information表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 編號 INT(10) 是 否 是 是 是
namne 姓名 VARCHAR(20) 否 否 是 否 否
gender 姓別 TINYINT(1) 否 否 是 否 否
birthday出生日期 DATE 否 否 否 否 否
address 家庭住址 VARCHAR(50) 否 否 否 否 否
tel 電話號碼 VARCHAR(20) 否 否 否 否 否
pic 照片 BLOB 否 否 否 否 否
CREATE DATABASE IF NOT EXISTS job;
USE job;
CREATE TABLE IF NOT EXISTS user(
userid INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT COMMENT '編號',
username VARCHAR(20) NOT NULL COMMENT '用戶名',
passwd VARCHAR(32) NOT NULL COMMENT '密碼',
info TEXT COMMENT '附加信息',
UNIQUE INDEX idx_uid(userid DESC),
INDEX idx_user(username, passwd),
FULLTEXT INDEX idx_info(info)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
DROP INDEX userid ON user;
DROP INDEX idx_uid ON user;
ALTER TABLE user DROP INDEX userid;
ALTER TABLE user DROP INDEX idx_uid;
DROP INDEX idx_user ON user;
ALTER TABLE user DROP INDEX idx_user;
CREATE DATABASE IF NOT EXISTS job;
USE job;
CREATE TABLE IF NOT EXISTS information(
id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT COMMENT '編號',
name VARCHAR(20) NOT NULL COMMENT '姓名',
gender BOOLEAN NOT NULL COMMENT '姓別',
birthday DATE COMMENT '出生日期',
address VARCHAR(50) COMMENT '家庭住址',
tel VARCHAR(20) COMMENT '電話號碼',
pic BLOB COMMENT '照片'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
DROP INDEX id ON information;
CREATE INDEX index_name ON information(name(10));
ALTER TABLE information ADD INDEX idx_name(name(10));
CREATE INDEX index_bir ON information(birthday,address);
ALTER TABLE information ADD INDEX index_bir(birthday,address);
ALTER TABLE information ADD INDEX index_id(id ASC);
DROP INDEX idx_name ON information;
SHOW CREATE TABLE user;
SHOW CRETAE TABLE information;
7.5 上機實踐
在數據庫job下建立workInfo表。建立表的同時在id字段上建立名爲index_id的唯一性索引,並且也降序的格式排列。
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 編號 INT(10) 是 否 是 是 是
name 職位名稱 VARCHAR(20) 否 否 是 否 否
type 職位類別 VARCHAR(10) 否 否 否 否 否
address 工做地址 VARCHAR(50) 否 否 否 否 否
wages 工資 FLOAT 否 否 否 否 否
contents工做內容 TINYTEXT 否 否 否 否 否
extra 附加信息 TEXT 否 否 否 否 否
CREATE DATABASE IF NOT EXISTS job;
USE job;
CREATE TABLE workInfo(
id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
type VARCHAR(10),
address VARCHAR(50),
wages FLOAT,
contents TINYTEXT,
extra TEXT,
INDEX index_id(id DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE INDEX index_name ON workInfo(name(10));
SHOW CREATE TABLE workInfo \G
ALTER TABLE workInfo ADD INDEX index_t(type,address);
ALTER TABLE workInfo ENGINE=MyISAM;
ALTER TABLE workInfo ADD FULLTEXT INDEX index_ext(extra);
7.6 常見問題及解答
1. MySQL中索引、主鍵和唯一性的區別是什麼?
索引創建在一個或者多個字段上。創建了索引後,表中的數據就按照索引的必定規則排列。這樣能夠提升查詢速度。
主鍵是表中數據的惟一標識。不一樣的記錄的主鍵值不一樣。在創建主鍵的時候,系統會自動創建一個唯一性索引。
惟一性也是創建在表中一個或者幾個字段上。其目的是爲了對於不一樣的記錄,具備惟一性的字段的值是不一樣的。
2. 表中創建了索引之後,導入大量數據爲何會很慢?
8.視圖
視圖是從一個或多個表中導出來的表,是一種虛擬存在的表。視圖就像一個窗口,經過這個窗口能夠看到系統專門提供的數據。這樣,用戶能夠不用看到整個數據庫表中的數據,而只關係對本身有用的數據。視圖能夠使用戶的操做更方便,並且能夠保障數據庫系統的安全性。
- 視圖的含義和做用
- 如何建立視圖
- 如何修改視圖
- 如何查看視圖
- 如何刪除視圖
8.1 視圖簡介
視圖由數據庫中的一個表或多個表導出的虛擬表。其做用是方便用戶對數據的操做。
8.1.1 視圖的含義
視 圖是一種虛擬的表。視圖從數據庫中的一個或多個表導出來的表。視圖還能夠從已經存在的視圖的基礎上定義。數據庫只存放了視圖的定義,而並無存放視圖中的 數據。這些數據存放在原來的表中。使用視圖查詢數據時,數據庫系統會從原來的表中取出對應的數據。所以,視圖中的數據是依賴於原來的表中的數據的。一旦表 中的數據發生改變,顯示在視圖中的數據也會發生改變。
8.1.2 視圖的做用
視圖是在原有的表或者視圖的基礎上從新定義的虛擬表,這能夠從原有的表上選取對用戶有用的信息。那些對用戶沒有用,或者用戶沒有權限瞭解的信息,均可以直接屏蔽掉。這樣作既使應用簡單化,也保證了系統的安全。視圖起着相似於篩選的做用。
1. 使操做簡單化
視圖須要達到的目的就是所見即所需。也就是說,從視圖看到的信息就是所須要瞭解的信息。視圖能夠簡化對數據的操做。例如,能夠爲常用的查詢定義一個視圖,使用戶沒必要爲一樣的查詢操做指定條件。這樣能夠很大程序上方便用戶的操做。
2. 增長數據的安全性
通 過視圖,用戶只能查詢和修改指定的數據。指定數據之外的信息,用戶根本接觸不到。數據庫受權命令能夠限制用戶操做權限,但不能限制定特定行和列上。使用視 圖後,能夠簡單方便的將用戶的權限限制到特定的行和列上。這樣能夠保證敏感信息不會被沒有權限的人看到,能夠保證一些機密信息的安全。
3. 提升表的邏輯獨立性
視圖能夠屏蔽原有表結構變化帶來的影響。例如,原有表增長列和刪除示被引用的列,對視圖不會形成影響。一樣,若是修改了表中的某些列,能夠同修改視圖來解決這些列帶來的影響。
8.2 建立視圖
建立視圖是指在已經存在的數據庫表上創建視圖。視圖能夠創建在一張表上,也能夠創建在多張表上。
8.2.1 建立視圖的語法形式
MySQL中,建立視圖是經過SQL語句CREATE VIEW實現的。其語法形式以下 :
CREATE [ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}]
VIEW 視圖名 [(屬性清單)]
AS SELECT語句
[WITH[CASCADED|LOCAL] CHECK OPTION];
ALGORITHM:
UNDEFINED, MySQL將自動選擇所要使用的算法;
MERGE, 表示將使用視圖的語句與視圖定義合併起來,使用視圖定義的某一部分取代語句的對應部分;
TEMPTABLE, 表示將視圖的結果存入臨時表,而後使用臨時表執行語句。
CASCADED是可選參數,表示更新視圖時要知足全部視圖和表的條件,該參數默認值;"LOCAL"表示更新視圖時要知足該視圖自己的定義的條件便可。
# 查詢執行(select和create view)權限
SELECT Select_priv,Create_view_priv FROM mysql.user WHERE user='root';
8.2.2 在單表上建立視圖
MySQL中能夠在單個表上建立視圖。在department表上建立一個簡單的視圖,視圖的名稱爲department_view。
實例一:
USE example;
CREATE VIEW department_view1
AS SELECT * FROM example.department;
DESC department_view;
實例二:
CREATE VIEW department_view2(name, function,location)
AS SELECT d_name, function, address FROM example.department;
DESC department_view2;
8.2.2 MySQL中也能夠在兩個或兩個以上的表上建立視圖,也是使用CREATE VIEW語句實現的。下面在department表和worker表上建立一個名爲worker_view1的視圖。
實例一:
CREATE ALGORITHM=MERGE VIEW
worker_view1(name, department, gender, age, address)
AS SELECT name, department.d_name, gender, 2011-birthday, worker.address
FROM worker,department WHERE worker.d_id=department.d_id
WITH LOCAL CHECK OPTION;
8.3 查看視圖
查 看視圖是指查看數據庫中已存在的視圖的定義。查看視圖必需要有SHOW VIEW的權限,mysql數據庫下的user表中保存着這個信息。查看視圖的方法包括DESCRIBE語句、SHOW TABLE STATUS語句、SHOW CREATE VIEW語句和查詢information_schema數據庫下的views表等。
8.3.1 DESCRIBE語句查看視圖基本信息
使用DESCRIBE語句來查看錶的基本定義。由於,視圖也是一張表。只是這張表比較特殊,是一張虛擬表。所以,一樣能夠使用DESCRIBE語句能夠用來查看視圖的基本定義。DESCRIBE語句查看視圖的基本形式與查看錶的形式是同樣的。基本形式以下:
DESCRIBE 視圖名;
DESC example.department_view1;
DESC example.department_view2;
DESCRIBE example.worker_view1;
8.3.2 SHOW TABLE STATUS語句查看視圖基本信息
MySQL中,能夠使用SHOW TABLE STATUS語句來查看視圖的信息。其語法形式以下:
SHOW TABLE STATUS LIKE '視圖名';
其中,'like'表示後面匹配的字符串;'視圖名'參數要查看的視圖的名稱,須要單引號引發了。
實例一:
SHOW TABLE STATUS LIKE 'worker_view1' \G
SHOW TABLE STATUS LIKE 'department' \G
8.3.3 SHOW CREATE VIEW語句查看視圖詳細信息
MySQL中,SHOW CREATE VIEW語句能夠查看視圖的詳細定義。其語法形式以下:
SHOW CREATE VIEW 視圖名;
實例一:
SHOW CREATE VIEW worker_view1;
8.3.4 在views表中查看視圖詳細信息
MySQL中,全部視圖的定義都存在information_schema數據庫下的views表中。查詢views表,能夠查看到數據庫中全部視圖的詳細信息。查詢的語句以下:
SELECT * FROM information_schema.views \G
其中,'*'表示查詢全部的列的信息;
'information_schema.view'表示information_schema數據庫下面的views表。
8.4 修改視圖
修改視圖是指修改數據庫已存在的表的定義。當基本表的某些字段發生改變時,能夠經過修改視圖來保持視圖和基本表之間一致。MySQL中經過CREATE OR REPLACE VIEW語句和ALTER語句來修改視圖。
8.4.1 CREATE OR REPLACE VIEW語句修改視圖
MySQL中,CREATE OR REPLACE VIEW語句能夠用來修改視圖。該語句的使用很是靈活。在視圖已經存在的狀況下,對視圖進行修改;視圖不存在時,能夠說建立視圖。CREATE OR REPLACE VIEW語句的語法形式以下:
CREATE OR REPLACE [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW 視圖名 [(屬性清單)]
AS SELECT語句
[WITH [CASCADED | LOCAL] CHECK OPTION];
實例一:
USE example;
CREATE VIEW department_view3
AS SELECT * FROM example.department;
CREATE OR REPLACE ALGORITHM = TEMPTABLE
VIEW department_view3(departmnt, func, location)
AS SELECT d_name, function, address
FROM department;
8.4.2 ALTER語句修改視圖
在MySQL中,ALTER語句能夠修改表的定義,能夠建立索引。不只如此,ALTER語句還能夠用來修改視圖。ALTER語句修改視圖的語法格式以下:
ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW 視圖名 [(屬性清單)]
AS SELECT語句
[WITH [CASCADED|LOCAL] CHECK OPTION];
實例一:
USE example;
CREATE VIEW department_view4
AS SELECT * FROM example.department;
ALTER VIEW department_view4(department, name, gender, location)
AS SELECT d_name, worker.name, gender, worker.address
FROM department, worker
WHERE department.d_id = worker.d_id
WITH CHECK OPTION;
8.5 更新視圖
更新視圖是指經過視圖來插入(INSERT)、更新(UPDATE)、和刪除(DELETE)表中的數據。由於是視圖是一個虛擬表,其中沒有數據。經過視圖更新時,都是轉換到基本表來更新。更新視圖時,只能更新權限範圍內的數據。超出了範圍,就不能更新。
INSERT INTO example.department VALUES
(1001,'人事部', '管理公司從事變更', '2號樓3層'),
(1002,'生產部', '生產管理', '5號樓1層');
USE example;
CREATE VIEW department_view5(name, function ,address)
AS SELECT d_name, function, address
FROM example.department
WHERE d_id = 1001;
UPDATE department_view5
SET name='科研部', function='新產品研發', address='3號樓5層';
INSERT INTO example.worker VALUES
(001,1,1001,'李明',1,'1982-5-8', '延吉市局子街21號'),
(002,2,1002,'王晶',0, '1985-6-4','龍井市解放路10號'),
(003,3,1002,'王磊',1, '1955-10-10','圖們市和平路6號'),
(004,4,1002,'張三',1, '2000-1-18','和龍市天平路16號'),
(005,5,1001,'劉亞南',0, '1977-7-9','汪清市開放路2號'),
(006,6,1001,'李四',1, '1946-2-16','琿春市開發區10號');
並非全部的視圖均可以更新的。如下這幾中狀況是不能更新視圖的:
(1)視圖中包含sum()、count()、max()、min()等函數。
CREATE VIEW worker_view2(name, gender, total)
AS SELECT name, gender, count(name) FROM worker;
由於視圖中包含count(),全部該視圖是不能更新的。
UPDATE worker_view2 SET total = 4;
(2)視圖中包含union、 union all、distinct、group by、having等關鍵字。
CREATE VIEW worker_view3(name, gender, address)
AS SELECT name, gender, homeAddress
FROM example.worker
GROUP BY d_id;
UPDATE worker_view2 SET name = '劉佳';
由於該視圖包含GROUP BY,全部該視圖也是不能更新的。
(3)常量視圖。
CREATE VIEW worker_view4
as SELECT 'Aric' as name;
由於該視圖的name字段是個字符串常量'Aric',因此該視圖也是不能更新的。使用UPDATE語句更新時,會出現系統報錯。
UPDATE worker_view4 SET name='hi';
ERROR............The target table worker_view4 of the UPDATE is not updatable.
(4)視圖中的SELECT中包含子查詢。
CREATE VIEW worker_view5(name)
AS SELECT (SELECT name FROM worker);
UPDATE worker_view5 SET name = '劉佳';
該視圖中包含了子查詢,所以也是不能更新的。
(5)由不可更新的視圖導出的視圖。
CREATE VIEW worker_view6
AS SELECT * FROM worker_view5;
UPDATE worker_view6 SET name = '王仔';
由於worker_view6是不可更新的視圖,因此worker_view6也不能夠更新的視圖。使用UPDATE語句更新時,會出現系統報錯。
(6)建立視圖時,ALGORITHM爲TEMPTABLE類型。
CREATE ALGORITHM=TEMPTABLE
VIEW worker_view7
AS SELECT * FROM worker;
UPDATE worker_view7 SET name = '王仔';
由於該視圖ALGORITHM爲TEMPTABLE類型,因此worker_view7不能夠更新的視圖。TEMPTABLE類型就是臨時表類型。系統默認臨時表是不能更新的。
(7) 視圖對應的表上存在沒有默認值的列,並且該列沒有包含在視圖裏。例如,表中包含的name字段沒有默認值,可是視圖中不包含該字段。那麼這個視圖是不能更 新的。由於,在更新視圖時,這個沒有默認值的記錄將沒有值插入,也沒有NULL值插入。數據庫系統是不會容許這樣的狀況出現的,數據庫系統將會阻止這個視 圖更新。
注意:視圖中雖然能夠更新數據,可是有不少的限制。通常狀況下,最好將視圖做爲查詢數據的虛擬表,而不要經過視圖來更新數據。由於,使用視圖更新數據時,若是沒有全面考慮在視圖中更新數據的限制,可能會形成數據更新失敗。
除了上述條件不能更新視圖之外,WITH[CASCADED|LOCAL]CHECK OPTION也將決定視圖可否更新。"LOCAL"參數表示更新視圖時要知足該視圖自己的定義的條件便可;
8.6 刪除視圖
刪除視圖是指刪除數據庫中已經存在的視圖。刪除視圖時,只能刪除視圖的定義,不會刪除數據。MYSQL中,使用DROP VIEW語句來刪除視圖,不會刪除數據。MySQL中,使用DROP VIEW語句來刪除視圖。可是,用戶必須擁有DROP權限。
DROP VIEW[IF EXISTS] 視圖名列表 [RESTRICT|CASCADE]
實例一:
SELECT Drop_priv
FROM mysql.user
WHERE user='root';
CREATE VIEW worker_view_del1
AS SELECT * FROM worker;
CREATE VIEW worker_view_del2
AS SELECT * FROM worker;
CREATE VIEW worker_view_del3
AS SELECT * FROM worker;
DROP VIEW IF EXISTS worker_view_del2, worker_view_del3;
8.7 本章實例
在test數據庫中work_info表上進行視圖操做。
1. 在test數據庫中work_info表
2. 插入記錄
3. 建立視圖info_view
4. 查看視圖info_view的基本結構和詳細結構
5. 查看視圖info_view的全部記錄
6. 修改視圖info_view
7. 更新視圖
8. 刪除視圖
work_info表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 編號 INT(10) 是 否 是 是 否
name 姓名 VARCHAR(20) 否 否 是 否 否
gender 姓別 VARCHAR(4) 否 否 是 否 否
age 年齡 INT(5) 否 否 否 否 否
address 家庭住址 VARCHAR(50) 否 否 否 否 否
tel 電話號碼 VARCHAR(20) 否 否 否 否 否
work_info表中的內容
id name gender age address tel
1 張三 M 18 北市市海淀區 01-155151
2 李四 M 22 北京市昌平區 01-215151
3 王五 F 17 湖南省永州市 025-545845
4 趙六 F 25 遼寧省阜新市 0625-514545
(1) 建立work_info表
USE test;
CREATE TABLE IF NOT EXISTS work_info (
id INT(10) NOT NULL UNIQUE PRIMARY KEY,
name VARCHAR(20) NOT NULL,
gender VARCHAR(4) NOT NULL,
age INT(5),
address VARCHAR(50),
tel VARCHAR(20)
) DEFAULT CHARSET=utf8;
(2)向work_info表中插入幾條記錄。
INSERT INTO work_info VALUES
(1, '張三', 'M', 18, '北市市海淀區','01-155151'),
(2,'李四', 'M', 22, '北京市昌平區', '01-215151'),
(3,'王五','F',17,'湖南省永州市','025-545845'),
(4,'趙六','F',25,'遼寧省阜新市','0625-514545');
(3) 建立視圖info_view。從work_info表中選出age>20的記錄來建立視圖。視圖的字段包括id、name、gender和address。ALGORITHM設置爲MERGE類型。加上WITH LOCAL CHECK OPTION條件。
CREATE ALGORITHM=MERGE
VIEW info_view(id, name, gender, address)
AS SELECT id, name, gender, address
FROM work_info
WHERE age>20
WITH LOCAL CHECK OPTION;
(4)查看視圖info_view的基本結構和詳細結構。
SHOW CREATE VIEW info_view \G
(5)查看視圖info_view的全部記錄。
SELECT * FROM info_view;
(6)修改視圖info_view,使其顯示age<20的信息,其餘條件不變。
ALTER ALGORITHM=MERGE
VIEW info_view(id, name, gender, address)
AS SELECT id, name, gender, address
FROM work_info
WHERE age<20
WITH LOCAL CHECK OPTION;
(7)更新視圖,將id爲3的記錄進行更新。設置其gender爲M。
UPDATE info_view SET gender='M' WHERE id=3;
(8)刪除視圖。
DROP VIEW info_view;
8.8 上機實踐
題目要求:
(1)在數據庫example下建立college表。
(2) 在college表上建立視圖college_view。視圖的字段包括student_num、student_name、student_age和 department。ALGORITHM設置爲UNDEFINED類型。加上WITH LOCAL CHECK OPTION條件。
(3)查看視圖college_view的詳細結構。
(4)更新視圖。向視圖中插入三條記錄。
(5)修改視圖,使其顯示專業爲"計算機"的信息,其餘條件不變。
(6)刪除視圖college_view。
college表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
number 學號 INT(10) 是 否 是 是 否
name 姓名 VARCHAR(20) 否 否 是 否 否
major 專業 VARCHAR(20) 否 否 是 否 否
age 年齡 INT(5) 否 否 否 否 否
college_view表的內容
student_num student_name student_age department
0901 張三 20 外語
0902 李四 22 計算機
0903 王五 19 計算機
USE example;
CREATE TABLE college(
number INT(10) NOT NULL UNIQUE PRIMARY KEY,
name VARCHAR(20) NOT NULL,
major VARCHAR(20) NOT NULL,
age TINYINT(3)
) DEFAULT CHARSET=utf8;
CREATE ALGORITHM=UNDEFINED
VIEW college_view(student_num, student_name, student_age, department)
AS SELECT number, name, age, major
FROM college
WITH LOCAL CHECK OPTION;
SHOW CREATE VIEW college_view \G
INSERT INTO college_view VALUES
(0901, '張三', 20, '外語'),
(0902, '李四', 22, '計算機'),
(0903, '王五', 19, '計算機');
CREATE OR REPLACE ALGORITHM=UNDEFINED
VIEW college_view(student_num, student_name, student_age, department)
AS SELECT number, name, age, major
FROM college
WHERE major='計算機'
WITH LOCAL CHECK OPTION;
8.9 常見問題及解答
1. MySQL中視圖和表的區別和聯繫是什麼?
區別:
(1)視圖是按照SQL語句生成的一個虛擬的表。
(2)視圖不佔實際的物理空間,而表中的記錄須要物理空間。
(3)創建和刪除視圖隻影響視圖自己,不會影響實際的記錄。而創建和刪除表會影響實際的記錄。
聯繫:
(1)視圖是在基本表之上創建的表,其字段和記錄都來自基本表,其依賴基本表而存在。
(2)一個視圖能夠對應一個基本表,也能夠對應多個基本表。
(3)視圖是基本表的抽象,在邏輯意義上創建的新關係。
2. 爲何視圖更新不了?
9.觸發器
觸發器(TRIGGER)是由事件來觸發某個操做。這些事件包括INSERT語句、UPDATE語句和DELETE語句。當數據庫系統執行這些事件時,就會激活觸發器執行相應的操做。MySQL從5.0.2版本開始支持觸發器。
觸發器的含義和做用
如何建立觸發器
如何查看觸發器
如何刪除觸發器
9.1 建立觸發器
觸 發器是由INSERT、UPDATE和DELETE等事件觸發某種特定操做。知足觸發器的觸發條件時,數據庫系統就會執行觸發器中定義的程序語句。這樣作 能夠保證某些操做之間的一致性。例如,當學生表中增長了一個學生的信息時,學生的總數就必須同時改變。能夠在這裏建立一個觸發器,每次增長一個學生的記 錄,就執行一次計算學生總數的操做。這樣就能夠保證每次增長學生的記錄後,學生總數是與記錄數是一致的。觸發器觸發的執行語句可能只有一個,也可能有多 個。
9.1.1 建立只有一個執行語句的觸發器
MySQL中,建立只有一個執行語句的觸發器的基本形式以下 :
CREATE TRIGGER 觸發器名 BEFORE | AFTER 觸發事件
ON 表名 FOR EACH ROW 執行語句
「觸發器名」參數指要建立的觸發器的名字。
「BEFORE」和「AFTER」參數指定了觸發器執行的時間。「BEFORE」指在觸發事件以前執行觸發語句。「AFTER」表示在觸發事件以後執行觸發語句。
「觸發事件」參數批觸發的條件,其中包括INERT、UPDATE和DELETE。
「表名」參數指觸發事件操做的表的名稱。
「FOR EACH ROW」表示任何一條記錄上的操做知足觸發事件都會觸發都會觸發該觸發器。
「執行語句」參數指觸發器被觸發執行的程序。
USE example;
CREATE TABLE trigger_time(
exec_time TIME
);
CREATE TRIGGER dept_trig1 BEFORE INSERT
ON department FOR EACH ROW
INSERT INTO trigger_time VALUES(NOW());
INSERT INTO department VALUES(1003, '銷售部', '負責產品銷售', '1號樓銷售大廳');
9.1.2 建立多個執行語句的觸發器
MySQL中,觸發器觸發的執行語句可能有多個。建立有多個執行語句的觸發器的基本形式以下:
CREATE TRIGGER 觸發器名
BEFORE|AFTER 觸發事件
ON 表名
FOR EACH ROW
BEGIN
執行語句列表
END
BEGIN和END之間的「執行語句列表」參數表示須要執行的多個執行語句的內容。不一樣的執行語句之間用分號隔開。
DELIMITER && # 設置語句執行結束符
CREATE TRIGGER dept_trig2 AFTER DELETE
ON department FOR EACH ROW
BEGIN
INSERT INTO trigger_time VALUES('21:01:01');
INSERT INTO trigger_time VALUES('22:01:01');
END
&&
9.2 查看觸發器
查看觸發器是指查看數據庫中已存在的觸發器的定義、狀態和語法等信息。查看觸發器的方法包括SHOW TRIGGERS語句和查詢information_schema數據庫下的triggers表等。
實例一:SHOW TRIGGERS \G
實例二:SELECT * FROM information_schema.TRIGGERS \G
SELECT * FROM information_schema.TRIGGERS WHERE trigger_name='dept_trig1' \G
9.3 觸發器的使用
MySQL 中,觸發器執行的順序是BEFORE觸發器、表操做(INSERT、UPDATE和DELETE)、AFTER觸發器。在department表上建立 BEFORE INSERT和AFTER INSERT這兩個觸發器。在向department表中插入數據時,觀察這兩個觸發器的觸發順序。
USE example;
CREATE TABLE trigger_test(
id INT PRIMARY KEY AUTO_INCREMENT,
info VARCHAR(20)
);
DROP TRIGGER dept_trig1;
CREATE TRIGGER before_insert BEFORE INSERT
ON department FOR EACH ROW
INSERT INTO trigger_test VALUES(NULL, 'before_insert');
CREATE TRIGGER after_insert AFTER INSERT
ON department FOR EACH ROW
INSERT INTO trigger_test VALUES(NULL, 'after_insert');
INSERT INTO department VALUES(1003, '銷售部', '負責產品銷售', '1號樓銷售大廳');
9.4 刪除觸發器 DROP TRIGGER 觸發器名
9.5 本章實例
在product表上建立三個觸發器。每次激活觸發器後,都會更新operate表。
1. 建立product表和operate表。
2. 建立product_ab_insert觸發器
3. 建立product_af_update觸發器
4. 建立product_af_del觸發器
5. 對product表進行操做
6. 刪除觸發器
product表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 產品編號 INT(10) 是 否 是 是 否
name 產品名稱 VARCHAR(20) 否 否 是 否 否
function主要功能 VARCHAR(50) 否 否 否 否 否
company 生產廠商 VARCHAR(20) 否 否 是 否 否
address 家庭住址 VARCHAR(50) 否 否 否 否 否
operate表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
op_id 編號 INT(10) 是 否 是 是 是
op_type 操做方式 VARCHAR(20) 否 否 是 否 否
op_time 操做時間 TIME 否 否 是 否 否
(1) 在product表上分別建立BEFORE INSERT、AFTER UPDATE和AFTER DELETE三個觸發器,觸發器的名稱分別爲product_af_insert、product_af_update和product_af_del。 執行語句部分都向operate表插入操做方法和操做時間。
(2)對product表分別執行INSERT、UPDATE和DELETE操做。
(3)刪除product_af_insert和product_af_update這兩個觸發器。
USE example;
CREATE TABLE product(
id INT(10) NOT NULL UNIQUE PRIMARY KEY COMMENT,
name VARCHAR(20) NOT NULL,
function VARCHAR(50),
company VARCHAR(20) NOT NULL,
address VARCHAR(50)
) DEFAULT CHARSET=utf8;
CREATE TABLE operate(
op_id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT,
op_type VARCHAR(20) NOT NULL,
op_time TIME NOT NULL
) DEFAULT CHARSET=utf8;
CREATE TRIGGER product_af_insert BEFORE INSERT
ON product FOR EACH ROW
INSERT INTO operate VALUES(NULL, 'insert', NOW());
CREATE TRIGGER product_af_update AFTER UPDATE
ON product FOR EACH ROW
INSERT INTO operate VALUES(NULL, 'update', NOW());
CREATE TRIGGER product_af_del AFTER DELETE
ON product FOR EACH ROW
INSERT INTO operate VALUES(NULL, 'delete', NOW());
INSERT INTO product VALUES(1001, '國珍', '適用於全部人羣的保健品', '煙臺新時代健康產業集團有限公司', '吉林省延吉市開發區');
UPDATE product SET name='竹珍' WHERE id=1001;
DELETE FROM product WHERE id=1001;
DROP TRIGGER product_af_insert;
DROP TRIGGER product_af_update;
DROP TRIGGER product_af_del;
9.6 常見問問題及解答
1. MySQL中建立多條執行語句的觸發器部是遇到分號就結束建立,而後報錯?
MySQL 中,建立多條執行語句的觸發器時,須要用到BEGIN...END的形式。每一個執行語句都必須是以分號結束。可是,這樣就會出問題。由於,系統默認分號是 SQL程序結束的標誌,遇到分號整個程序就結束了。要解決這個問題,就須要DELIMITER語句來改變程序的結束符號。如「DELIMITER &&」,能夠將程序的結束符號變量「&&」。
若是要把結束符號變回分號,只要執行「DEMILITE;」便可。
10.查詢數據
查詢數據指從數據庫中獲取所須要的數據。查詢數據是數據庫操做中最經常使用,也是最重要操做。用戶可能根據本身對數據的需求,使用不一樣的查詢方式。經過不一樣的查詢方式,能夠得到不一樣的數據。MySQL中是使用SELECT語句來查詢數據的。
- 查詢語句的基本語法
- 在單表上查詢數據
- 使用聚合函數查詢數據
- 多表上聯合查詢
- 子查詢
- 合併查詢結果
- 爲表和字段取別名
- 使用正則表達式查詢
10.1 基本查詢語句
查 詢數據是數據庫操做中最經常使用的操做。經過對數據庫的查詢,用戶能夠從數據庫中獲取須要的數據。數據庫中可能包含着無數的表,表中可能包含着無數記錄。因 此,要得到所需的數據並不是易事。MySQL中能夠使用SELECT語句來查詢數據。根據查詢的條件的不一樣,數據庫系統會找到不一樣的數據。經過SELECT 語句能夠很方便的獲取所需的信息。
MySQL中,SLEECT的基本語法形式以下:
SELECT 屬性列表
FROM 表名和視圖列表
[WHERE 條件表達式1]
[GROUP BY 屬性名1] [HAVING 條件表達式2]
[ORDER BY 屬性名[ASC|DESC]]
'屬性列表'參數表示須要查詢的字段名;
'表名或視圖列表'參數表示此處指定的表或者視圖中查詢數據,表和視圖能夠有多個;
'條件表達式1'參數指定查詢條件;
'屬性名1'參數指按該字段中的數據進行分組;
'條件表達式2'參數表示知足該表達式的數據才能輸出;
'屬性名2'參數指按該字段中的數據進行排序,排序方式由'ASC'和'DESC'兩個參數指出;
'ASC'參數表示按升序的順序進行排序,這是默認排序;(從小到大)
'DESC'參數表示按降序的順序進行排序。(從大到小)
若是有WHERE子句,就按照'條件表達式1'指定的條件進行查詢。若是沒有WHERE子句,就查詢全部記錄。
若是有GROUP BY子句,就按照'屬性名1'指定的字段進行分組。若是GROUP BY子句後帶着HAVING關鍵字,那麼只有知足'條件表達式2'中指定的條件纔可以輸出。
GROUP BY子句一般和COUNT()、SUM()等聚合函數一塊兒使用。
若是有ORDER BY子句,就按照'屬性名2'指定的字段進行排序。排序方式由'ASC'和'DESC'兩個參數指出。默認的狀況下是'ASC'。
CREATE TABLE employee(
num INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
d_id INT NULL,
name VARCHAR(20),
age INT,
gender VARCHAR(4),
homeaddr VARCHAR(50)
) DEFAULT CHARSET=utf8;
INSERT INTO employee VALUES
(NULL, 1001, '張三', 26, '男', '北京市海淀區'),
(NULL, 1001, '李四', 24, '女', '北京市昌平區'),
(NULL, 1002, '王五', 25, '男', '湖南長沙市'),
(NULL, 1004, 'Aric', 15, '男', 'England');
(1)使用SELECT語句查詢employee表
select num, name, age, gender, homeaddr FROM employee;
(2)包括WHERE子句和ORDER BY子句的SELECT語句
SELECT num, d_id, name, age, gender, homeaddr
FROM employee
WHERE age<26
ORDER BY d_id DESC;
10.2 單表查詢
單 表查詢是指從一張表中查詢所須要的數據。查詢數據時,能夠從一張表中查詢數據,也能夠從多張表中同時查詢數據。二者的查詢方式有必定的區別。由於單表查詢 只在一張表上進行操做,因此查詢比較簡單。本小節將講解在單表上查詢全部的字段、查詢指定的字段、查詢指定的行、多條查詢、查詢結果不重複、給查詢結果排 序、分組查詢和用LIMIT限制查詢結果的數據等內容。
10.2.1 查詢全部字段
查詢全部字段是指查詢表中全部字段的數據。這種方式能夠將表中全部字段的數據都查詢出來。MySQL中有兩種方式能夠查詢表中全部的字段。
1. 列出表的全部字段
2. 使用'*'查詢全部字段
(1)SELECT語句查詢employe表中的全部字段的數據
SELECT num, d_id, name, age, gender, homeaddr FROM employee;
(2)用SELECT語句來查詢employee表的全部字段的數據,此處用'*'來代替'屬性列表'。
SELECT * FROM employee;
10.2.2 查詢指定字段
查詢數據時,能夠在SELECT語句的'屬性列表'中列出全部查詢的字段。這種方式能夠指定須要查詢的字段,而不須要查詢出全部的字段。下面查詢employee表中num、name、gender和homeaddr這四個字段的數據。
SELECT num, name, gender, homeaddr FROM employee;
10.2.3 查詢指定記錄
SELECT 語句中能夠設置查詢條件。用戶能夠根據本身的須要來設置查詢條件,按條件進行查詢。查詢的結果必須知足查詢條件。例如,用戶須要查找d_id爲1001的 記錄,那麼能夠設置'd_id=1001'爲查詢條件。這樣查詢結果中的記錄就都會知足'd_id=1001'這個條件。WHERE子句能夠用來指定查詢 條件。
WHEER 條件表達式
(1)查詢employee表中d_id爲1001的記錄。
SELECT * FROM employee WHERE d_id=1001;
(2)查詢employee表中d_id爲1004的記錄。
SELECT * FROM employee WHERE d_id=1004;
10.2.4 帶IN關鍵字的查詢
IN關鍵字能夠判斷某個字段的值是否在指定的集合中。若是字段的值在集合中,則知足查詢條件,該記錄被查詢出來。若是不在集合中,則不知足查詢條件。其語法規則以下:
[NOT] IN(元素1, 元素2,...,元素n)
查詢條件 符號或關鍵字
比較 =, <, <=, >, >=, !=, <>, !>, !<
指定範圍 BETWEEN AND, NOT BETWEEN AND
指定集合 IN, NOT IN
匹配字符 LIKE, NOT LIKE
是否爲空值 IS NULL, IS NOT NULL
多個查詢條件 AND, OR
(1)使用IN關鍵字查詢。
SELECT * FROM employee WHERE d_id IN(1001,1004);
(2)使用NOT IN關鍵字查詢, 並且集合元素爲字符型數據。
SELECT * FROM employee WHERE name NOT IN('張三','李四');
10.2.5 帶BETWEEN AND的範圍查詢
BETWEEN AND關鍵字能夠判斷某個字段的值是否在指定的範圍內。若是字段的值在指定範圍內,則知足查詢條件,該記錄將被查詢出來。若是不在指定範圍內,則不知足查詢條件。其語法規則以下:
[NOT] BETWEEN 取值1 AND 取值2
(1)使用BETWEEN AND關鍵字進行查詢,查詢條件是age字段取值從15到25。
SELECT * FROM employee WHERE age BETWEEN 15 AND 25;
(2)使用NOT BETWEEN AND關鍵字查詢employee表。查詢條件是age字段的取值不在15到25之間。
SELECT * FROM employee WHERE age NOT BETWEEN 15 AND 25;
10.2.6 帶LIKE的字符匹配查詢
LIKE關鍵字能夠匹配字符串是否相等。若是字段的值與指定的字符串相匹配,則知足查詢條件,該記錄將被查詢出來。若是與指定的字符串不匹配,則不知足查詢條件。其語法規則以下:
[NOT] LIKE '字符串'
SELECT * FROM employee WHERE name LIKE 'Aric';
SELECT * FROM employee WHERE homeaddr LIKE '北京%';
SELECT * FROM employee WHERE name LIKE 'Ar_c';
SELECT * FROM employee WHERE homeaddr LIKE '%區';
10.2.7 查詢空值
IS NULL 關鍵字能夠用來判斷字段的值是否爲空值(NULL)。若是字段的值是空值,則知足查詢條件,該記錄將被查詢出來。若是字段的值不是空值,則不知足查詢條件。其語法規則以下:
IS [NOT] NULL
其中,'NOT'是可選參數,加上NOT表示字段不是空值時知足條件。
CREATE TABLE work(
id INT,
name VARCHAR(20),
gender VARCHAR(4),
info VARCHAR(50)
) DEFAULT CHARSET=utf8;
INSERT INTO work VALUES
(1001, 'hijh', NULL, NULL),
(1002, 'CCH', NULL, NULL),
(1003, 'zk', NULL, 'student');
SELECT * FROM work WHERE info IS NULL;
SELECT * FROM work WHERE info IS NOT NULL;
10.2.8 帶AND的多條件查詢
AND關鍵字能夠用來聯合多個條件進行查詢。使用AND關鍵字時,只有同時知足全部查詢條件記錄會被查詢出來。若是不知足這些查詢條件的其中一個,這樣的記錄將被排除掉。AND關鍵字的語法規則以下:
條件表達式1 AND 條件表達式2 [... AND 條件表達式n]
其中,AND能夠鏈接兩個條件表達式。並且,能夠同時使用AND關鍵字,這樣能夠鏈接更多的條件表達式。
SELECT * FROM employee
WHERE d_id<1004
AND gender LIKE '男';
SELECT * FROM employee
WHERE d_id<1004
AND age<26 and="" gender="男" select="" from="" employee="" where="" num="" in="" 1="" 2="" 3="" and="" age="" between="" 15="" and="" 25="" and="" homeaddr="" like="" 10="" 2="" 9="" or="" or="" and="" or="" or="" 1="" or="" 2="" or="" n="" or="" or="" select="" from="" employee="" where="" num="" in="" 1="" 2="" 3="" or="" age="" between="" 24="" and="" 25="" or="" homeaddr="" like="" select="" from="" employee="" where="" num="" in="" 1="" 3="" 4="" and="" age="25" or="" gender="女" select="" from="" employee="" where="" gender="女" or="" num="" in="" 1="" 3="" 4="" and="" age="25;" 10="" 2="" 10="" employee="" d_id="" select="" distinct="" d_id="" from="" employee="" 10="" 2="" 11="" order="" by="" order="" by="" asc="" desc="" select="" from="" employee="" ordery="" by="" age="" select="" from="" employee="" order="" by="" age="" asc="" select="" from="" employee="" order="" by="" age="" desc="" select="" from="" employee="" order="" by="" d_id="" asc="" age="" desc="" 10="" 2="" 12="" group="" by="" group="" by="" having="" with="" rollup="" 1="" group="" by="" 2="" group="" by="" group_concat="" 3="" group="" by="" 4="" group="" by="" having="" 5="" 6="" group="" by="" with="" rollup="" select="" from="" employee="" group="" by="" gender="" select="" gender="" group_concat="" name="" from="" employee="" group="" by="" gender="" select="" gender="" count="" gender="" from="" employee="" group="" by="" gender="" select="" gender="" count="" gender="" from="" employee="" group="" by="" gender="" having="" count="" gender="">=3;
INSERT INTO employee VALUES(NULL, 1002, '趙六', 22, '男', '延吉市開發區');
SELECT * FROM employee GROUP BY d_id, gender;
SELECT gender, COUNT(gender) FROM employee GROUP by gender WITH ROLLUP;
SELECT gender, GROUP_CONCAT(name) FROM employee GROUP BY gender WITH ROLLUP;
10.2.13 用LIMIT限制查詢結果的數量
查 詢數據時,可能會查詢出不少的記錄。而用戶須要的記錄可能只是不多的一部分。這樣就須要來限制查詢結果的數量。LIMIT是MySQL中的一個特殊關鍵 字。其能夠用來指定查詢結果從哪條記錄開始顯示。還能夠指定一共顯示多少條記錄。LIMIT關鍵字有兩種使用方式。這兩種方式分別是不指定初始位置和指定 初始位置。
1. 不指定初始位置
2. 指定初始位置
SELECT * FROM employee LIMIT 2;
SELECT * FROM employee LIMIT 6;
SELECT * FROM employee LIMIT 0, 2;
SELECT * FROM employee LIMIT 2, 2;
10.3 使用集合函數查詢
集 合函數包括COUNT()、SUM()、AVG()、MAX()和MIN()。其中,COUNT()用來統計記錄的條件;SUM()用來計算字段的值的總 和;AVG()用來計算字段的值的平均值;MAX()用來查詢字段的最大值;MIN()用來查詢字段的最小值。當須要對錶中的記錄求和、求平均值、查詢最 大值、查詢最小值等操做時,能夠使用集合函數。例如,須要計算學生成績表中的平均成績,能夠使用AVG()函數。GROUP BY關鍵字一般須要與集合函數一塊兒使用。
10.3.1 COUNT函數
COUNT()函數用來統計記錄的條數。若是要統計employee表中有多少條記錄,能夠使用COUNT()函數。若是要統計employee表中不一樣部門的人數,也能夠使用COUNT()函數。使
SELECT COUNT(*) FROM employee;
SELECT d_id, COUNT(*) from employee GROUP BY d_id;
10.3.2 SUM()函數
SUM()函數是求和函數。使用SUM()函數能夠求出表中某個字段取值的總和。例如,能夠用SUM()函數來求學生的總成績。
CREATE TABLE grade(
num INT NOT NULL,
course VARCHAR(10) NOT NULL,
score FLOAT
) DEFAULT CHARSET=utf8;
INSERT INTO grade VALUES
(1001, '數學', 80),
(1001, '語文', 90),
(1001, '英語', 85),
(1001, '計算機', 95),
(1002, '數學', 88),
(1002, '語文', 90),
(1002, '英語', 89),
(1002, '計算機', 90),
(1003, '數學', 80),
(1003, '語文', 98),
(1003, '英語', 85),
(1003, '計算機', 95);
SELECT * FROM grade WHERE num=1001;
SELECT num, SUM(score) FROM grade WHERE num=1001;
SELECT num, SUM(score) FROM grade GROUP BY num;
10.3.3 AVG()函數
AVG()函數是求平均值的函數。使用AVG()函數能夠求出表中某個字段取值的平均值。例如,能夠用AVG()函數來求平均年齡,也能夠使用AVG()函數來求學生的平均成績。
SELECT AVG(age) FROM employee;
SELECT course, AVG(score) FROM grade GROUP BY course;
SELECT num, AVG(score) FROM grade GROUP BY num;
10.3.4 MAX()函數
MAX()函數是求最大值的函數。使用MAX()函數能夠求出表中某個字段取值的最大值。例如,能夠用MAX()函數來查詢最大年齡,也能夠使用MAX()函數來求各科的最高成績。
SELECT MAX(age) FROM employee;
SELECT num, course, MAX(score) FROM grade GROUP BY course;
SELECT MAX(name) from work;
10.3.5 MIN()函數
MIN()函數是求最小值的函數。使用MIN()函數能夠求出表中某個字段取值的最小值。例如,能夠用MIN()函數來查詢最小年齡,也能夠使用MIN()函數來求各科的最小成績。
SELECT MIN(age) FROM employee;
SELECT num, course, MIN(score) FROM grade GROUP BY course;
SELECT MIN(name) from work;
10.4 鏈接查詢
連 接查詢是將兩個或兩個以上的表按某個條件鏈接起來,從中選取須要的數據。鏈接查詢是同時查詢兩個或兩個以上的表時使用的。當不一樣的表中存在表示相贊成義的 字段時,能夠經過該字段來鏈接這幾個表。例如,學生表中有course_id字段來表示所學課程的課程號,課程表中有num字段來表示課程號。那麼,可能 經過學生表中的course_id字段與課程表中的num字段來進行鏈接查詢。鏈接查詢包括內鏈接查詢和外鏈接查詢。本小節將詳細講解內鏈接查詢和外鏈接 查詢。同時,還會講解多個條件結合在一塊兒進行復合鏈接查詢。
10.4.1 內鏈接查詢
內鏈接查詢是一種最經常使用的鏈接查詢。內鏈接查詢能夠查詢兩個或兩個以上的表。當兩個表中存在表示相贊成義的字段時,能夠經過該字段來鏈接這兩個表。當該字段的值相等時,就查詢出該記錄。
INSERT INTO department VALUES
(1004, '人力資源部', '管理員工的信息', '2號樓3層');
INSERT INTO employee VALUES(NULL, 1003, '劉花', 28, '女', '吉林省長春市');
INSERT INTO employee VALUES(NULL, 1006, '王晶', 22, '女', '吉林省通化市');
使用內連查詢的方式查詢
SELECT num, name, employee.d_id, age, d_name, function
FROM employee, department
WHERE employee.d_id=department.d_id;
10.4.2 外鏈接查詢
外鏈接查詢能夠查詢兩個或兩個之後的表。外鏈接查詢也須要經過指定字段來進行鏈接。當該字段取值相等時,能夠查詢該記錄。並且,該字段取值不相等的記錄也能夠查詢出來。外鏈接查詢包括左鏈接查詢和右鏈接查詢。其基本語法以下:
SELECT 屬性名列表
FROM 表名1 LEFT|RIGHT JOIN 表名2
ON 表名1.屬性名1 = 表名2.屬性名2;
1. 左鏈接查詢
SELECT num, name, employee.d_id,age,gender, d_name, function
FROM employee
LEFT JOIN department
ON employee.d_id=department.d_id;
2. 右鏈接查詢
SELECT num, name, employee.d_id,age,gender, d_name, function
FROM employee
RIGHT JOIN department
ON employee.d_id=department.d_id;
CREATE TABLE performance(
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
e_num INT(10) NOT NULL UNIQUE,
performance FLOAT NOT NULL DEFAULT 0
) DEFAULT CHARSET=utf8;
INSERT INTO performance VALUES
(NULL, 2, 2000),
(NULL, 1, 100),
(NULL, 3, 5000),
(NULL, 5, 8000),
(NULL, 6, 10000);
SELECT num, name, employee.d_id,age,gender, d_name, function, performance
FROM employee
LEFT JOIN department
ON employee.d_id=department.d_id
LEFT JOIN performance
ON employee.num=performance.id;
10.4.3 複合條件鏈接查詢
在鏈接查詢時,也能夠增長其餘的限制條件。經過多個條件的複合查詢,能夠使查詢結果更加準備。例如,employee表和department表進行鏈接查詢時,能夠限制age字段的取值必須大於24。能夠更加準備的查詢出年齡大於24歲的員工的信息。
SELECT num,name,employee.d_id,age,gender,d_name,function
FROM employee,department
WHERE employee.d_id=department.d_id
AND age>24
ORDER BY age DESC;
10.5 子查詢
子 查詢是將一個查詢語句嵌套在另外一個查詢語句中。內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。由於在特定狀況下,一個查詢語句的條件須要另外一 個查詢語句來獲取。例如,如今須要從學生成績表中查詢計算機系統學生的各科成績。那麼,首先就必須知道哪些課程是計算機系學生選修的。所以,必須先查詢計 算機系學生選修的課程,而後根據這些課程來查詢計算機系學生的各科成績。經過子查詢,能夠實現多表之間的查詢。子查詢中可能包括IN、NOT IN、ANY、ALL、EXISTS、NOT EXISTS等關鍵字。子查詢中還可能包含比較運算符,如'='、'!='、'>'和'<'等。
10.5.1 帶IN關鍵字的子查詢
一 個查詢語句的條件可能在另外一個SELECT語句的查詢結果中。這能夠經過IN關鍵字來判斷。例如,要查詢哪些同窗選擇了計算機系開設的課程。先必須從課程 表中查詢出計算機系開設了哪些課程。而後再從學生表中進行查詢。若是學生選修的課程在前面查詢出來的課程中,則查詢出該同窗的信息。這能夠用帶IN關鍵字 的子查詢來實現。
SELECT * FROM employee
WHERE d_id IN(SELECT d_id FROM department);
SELECT * FROM employee
WHERE d_id NOT IN(SELECT d_id FROM department);
10.5.2 帶比較運算符的子查詢
子查詢能夠使用比較運算符。這些比較運算符包括=、!=、>、>=、<、<=、<>等。其中,<>與!=是等價的。比較運算符在子查詢時使用的很是普遍。如查詢分數、年齡、價格、 收入等。
CREATE TABLE computer_stu(
id INT PRIMARY KEY,
name VARCHAR(20),
score FLOAT
) DEFAULT CHARSET=utf8;
INSERT INTO computer_stu VALUES(1001, 'lILY', 85);
INSERT INTO computer_stu VALUES(1002, 'Tom', 91);
INSERT INTO computer_stu VALUES(1003, 'Jim', 87);
INSERT INTO computer_stu VALUES(1004, 'Aric', 77);
INSERT INTO computer_stu VALUES(1005, 'Lucy', 65);
INSERT INTO computer_stu VALUES(1006, 'Andy', 99);
INSERT INTO computer_stu VALUES(1007, 'Ada', 85);
INSERT INTO computer_stu VALUES(1008, 'jeck', 70);
CREATE TABLE scholarship(
level INT PRIMARY KEY,
score INT
) DEFAULT CHARSET=utf8;
INSERT INTO scholarship VALUES(1, 90);
INSERT INTO scholarship VALUES(2, 80);
INSERT INTO scholarship VALUES(3, 70);
在computer_stu表中查詢得到一等獎學金的學生的學號、姓名和分數。各個等級的獎學金的最低存儲在scholarship表中。
SELECT id, name, score, FROM computer_stu
WHERE score>=(SELECT score FROM scholarship WHERE level=1)
在department表中查詢哪些部門沒有年齡爲24歲的員工。員工的年齡存儲在employee表中。先查詢一下employee表和deparment表,以便進行對比。
SELECT d_id, d_name
FROM department
WHERE d_id!=(SELECT d_id FROM employee WHERE age=24);
SELECT d_id, d_name
FROM department
WHERE d_id<>(SELECT d_id FROM employee WHERE age=24);
10.5.3 帶EXISTS關鍵字的子查詢
EXISTS 關鍵字表示存在。使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。而是返回一個真假值。若是內層查詢語句查詢到知足條件的記錄,就返回一個真值 (TRUE)。不然,將返回一個假值(FALSE)。當返回的值是真值時,外層查詢語句將進行查詢。當返回值是假值時,外層查詢語句再也不進行查詢或者查詢 不出任何記錄。
若是department表中存在d_id取值爲1003的記錄,則查詢employee表的記錄
SELECT * FROM employee
WHERE EXISTS(SELECT d_name FROM department WHERE d_id=1003);
若是department表中存在d_id取值爲1003的記錄,則查詢employee表中age大於24的記錄
SELECT * FROM employee
WHERE age>24 AND EXISTS(SELECT d_name FROM department WHERE d_id=1006);
若是department表中不存在d_id取值爲1003的記錄,則查詢employee表的記錄
SELECT * FROM employee
WHERE NOT EXISTS(SELECT d_name FROM department WHERE d_id=1006);
10.5.4 帶ANY關鍵字的子查詢
ANY 關鍵字表示知足其中任一條件。使用ANY關鍵字時,只要知足內層查詢語句返回的結果中的任何一個,就能夠經過該條件來執行外層查詢語句。例如,須要查詢哪 些同窗可以得到獎學金。那麼,首先必須從獎學金錶中查詢出各類獎學金要求的最低分。只要一個同窗的成績高於不一樣獎學金最低分的任何一個,這個同窗就能夠獲 得獎學金。ANY關鍵字一般與比較運算符一塊兒使用。
從computer_stu表中查詢哪些同窗能夠得到獎學金。獎學金的信息存儲在scholarship表中。
SELECT * FROM computer_stu WHERE score>=ANY
(SELECT score FROM scholarship);
10.5.5 帶ALL關鍵字的子查詢
ALL 關鍵字表示知足全部條件。使用ALL關鍵字時,只有知足內層查詢語句返回的全部結果,才能夠執行外層查詢語句。例如,須要查詢哪些同窗可以得到一等獎學 金。首先必須從獎學金錶中查詢出各類獎學金要求的最低分。由於一等獎金要求的分數最高。只有當同窗的成績高於全部獎學金最低分時,這個同窗纔可能得到等獎 學金。ALL關鍵字也常常與比較運算符一塊兒使用。
SELECT * FROM computer_stu
WHERE score>=ALL(SELECT score FROM scholarship);
10.6 合併查詢結果
合 並查詢結構是將多個SELECT語句的查詢結果合併到一塊兒。由於某種狀況下,須要將幾個SELECT語句查詢出來的結果合併起來顯示。例如,如今須要查詢 公司甲和公司乙這兩個公司全部員工的信息。這就須要從公司甲中查詢出全部員工的信息,再從公司乙查詢出全部員工的信息。而後將兩次的查詢結果合併到一塊兒。 進行合併操做使用UNION和UNION ALL關鍵字。
使用UNION關鍵字時,數據庫系統會將全部的查詢結果合併到一塊兒,而後去除相同的記錄。而UNION ALl關鍵字則只是簡單的合併到一塊兒。
SELECT語句1
UNION | UNION ALL
SELECT語句2
UNION | UNION ALL...
SELECT語句n;
SELECT d_id FROM department;
SELECT d_id FROM employee;
SELECT d_id FROM department
UNION
SELECT d_id FROM employee;
SELECT d_id FROM department
UNION ALL
SELECT d_id FROM employee;
10.7 爲表和字段取別名
在查詢時,能夠爲表和字段取一個別名。這個別名能夠代替其指定的表和字段。
10.7.1 爲表取別名
當 表的名稱特別長時,在查詢中直接使用表名很不方便。這時能夠爲表取一個別名。用這個別名代替表的名稱。例如,電力軟件中的變壓器的名稱爲 power_system_transform。若是要使用該表下面的字段id,但同時查詢的其餘表中也有id字段。這樣就必須指明是哪一個表下的id字 段,如power_system_transform.id。由於變壓器表的表名太長,使用起來不是很方便。爲了解決這個問題,能夠將變壓器表取一個別 名。如將power_system_transform取個別名爲t,那麼t就表明了變壓器表。t.id就與 power_system_transform.id表示的意思相同了。
MySQL 中爲表取別名的基本形式以下:
表名 表的別名
SELECT * FROM department [AS] D WHERE d.d_id=1001;
10.7.2 爲字段取別名
當 查詢數據時,MySQL會顯示每一個輸出列的名詞。默認的狀況下,顯示的列名是建立表是定義的列名。例如,department表的列名分別是d_id、 d_name、function和address。當查詢department表時,就會相應顯示這幾個列名。有時爲了顯示結果更加直觀,須要一個更加直 觀的名字來表示這一列。如department_name能夠很直接的知道是部門名稱。這時就須要將d_name字段取別名爲 deparment_name。
屬性名 [AS] 別名
SELECT d_id AS department_id, d_name AS department_name FROM department;
SELECT d.d_id AS department_id, d.d_name AS department_name, d.function, d.address FROM department d WHERE d.d_id=1001;
10.8 使用正則表達式查詢
正則表達式是用某種模式去匹配一類字符串的一個方式。例如,使用正則表達式能夠查詢出包含A、B、C其中任一字母的字符串。正則表達式的查詢能力比通配字符的查詢能力更強大,並且更加的靈活。正則表達式能夠應用於很是複雜查詢。
屬性名 REGEXP '匹配方式'
正則表達式的模式字符
模式字符 含義
^ 匹配字符串開始的部分
$ 匹配字符串結尾的部分
. 表明字符串中的任意一個字符,包括回車和換行
[字符集合] 匹配'字符集合'中的任何一個字符
[^字符集合] 匹配除了'字符集合'中的之外的任何一個字符
S1|S2|S3 匹配S一、S二、S3中的任意一個字符串
* 表明多個該字符以前的字符,包括0和1個
+ 表明多個該符號以前的字符,包括1個
字符串{N} 字符串出現N次
字符串{M,N} 字符串出現至少M次,最多N次
10.8.1 查詢以特定字符或字符串開頭的記錄
使用字符'^'能夠匹配特定字符或字符串開頭的記錄。下面從info表name字段中查詢以字母'L'開頭的記錄。
CREATE TABLE info(
id INT,
name VARCHAR(20)
) DEFAULT CHARSET=utf8;
INSERT INTO info VALUES(1, 'Aric');
INSERT INTO info VALUES(2, 'Eric');
INSERT INTO info VALUES(3, 'Jame');
INSERT INTO info VALUES(4, 'Jack');
INSERT INTO info VALUES(5, 'Lucy');
INSERT INTO info VALUES(6, 'Lily');
INSERT INTO info VALUES(7, 'Tom');
INSERT INTO info VALUES(8, 'aaa');
INSERT INTO info VALUES(9, 'dadaaa');
INSERT INTO info VALUES(10, '2323');
INSERT INTO info VALUES(11, 'bbdfec12');
INSERT INTO info VALUES(12, '212abc');
INSERT INTO info VALUES(17, 'werabc');
SELECT * FROM info WHERE name REGEXP '^L';
SELECT * FROM info WHERE name REGEXP '^aaa';
10.8.2 查詢以特定字符或字符串結尾的記錄
SELECT * FROM info WHERE name REGEXP 'c$';
# SELECT * FROM info WHERE name REGEXP 'aaa$';
10.8.3 用符號'.'來替代字符串任意一個字符
# SELECT * FROM info WHERE name REGEXP '^L..y$';
10.8.4 匹配指定字符串的任意一個
使用方括號([])能夠將須要查詢字符組成一個字符集。只要記錄中包含方括號中的任意字符,該記錄將會被查詢出來。例如,經過"[abc]"能夠查詢包括a、b、c這三個字母中任何一個的記錄。
SELECT * FROM info WHERE name REGEXP '[ceo]';
SELECT * FROM info WHERE name REGEXP '[0-9]';
10.8.5 匹配指定字符之外的字符
使用'[^字符集合]'能夠匹配指定字符之外的字符。從info表字段中查詢包含a到w字母和數字之外的字符的記錄。
SELECT * FROM info WHERE name REGEXP '[^a-w0-9]';
10.8.6 匹配指定字符串
正則表達式能夠匹配字符串。當表中的記錄包含這個字符串時,就能夠將該記錄查詢出來。若是指定多個字符串時,須要用符號'|'隔開。只要匹配這些字符串中的任意一個便可。
SELECT * FROM info WHERE name REGEXP 'ic';
SELECT * FROM info WHERE name REGEXP 'ic|ab|uc';
10.8.7 使用'*'和'+'來匹配多個字符
正則表達式中,'*'和'+'均可以匹配多個該符號之間的字符。可是,'+'至少表示一個字符,而'*'能夠表示零個字符。
SELECT * FROM info WHERE name REGEXP 'a*c';
SELECT * FROM info WHERE name REGEXP 'a+c';
10.8.8 使用{M}或者{M,N}來指定字符串連續出現的次數
正則表達式中,'字符串{M}'表示字符串連續出現M次;'字符串{M,N}'表示字符串聯連續出現至少M次,最多N次。例如,'ab{2}'表示字符串'ab'連續出現兩次。'ab{2,4}'表示字符串'ab'連續出現至少兩次,最多四次。
SELECT * FROM info WHERE name REGEXP 'a{3}';
SELECT * FROM info WHERE name REGEXP 'ab{1,3}';
10.9 本章實例
student表結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 學號 INT(10) 是 否 是 是 否
name 姓名 VARCHAR(20) 否 否 是 否 否
gender 性別 VARCHAR(4) 否 否 否 否 否
birth 出生年份 YEAR 否 否 否 否 否
department 院系 VARCHAR(20) 否 否 是 否 否
address 家庭住址 VARCHAR(50) 否 否 否 否 否
score表結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 編號 INT(10) 是 否 是 是 是
stu_id 學號 INT(10) 否 否 是 否 否
c_name 課程名 VARCHAR(20) 否 否 否 否 否
grade 分數 INT(10) 否 否 否 否 否
student表的記錄
id name gender birth department address
901 張老大 男 1985 計算機系 北京市海淀區
902 張老二 男 1986 中文系 北京市昌平區
903 張三 女 1990 中文系 湖南省永州區
904 李四 男 1990 英語系 遼寧省阜新市
905 王五 女 1991 英語系 福建省廈門市
906 王六 男 1988 計算機系 湖南省衡陽市
score表的記錄
id stu_id c_name grade
1 901 計算機 98
2 901 英語 80
3 902 計算機 65
4 902 中文 88
5 903 中文 95
6 904 計算機 70
7 904 英語 92
8 905 英語 94
9 906 計算機 90
10 906 英語 85
執行操做以下:
(1)先按照以上兩個表的結構建立表studetn和表socre。
(2)給兩個表增長記錄
(3)查詢student表的全部記錄
(4)查詢studnet表的第二條到第四條
(5)從student表查詢全部學生的學號、姓名和院系的信息。
(6)從student表中查詢計算機系和英語系的學生的信息
(7)從student表中查詢年齡爲18到22歲的學生的信息
(8)從student表中查詢每一個院系有多少人
(9)從score表中查詢每一個科目的最高分。
(10)查詢李四的考試科目和考試成績
(11)用鏈接查詢的方式查詢全部學生的信息和考試信息
(12)計算每一個學生的總成績
(13)計算每一個考試科目的平均成績
(14)查詢計算機成績低於95的學生的信息
(15)查詢同時參加計算機和英語系考試的學生的信息
(16)將計算機考試成績按從高到低進行排序
(17)從student表和score表中查詢出學生的學號、而後合併查詢結果
(18)查詢姓張或者姓王同窗的姓名、院系、考試科目和成績
(19)查詢都是湖南的同窗的姓名、年齡、院系、考試科目和成績
CREATE TABLE student(
id INT(10) NOT NULL UNIQUE PRIMARY KEY,
name VARCHAR(20) NOT NULL,
gender VARCHAR(4),
birth YEAR,
department VARCHAR(20) NOT NULL,
address VARCHAR(50)
) DEFAULT CHARSET=utf8;
CREATE TABLE score(
id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT,
stu_id INT(10) NOT NULL,
c_name VARCHAR(20),
grade INT(10)
) DEFAULT CHARSET=utf8;
INSERT INTO student VALUES
(901,'張老大','男','1985','計算機系','北京市海淀區'),
(902,'張老二','男','1986','中文系','北京市昌平區'),
(903,'張三','女','1990','中文系','湖南省永州區'),
(904,'李四','男','1990','英語系','遼寧省阜新市'),
(905,'王五','女','1991','英語系','福建省廈門市'),
(906,'王六','男','1988','計算機系','湖南省衡陽市');
INSERT INTO score VALUES
(NULL, 901, '計算機', 98),
(NULL, 901, '英語', 80),
(NULL, 902, '計算機', 65),
(NULL, 902, '中文', 88),
(NULL, 903, '中文', 95),
(NULL, 904, '計算機', 70),
(NULL, 904, '英語', 92),
(NULL, 905, '英語', 94),
(NULL, 906, '計算機', 90),
(NULL, 906, '英語', 85);
(3)SELECT * FROM student;
(4)SELECT * FROM student LIMIT 1,3
(5)SELECT id, name, department FROM student;
(6)SELECT * FROM student WHERE department IN('計算機系','英語系');
SELECT * FROM student WHERE department='計算機系' OR department='英語系';
(7)SELECT * FROM student WHERE YEAR(NOW())-birth BETWEEN 18 AND 22;
(8)SELECT department, COUNT(id) as sum_of_department FROM student GROUP BY department;
(9)SELECT c_name, MAX(grade) FROM score GROUP BY c_name;
(10) SELECT c_name, grade
FROM score
WHERE stu_id=(SELECT id FROM student WHERE name='李四');
(11)SELECT student.id, name, gender, birth, department, address, c_name,grade
FROM student, score
WHERE student.id=score.stu_id;
(12)SELECT stu_id, SUM(grade) FROM score GROUP BY stu_id;
SELECT student.id, name, SUM(grade)
FROM student, score
WHERE student.id=score.stu_id
GROUP BY student.id;
(13)SELECT c_name, AVG(grade) FROM score GROUP BY c_name;
(14)SELECT * FROM student
WHERE id IN(
SELECT stu_id FROM score
WHERE c_name='計算機' AND grade<95 15="" select="" from="" student="" where="" id="ANY" select="" stu_id="" from="" score="" where="" stu_id="" in="" select="" stu_id="" from="" score="" where="" c_name="計算機" and="" c_name="英語" 16="" select="" stu_id="" grade="" from="" score="" where="" c_name="計算機" order="" by="" grade="" desc="" 17="" student="" score="" select="" id="" from="" student="" union="" select="" stu_id="" from="" score="" 18="" select="" student="" id="" name="" gender="" birth="" department="" address="" c_name="" grade="" from="" student="" score="" where="" name="" like="" or="" name="" like="" and="" student="" id="score.stu_id;" 19="" select="" student="" id="" name="" gender="" birth="" department="" address="" c_name="" grade="" from="" student="" score="" where="" address="" like="" and="" student="" id="score.stu_id;" 10="" 10="" department="" d_id="" int="" 10="" d_name="" varchar="" 20="" function="" varchar="" 20="" address="" varchar="" 30="" employee="" id="" int="" 10="" name="" varchar="" 20="" gender="" varchar="" 4="" age="" tinyint="" d_id="" int="" 10="" salary="" float="" address="" varchar="" 50="" department="" d_id="" d_name="" function="" address="" 1001="" 1002="" 1003="" 1004="" employee="" id="" name="" gender="" age="" d_id="" salary="" address="" 9001="" aric="" 25="" 1002="" 4000="" 9002="" jim="" 26="" 1001="" 2500="" 9003="" tom="" 20="" 1003="" 1500="" 9004="" eric="" 30="" 1001="" 3500="" 9005="" lily="" 21="" 1002="" 3000="" 9006="" jack="" 28="" 1003="" 1800="" create="" database="" example2="" use="" example2="" create="" table="" department="" d_id="" int="" 10="" not="" null="" unique="" primary="" key="" d_name="" varchar="" 20="" not="" null="" function="" varchar="" 20="" address="" varchar="" 30="" default="" charset="utf8;" create="" table="" employee="" id="" int="" 10="" not="" null="" unique="" primary="" key="" name="" varchar="" 20="" not="" null="" gender="" varchar="" 40="" age="" tinyint="" unsigned="" d_id="" int="" 10="" salary="" float="" address="" varchar="" 50="" default="" charset="utf8;" insert="" into="" department="" values="" 1001="" insert="" into="" department="" values="" 1002="" insert="" into="" department="" values="" 1003="" insert="" into="" department="" values="" 1004="" insert="" into="" employee="" values="" 9001="" aric="" 25="" 1002="" 4000="" insert="" into="" employee="" values="" 9002="" jim="" 26="" 1001="" 2500="" insert="" into="" employee="" values="" 9003="" tom="" 20="" 1003="" 1500="" insert="" into="" employee="" values="" 9004="" eric="" 30="" 1001="" 3500="" insert="" into="" employee="" values="" 9005="" lily="" 21="" 1002="" 3000="" insert="" into="" employee="" values="" 9006="" jack="" 28="" 1003="" 1800="" 1="" employee="" 2="" employee="" 3="" department="" 4="" employee="" 5="" employee="" 25="" 30="" 6="" 7="" 8="" deparment="" employee="" 9="" 10="" employee="" 11="" department="" employee="" 12="" 13="" ric="" 14="" l="" y="" 15="" ric="" 16="" l="" y="" 1="" select="" from="" employee="" 2="" select="" from="" employee="" limit="" 3="" 2="" 3="" select="" d_id="" d_name="" function="" from="" department="" 4="" select="" from="" employee="" where="" d_id="" in="" select="" d_id="" from="" department="" where="" d_name="" in="" 5="" select="" from="" employee="" where="" age="" between="" 25="" and="" 30="" 6="" select="" count="" d_id="" from="" employee="" group="" by="" d_id="" 7="" select="" max="" salary="" from="" employee="" group="" by="" d_id="" 8="" 9="" select="" sum="" salary="" from="" employee="" group="" by="" d_id="" 10="" select="" from="" employee="" order="" by="" salary="" desc="" 11="" select="" d_id="" from="" department="" union="" select="" d_id="" from="" employee="" 12="" select="" name="" age="" address="" from="" employee="" where="" address="" like="" 13="" select="" from="" employee="" where="" name="" like="" _ric="" 14="" select="" from="" employee="" where="" name="" like="" l__y="" 15="" select="" from="" employee="" where="" name="" like="" _ric="" select="" from="" employee="" where="" name="" regexp="" ric="" 16="" select="" from="" employee="" where="" name="" regexp="" l="" y="" 10="" 11="" 1="" mysql="" mysql="" like="" regexp="" java="" javascript="" php="" 2="" limit="" select="" limit="" 10="" limit="" 10="" limit="" limit="" 3="" group="" by="" :="" group="" by="" count="" avg="" group="" by="" mysql5="" 1="" group="" by="" group="" by="" 4="" :mysql="" sql="" age="" 11="" insert="" update="" delete="" -="" -="" -="" 11="" 1="" mysql="" insert="" insert="" insert="" 11="" 1="" 1="" insert="" 1="" insert="" insert="" into="" values="" 1="" 2="" n="" insert="" into="" product="" values="" 1001="" 2="" insert="" insert="" into="" 1="" 2="" 3="" values="" 1="" 2="" n="" insert="" into="" product="" id="" function="" name="" address="" company="" values="" 1002="" insert="" into="" product="" id="" name="" function="" values="" 1003="" insert="" into="" product="" name="" company="" id="" values="" 1004="" show="" create="" table="" product="" g="" desc="" product="" 11="" 1="" 2="" insert="" insert="" mysql="" insert="" insert="" into="" values="" 1="" 2="" n="" insert="" into="" product="" values="" 1005="" 1="" dd="" 1006="" 2="" dd="" 1007="" 3="" dd="" insert="" into="" product="" id="" name="" company="" values="" 1008="" 1="" 1009="" 2="" 1010="" 3="" 11="" 1="" 3="" insert="" insert="" into="" 1="" 1="" select="" 2="" from="" 2="" where="" create="" table="" example="" medicine="" id="" int="" 10="" not="" null="" name="" varchar="" 20="" not="" null="" function="" varchar="" 50="" default="" null="" company="" varchar="" 20="" not="" null="" address="" varchar="" 50="" default="" null="" primary="" key="" id="" unique="" key="" id="" id="" default="" charset="utf8;" insert="" into="" medicine="" values="" 2001="" 1="" 2002="" 2="" 2003="" 3="" select="" from="" medicine="" insert="" into="" product="" id="" function="" name="" address="" company="" select="" id="" function="" name="" address="" company="" from="" medicine="" select="" from="" product="" where="" id="">=2001;
11.1.4 使用REPLACE語句替換數據
若是使用INSERT語句插入數據時,在表中已經有相同數據時(指的是PRIMARYT KEY或UNIQUE字段相同數據)會發生錯誤。而REPLACE INTO語句會刪除原有相同數據而插入新的數據。
INSERT INTO product VALUES
(1005, '頭疼靈1號', '治療頭疼', 'DD製藥廠', '北京市房山區');
REPLACE INTO product VALUES
(1005, '頭疼靈1號_replace', '治療頭疼', 'DD製藥廠', '北京市房山區');
11.2 更新數據
更新數據是更新表中已經存在的記錄。經過這種方式能夠改變表中已經存在的數據。例如。學生表中某個學生的家庭住址改變了,這就須要在學生表中修改該同窗的家庭地址。MySQL中,經過UPDATE語句來更新數據。
MySQL中,UPDATE語句的基本語法形式以下:
UPDATE 表名
SET 屬性名1=取值1,屬性名2=取值3,
...,
屬性名n=取值n
WHERE 條件表達式;
UPDATE product
SET function='保護皮膚的護膚品', address='吉林省延吉市開發區'
WHERE id=1004;
UPDATE product
SET function='護理頭髮', address='北京市昌平區'
WHERE id >=1008 AND id<=1010;
ALTER TABLE product
ADD price FLOAT(5,2) DEFAULT 0 COMMENT '價格';
ALTER TABLE product MODIFY price FLOAT(5,2) DEFAULT 0 AFTER name;
UPDATE product
SET price=330
WHERE id=1001;
UPDATE product
SET price=price+100
WHERE id=1001;
11.3 刪除記錄
刪除數據是刪除表中已經存在的記錄。經過這種方式能夠刪除表中再也不使用的記錄。例如,學生表中某個學生退學了,這就須要從學生表中刪除該同窗的信息。MySQL中,經過DELETE語句來刪除數據。MySQL中,DELETE語句的基本語法形式以下:
DELETE FROM 表名[WHERE 條件表達式];
DELETE FROM product WHERE id=1001;
DELETE FROM product; # 刪除product表中的全部記錄
TRUNCATE TABLE product; # 刪除product表中的全部記錄
11.4 本章實例
(1)建立表food表
food表的結構
字段名 字段描述 數據類型 主鍵 外鍵 非空 惟一 自增
id 編號 INT(10) 是 否 是 是 是
name 食品名稱 VARCHAR(20) 否 否 是 否 否
company 生產廠商 VARCHAR(30) 否 否 是 否 否
price 價格(單位:圓) FLOAT 否 否 否 否 否
product_year 生產年份 YEAR 否 否 否 否 否
validity_m 保質期(單位:月)TINYINT(3) 否 否 否 否 否
address 廠址 VARCHAR(50) 否 否 否 否 否
(2)向以列數據插入到food表中
food表的內容
id name company price product_year validity_time address
1 AA餅乾 AA餅乾廠 2.5 2008 36 北京
2 CC牛奶 CC餅乾廠 3.5 2009 12 河北
3 EE果凍 EE餅乾廠 1.5 2007 24 北京
4 FF咖啡 FF餅乾廠 20 2006 60 天津
5 GG奶糖 GG餅乾廠 14 2010 36 廣東
(3)將"CC牛奶廠"的廠址(address)必爲"內蒙古",而且將價格必爲3.2。
(4)將廠址在北京的公司的保質斯爲都改成5年。
(5)刪除過時食品的記錄。若當前時間-生產年份 > 保質期,則視爲過時食品。
USE example;
CREATE TABLE food(
id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT COMMENT '編號',
name VARCHAR(20) NOT NULL COMMENT '食品名稱',
company VARCHAR(30) NOT NULL COMMENT '生產廠商',
price FLOAT COMMENT '價格',
product_year YEAR COMMENT '生產年份',
validity_m TINYINT(3) COMMENT '保質期',
address VARCHAR(50) COMMENT '廠址'
) DEFAULT CHARSET=utf8;
INSERT INTO food VALUES (1,'AA餅乾','AA餅乾廠',2.5,'2008',36,'北京');
INSERT INTO food(id, name, company, price, product_year, validity_m, address)
VALUES(2,'CC牛奶','CC餅乾廠',3.5,'2009',12,'河北');
INSERT INTO food VALUES
(NULL, 'EE果凍', 'EE餅乾廠', 1.5, '2007', 24, '北京'),
(NULL, 'FF咖啡', 'FF餅乾廠', 20, '2006', 60, '天津'),
(NULL, 'GG奶糖', 'GG餅乾廠', 14, '2010', 36, '廣東');
UPDATE food SET address='內蒙古', price=3.2 WHERE company='CC餅乾廠';
UPDATE food SET validity_m=60 WHERE address='北京';
DELETE FROM food WHERE YEAR(NOW())-product_year > validity_m/12;
DELETE FROM food WHERE address='北京';
11.5 常見問題及解答
1. 插入記錄時,哪一種狀況不須要在INSERT語句中指定字段名?
答:INSERT語句中指定字段名爲了指明將數據插入到那個字段中。若是INSERT語句爲表中的全部字段賦值時,就能夠不須要指明字段名。數據庫系統會按順序將數據依次插入到全部字段中。有些表的字段特別多,有些字段不要賦值。這樣就必須指明爲哪些字段賦值。
2. 如何爲自增字段(AUTO_INCREMENT)賦值?
答: 在INSERT語句中能夠直接爲自增字段賦值。可是,大部分的自增字段是須要數據庫系統爲其自動生成一個值的。這樣能夠保證這個值的唯一性。用戶能夠經過 兩種方式來讓數據庫系統自動爲自增字段賦值。第一種方法是在INSERT語句中不爲該字段賦值。第二種方法是在INSERT語句中將該字段賦值爲 NULL。這兩種狀況下,數據庫系統自動爲自增字段賦值。並且,其值是上條記錄中該字段的取值值加一。
3. 如何進行聯表刪除?
答: 若是某個學生退學了,那麼就必須從學生表中刪除這個學生信息。同時,必須從數據庫中刪除全部與該同窗圖書信息、成績信息等。這就是必須刪除。在刪除學生表 中這個學生的信息時,要同時刪除全部其它表中該同窗的信息。這個能夠經過外鍵來實現。其它表中的信息與學生表中的信息都是經過學號來聯繫的。根據學號查詢 存在該同窗信息的表,刪除相應的數據。聯表刪除能夠保證數據庫中數據的一致性。
12.MysQL運算符
運 算符是用來鏈接表達式中各個操做數的符號,其做用是用來指明對操做數所進行的運算。MySQL數據庫支持使用運算符。經過運算符,能夠使數據庫的功能更加 強大。並且,能夠更加靈活的使用表中的數據。MySQL運算符包括四類、分別是算術運算符、比較運算符、邏輯運算符和位運算符。
- 算術運算符(加、減、乘、除、模)
- 比較運算符(大於、小於、等於、不等於、爲空)
主要用於數據的比較、字符串的匹配等方面。尤爲是LIKE、IN、BETWEEN AND、IS NULL等都是比較運算符。還有用於使用正則表達式的REGEXP也是比較運算符。
- 邏輯運算符(與、或、非、異或)
這種運算的結果只返回真值(1或者TRUE)和假值(0或者FALSE)
- 位運算符
包括按位與、按位或、按位取反、按位異或、按位左移和按位右移等位運算。
這些運算都必須先數值變爲二進制。而後在二進制數上進行操做的。
- 運算符的優先級
12.1 運算符簡介
當 數據庫中的表定義好之後,表中的數據表明的意義就已經定下來了。經過使用運算符進行運算,能夠獲得包含另外一層意義的數據。經過使用運算符進行運算,能夠得 到包含另外一層意義的數據。例如,學生表中存在一個birth字段,這個字段是表示學生出生年份。若是,用戶如今但願查找這個學生年齡。而學生表中只有出生 年份,沒有字段表示年齒。這就須要進行運算,用當前的年份減去學生的出生年份,這就能夠計算機學生的年齡了。
從上面能夠知道,MySQL運算符能夠指明對錶中數據所進行的運算,以便獲得用戶但願獲得的數據。這樣能夠使用MySQL數據庫更加靈活。MySQL運算符包括算術運算符、比較運算符、邏輯運算符和位運算符這四類。
12.2 算術運算符
算術運算符是MySQL中最經常使用的一類運算符。MySQL支持的算術運算符包括加、減、乘、除、求做。
符號 表達式的形式 做用
+ x1+x2+...+xn 加法運算
- x1-x2-...-xn 減法運算
* x1*x2*...*xn 乘法運算
/ x1/x2 除法運算,返回x1除以x2的商
DIV x1 DIV x2 除法運算,返回商。同"/"
% x1%x2 求餘運算,返回x2除以x2的餘數
MOD MOD(x1,x2) 求餘運算,返回餘數。同"%"
實例一:
USE example;
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(24);
SELECT a,a+5, a-5, a*5*2 FROM t1;
SELECT a, a/3, a DIV 3, a%3, MOD(a,3) FROM t1;
SELECT 5/0, 5 DIV 0, 5%0, MOD(5,0);
12.3 比較運算符
比較運算符是查詢數據時最經常使用的一類運算符。
SELECT語句中的條件語句常常要使用的比較運算符。經過這些比較運算符,能夠判斷表中的哪些記錄是符合條件。
比較運算符
符號 表達式的形式 做用
= X1=X2 判斷x1是否等於x2
<>或!= X1<>X2或x1!=x2 判斷x1是否不等於x2
> x1>x2 判斷x1是否大於x2
>= x1>=x2 判斷x1是否大於等於x2
< x1<x2 判斷x1是否小於x2
<= x1<=x2 判斷x2是否小於等於x2
IS NULL x1 IS NULL 判斷x1是否等於NULL
IS NOT NULL x1 IS NOT NULL 判斷x1是否不等於NULL
BETWEEN AND x1 BETWEEN M and n 判斷x1的取值是否在m和n之間
IN x1 IN(值1,值2,...值n) 判斷x1的取值是否值1到值n中的一個
LIKE x1 LIKE 表達式 判斷x1是否與表達式匹配
REGEXP x1 REGEXP 正則表達式 判斷x1是否與正則表達式匹配
實例一:
1. 運算符'='
'='能夠用來判斷數字、字符串、表達式等是否相等。若是相等,結果返回1,若是不相等,結果返回0.空值(NULL)不能使用'='來判斷。
SELECT a, a=24, a=20 FROM t1;
2. 運算符'<>'和'!='
’<>'和'!='能夠用來判斷數字、字符串、表達式等是否相等。若是不相等,結果返回1,若是相等,結果返回0。這兩個符號也不能用來判斷空值(NULL)。
SELECT a, a<>23, a!=23, a!=24, a!=NULL FROM t1;
3. 運算符'<=>'
'<=>'的做用與'='是同樣的,也是用來判斷操做數是否相等。不一樣的是,'<=>'能夠用來判斷NULL。
SELECT a, a<=>24, a<=>20 FROM t1;
SELECT 'b'<=>'b', 'b'<=>'c', NULL<=>NULL;
4. 運算符'>'
'>'用來判斷左邊的操做數是否大於右邊的操做數。若是大於返回1。若是不大於返回0.空值(NULL)不能使用'>'來判斷。
SELECT a,a>24,a>23 FROM t1;
SELECT 'b'>'c', 'bc'>'bb', NULL>NULL;
5. 運算符'>='
'>='用來判斷左邊的操做數是否大於等於右邊的操做數。若是大於等於返回1。若是不小於返回0.空值(NULL)不能使用'>='來判斷。
SELECT a,a>=24,a>=23 FROM t1;
SELECT 'b'>='c', 'bc'>='bb', NULL>=NULL;
6. 運算符'<'
'<'用來判斷左邊的操做數是否小於右邊的操做數。若是小於返回1。若是不小於返回0.空值(NULL)不能使用'<'來判斷。
SELECT a,a<24,a<23 FROM t1;
SELECT 'b'<'c', 'bc'<'bb', NULL<NULL;
7. 運算符'<='
'<='用來判斷左邊的操做數是否小於等於右邊的操做數。若是小於等於返回1。若是不大於返回0.空值(NULL)不能使用'<='來判斷。
SELECT a,a<=24,a<=23 FROM t1;
SELECT 'b'<='c', 'bc'<='bb', NULL<=NULL;
8. 運算符'IS NULL'
'IS NULL'用來判斷操做數是否爲空值(NULL)。操做數爲NULL時,結果返回1.操做數不爲NULL時,結果返回0.'IS NOT NULL'恰好與'IS NULL'相反。
SELECT a, a IS NULL, a IS NOT NULL FROM t1;
9. 運算符'BETWEEN m and n'
'BETWEEN AND'能夠判斷操做數是否在某個取值範圍以內。表達式'x1 BETWEEN m AND n'中,若是x1大於m,並且小於等於n,結果將返回1。若是不是,結果將返回0.
SELECT a, a BETWEEN 20 AND 28, a BETWEEN 25 AND 28 FROM t1;
10. 運算符'IN'
'IN'能夠判斷操做數是否在某個集合中。表達式'x1 IN(值1,值2,...,值n)'中,若是x1等於值1到值n中的任何一個值,結果將返回1.若是不是,結果將返回0。
SELECT a, a IN(2,20,24,28), a IN(3,7,9) FROM t1;
SELECT 'a' IN('a','c','e'), 'a' IN('b','c','d');
11. 運算符'LIKE'
'LIKE'用來匹配字符串。表達式'x1 LIKE s1'中,若是x1與字符串s1匹配,結果將返回1.若是不匹配,結果將返回0.\。
CREATE TABLE t2(s VARCHAR(20));
INSERT INTO t2 VALUES('beijing');
SELECT s, s LIKE 'beijing',s LIKE '___jing', s LIKE 'b%', s LIKE 's%' FROM t2;
12. 運算符'REGEXP'
'REGEXP'也用來匹配字符串,但其是使用正則表達式進行匹配的。表達式'x1 REGEXP 正則表達式'中,若是x1知足正則表達式,結果將返回1。若是不知足,結果將返回0.
SELECT s, s REGEXP '^b', s REGEXP 'g$', s REGEXP 'y' FROM t2;
12.4 邏輯運算符
邏輯運算符用來判斷表達式的真假。邏輯運算符的返回結果只有1和0。若是表達式是真,結果返回1。若是表達式是假,結果返回0。邏輯運算符又稱爲布爾運算符。
MySQL中支持四種邏輯運算符。這四種邏輯運算符分別是與、或、非和異或。
符號 名稱
&&或者AND 與
||或者OR 或
!或者NOT 非
XOR 異或
1. 與運算
"&&" 或者AND表示與運算。全部操做數不爲且不爲空值(NULL)時,結果返回1;存在任何一個操做數爲0時,結果返回0;存在一個操做數爲NULL且沒有操 做數爲0時,結果返回NULL。與運算符"&&"能夠有多個操做數同時進行與運算,其基本形式 爲"x1&&x2&&...&&xn"
SELECT -1 && 2&&3, 0&&3, 0&&NULL, 3&&NULL;
與運算符AND 能夠有多個操做數同時進行與進行,其基本形式爲"x1 AND x2 AND ... AND xn"。可是多操做數與"AND"之間要用空格隔開。
SELECT -1 AND 2 AND 3, 0 AND 3, 0 AND NULL, 3 AND NULL;
2. 或運算
'||' 或者OR表示或運算。全部操做數中存在任何一個操做數不爲非0的數字時,結果返回1;若是操做數中不包含非0的數字,但包含NULL時,結果返回 NULL;若是操做數中只有0時,結果返回0.或運算符'||'能夠有多人操做數同時進行或運算,其基本形式爲'x1||x2||...||xn'。
SELECT 1 || -1 || NULL || 0, 3 || NULL, 0 || NULL, NULL | NULL, 0||0;
或運算符OR能夠有多個操做數現時進行或運算。其基本形式爲'x1 OR x2 OR...OR xn'。
SELECT 1 OR -1 OR NULL OR 0, 3 OR NULL, 0 OR NULL, NULL OR NULL, 0 OR 0;
3. 非運算
'!'或者NOT表示非運算。經過非運算,將返回與操做數相反的結果。若是操做數是非0的數字,結果返回0;若是操做數是0,結果返回1;若是操做數是NULL,結果返回NULL。或運算符'!'只能有一個操做數進行非運算,其基本形式爲'!x1'。
SELECT !1, !0.3, !-3, !NULL;
下面使用'NOT'的例子:
SELECT NOT 1, NOT 0.3, NOT -3, NOT NULL;
4. 異或運算
XOR表示異或運算。異或運算符XOR的基本形式爲'x1 XOR x2'。只要其中任何一個操做數爲NULL時,結果返回NULL;若是x1和x2都是非0的數字或者都是0時,結果返回0;若是x1和x2中一個是非0,另外一個是0時,結果返回1。
SELECT NULL XOR 1, NULL XOR 0, 3 XOR 1, 1 XOR 0, 0 XOR 0, 3 XOR 2 XOR 0 XOR 1;
12.5 位運算符
位運算符是在二進制數上進行計算的運算符。位運算會先將操做數變成二進制數,而後進行位運算。而後再計算結果從二進制數變回十進制數。MySQL中支持六種位運算符。這六種位運算符分別是按位與、接位或、接位取反、接位異或、接位左移和接位右移。
位運算符
符號 名稱
& 按位與
| 按位或
~ 按位取反
^ 按位異或
<< 按位左移
>> 按位右移
1. 按位與
'&'表示按位與。進行該運算時,數據庫系統會先將十進制數據轉換爲二進制的數。而後對應操做數的每一個二進制數位上進行與運算。1和1相與得1,與0相與得0.運算完成後再將二進制數變回十進制數。
SELECT 5&6, 5&6&7;
2. 按位或
'|'表示按位或。將操做數化爲二進制數後,每位都進行或運算。1和任何數進行或運算結果都是1,0與0或運算結果爲0。
SELECT 5|6, 5|6|7;
3. 按位取反
'~'表示按位取反。將操做數化爲二進制數後,每位都進行取反運算。1取反後變成0,0取反後變成1.
SELECT ~1;
下面使用BIN()函數來查看常數1取反結果的二進制數
SELECT BIN(~1);
4. 按位異或
'^'表示按位異或。將操做數化爲二進制數後,每位都進行或運算。相同的數異或以後結果是0,不一樣的數異或以後結果爲1.
SELECT 5^6;
5. 按位左移與按位右移
'<<' 表示按位左移。'm'<<'n'表示m的二進制數向左移n位,右邊補上n個0。例如,二進制數001左移1位後將變成0010。 '>>'表示按位右移。'm>>n'表示m的二進制數向右移n位,左邊補上n個0。二進制數011右移1位後變成001,最後一 個被移出去了,直接就不要了。
SELECT 5<<2 5="">>2;
12.6 運算符的優先級
因爲在實際應用中可能須要同時使用多個運算符。這就必須考慮運算符的運算順序。到底誰先運算,誰後運算。MySQL表達式都是從左到右開始運算,哪一個運算符的優先級別高,哪一個運算符先進行計算。
優先級 運算符
1 !
2 ~
3 ^
4 % / DIV % MOD
5 + -
6 >> <<
7 &
8 |
9 = <=> < <= > >= != <> IN IS NULL, is NOT NULL, LIKE, REGEXP
10 BETWEEN AND, CASE, WHEN, THEN, ELSE
11 NOT
12 &&, AND
13 || OR XOR
14 =
實際使用的時候()來將優先級計算內容括起來,這樣用起來更加簡單,並且可讀性更強。
12.7 本章實例
1. 在t表上使用算術運算符和比較運算符進行運算
2. 將數字2,0和NULL之間的任意兩個進行邏輯運算
3. 按下列要求進行位運算
(1)t表上只包含兩個字段。分別是字段num和字段str,二者分別是INT類型和VARCHAR類型。
CREATE TABLE t(num INT, str VARCHAR(2));
(2)向t表中插入一條記錄。num值爲30,str值爲'mysql'。
INSERT INTO t VALUES(30, 'mysql');
(3)從t表中取出num的值與數字4進行加法、減法、乘法、除法和求餘運算。
SELECT num, num+4, num-4, num*4, num DIV 4, num%4 FROM t;
(4)使用比較運算符將num的值與20進行比較。
SELECT num, num=20, num<>20, num>20, num>=20, num<20, num<=20, num<=>20 FROM t;
(5)判斷num的值是否在26到33之間,而且判斷num的值是否在(3, 28, 30, 33)這個集合中。
SELECT num, num BETWEEN 26 AND 33, num IN(3, 28, 33) FROM t;
(6)判斷t表的str字段值是否爲空;用LIKE來判斷是不是以'my'這兩個字母開頭;用REGEXP來判斷是否第一字母是m,最後一個字母是y。
SELECT str, str IS NULL, str LIKE 'my%', str REGEXP '^my', str REGEXP 'y$' FROM t;
SELECT !2, !0, NOT NULL, 2 XOR 0, 2 XOR NULL, 0 XOR NULL;
1. 將數字4和6進行按位與、接位或。並將4按位取反。
SELECT 4&6, 4|6, ~4;
2. 將數字6分別左移兩位和右移兩位。
SELECT 6<<2 6="">>2;
12.8 上機實踐
(1)的MySQL中執行下面的表達式:4+3-1, 3*2+7, 八、3, 9%2
(2)在MySQL中執行下面的表達式:30>28, 17>=16, 30<28, 17<=16, 17=17, 16<>17, 7<=>NULL, NULL<=>NULL
(3)判斷字符串'mybok'是否爲空,是否以字母m開頭,以字母k結尾。
(4)在MySQL中執行下列邏輯運算:2&&0&&NULL, 1.5&&2, 3||NULL, NOT NULL, 3 XOR 2, 0 XOR NULL
(5)在MySQL中執行下列位運算:3&5, 3|5, 3^5, ~5
(6)將12左移兩位,將9右移三位。
SELECT 4+3-1, 3*2+7, 8/3, 8 DIV 3, 9%2, MOD(9,2);
SELECT 30>28, 17>=16, 30<28, 17<=16, 17=17, 16<>17, 7<=>NULL, NULL<=>NULL;
SELECT 'mybook' IS NULL, 'mybook' LIKE 'm%', 'mybook' REGEXP 'k$';
SELECT 2&&0&&NULL, 1.5&&2, 3||NULL, NOT NULL, 3 XOR 2, 0 XOR NULL;
SELECT 3&5, 3|5, 3^5, ~5;
SELECT 12<<2 9="">>3;
set profiling=1;
select * from t;
show profiles;
12.9 常見問題及解答
1. 比較比較運算符結果只能是0和1嗎?
答:MySQL 中,比較運算符用來判斷運算符兩邊的操做數的大小關係。例如a>b就是用來判斷a是否大於b。若是大於則返回真;若是不大於則返回假。MySQL 中,真是用1來表示的,假是用0來表示的。因此,比較運算符的運算結果只有0和1.不只比較運算符是如此,邏輯運算符的運算結果也只有0和1。
2. 哪一種運算符的優先級別最高?
答:非運算(!)的級別最高,賦值符號(:=)的級別最低。可是,一般狀況下能夠使用括號來設定運算符的前後順序。使用括號能夠使運算的層次更加清晰,並且能夠沒必要侷限於各類運算符的優先級別。
3. 十進制數也能夠直接使用位運算符嗎?
答: 在進行位運算時,數據庫系統會先將全部的操做數轉換爲二進制數。而後將這些二進制數進行位運算,而後將這些運算結果轉換爲二進制數。因此,位運算符的操做 數是十進制數。十進制數與二進制數之間的互換是數據庫系統實現的。所以,位運算的操做數必須是十進制數,不然計算的結果就會是錯誤的。在使用位運算符時, 若是操做數是二進制數、八進制數、十六進制數,要先經過CONV()函數將操做數轉換爲十進制數。而後,才能進行相應的位運算。
13.MySQL函數
MySQL數據庫中提供了很豐富的函數。經過這些函數能夠簡化用戶的操做。
13.1 數學函數:主要用於處理數字
13.1.1 絕對值函數ABS(x)和返回圓周率函數PI()
SELECT ABS(10.4), ABS(-10.4), PI();
13.1.2 平方根函數SQRT(x)和求餘函數MOD(x,y)
SELECT SQRT(16),SQRT(2), MOD(5,2);
13.1.3 獲取整數的函數CEIL(x)、CEILING(x)和FLOOR(X);
SELECT CEIL(10.6), CEILING(10.2), FLOOR(120.5);
13.1.4 獲取隨機數的函數RAND()和RAND(x)(0~1之間的隨機數)
SELECT RAND(), RAND(), RAND(2), RAND(2), RAND(3);
13.1.5 四捨五入函數ROUND(x)、ROUND(X,Y)和TRUNCATE(x,y)
round(x)函數返回離x最近的整數,也就是對x進行四舍五到處理;round(x,y)函數返回x保留到小數點後y位的值,截斷時須要進行四捨五入處理;truncate(x,y)函數返回x保留到小數點後y位的值,不進行四捨五入處理。
SELECT ROUND(2.3), ROUND(2.5), ROUND(2.53, 1), ROUND(2.55, 1);
SELECT TRUNCATE(2.53, 1), TRUNCATE(2.55, 1);
13.1.6 符號函數SIGN(X)
SELECT SIGN(-2),SIGN(0),SIGN(2);
13.1.7 冪運算函數POW(X,Y)、power(x,y)和exp(x)
SELEC pow(3,2), POWER(3,2),EXP(2);
13.1.8 對數運算函數LOG(X)和log10(x)函數
log(x)函數計算x的天然對數;log10(x)函數計算以10爲底的對數。exp(x)和log(x)這兩個函數互爲反函數。
SELECT log(7.38905609893065), LOG10(100);
13.1.9 角度和弧度相互轉換的函數
radians(x)函數將角度轉換爲弧度;
degrees(x)函數將弧度轉換爲角度。這兩個函數互爲反函數
SELECT RADIANS(180), DEGREES(3.131592653589793);
13.1.10 正弦函數SIN(X)和反正弦函數ASIN(X)
SIN(X)函數用來求正弦值,其中x是弧度;
ASIN(X)函數用來求反正弦值。ASIN(X)中聚值必須在-1到1之間。不然返回的結果將會是NULL。
SELECT SIN(0.5236987755982989), ASIN(0.5);
13.1.11 餘弦函數COS(x)和反餘弦函數ACOS(X)
cos(x)函數用來求餘弦值,其中X是弧度;
acos(x)函數用來求反餘弦值。
cos(x)和acos(x)互爲反函數。
而且,acos(x)中x的取值必須在-1到1之間。不然返回的結果將會是NULL。
SELECT cos(1.0471975511965979), acos(0.5);
13.1.12 正切函數、反正切函數和餘切函數
tan(x)函數用來求正切值,其中x是弧度;atan(x)和atan2(x)用來求反正切值;cot(x)函數用來求餘切值。tan(x)和atan(x)、atan2(x)互爲反函數。並且 tan(x)返回值是cos(x)返回值的倒數。
SELECT tan(0.7953981633974483), atan(1),atan2(1);
SELECT COT(1), 1/TAN(1);
13.2 字符串函數
13.2.1 計算字符串字符數的函數和字符串長度的函數
char_length(s)函數計算字符串s的字符數;length(s)函數計算字符串s的長度。
SELECT CHAR_LENGTH('ABC'),CHAR_LENGTH('中國人民'),LENGTH('ABC'),LENGTH('中國人民');
13.2.2 合併字符串的函數concat(s1,s2,...)和concat_ws(x,s1,s2);
SELECT CONCAT('X','Y','_A'), CONCAT_WS('-', 'bei','jing');
13.2.3 替換字符串的函數insert(s1,x,len,s2);
SELECT INSERT('beijing', 4, 4, 'fang');
13.2.4 字母大小寫轉換函數
upper(s)函數和ucase(s)函數將字符串s的全部字母變成大寫字母;lower(s)函數和lcase(s)函數將字符串s的全部字母變成小寫字母。
SELECT UPPER('MySQl'), UCASE('mysql'), LOWER('MySQL'), LCASE('MySQL');
13.2.5 獲取指定長度的字符串的函數left(s,n)和right(s,n)
left(s,n)函數返回字符串s的前n個字符;
right(s,n)函數將返回字符串s的後n個字符
SELECT left('d00010005', 5), right('d00010005',4);
13.2.6 填充字符串的函數lpad(s1,len,s2)和rpad(s1,len,s2)
lpad(s1,len,s2)函數將字符串s2填充到s1的開始處,使字符串長度達到len;
rpad(s1,len,s2)函數將字符串s2填充到s1的結尾處,使字符串長度達到len。
SELECT lpad('beiing', 10, '+-'), rpad('beiing', 11, '+-');
13.2.7 刪除空格的函數ltrim(s)、rtrim(s)和trim(s)
SELECT concat('*',trim(' sd '),'*'), concat('*',ltrim(' left '),'*'), concat('*',rtrim(' right '),'*');
13.2.8 刪除指定字符串的函數trim(s1 from s);
trim(s1 from s)函數將去年字符串s中開始處和結尾處的字符串s1。
SELECT trim('ab' FROM 'ababddddabddab');
13.2.9 重複生成字符串的函數repeat(s,n)
repeat(s,n)函數將字符串s重複n次。
SELECT REPEAT('mysql-', 2);
13.2.10 空格函數space(n)和替換函數replace(s,s1,s2);
space(n)函數返回n個空格;replace(s,s1,s2)函數將字符串s2替代字符串s中的字符串s1。
SELECT concat('+',space(4), '+'), replace('mysql','sql','book');
13.2.11 比較字符串大小的函數strcmp(s1,s2);
select strcmp('a','b'), strcmp('b','a'), strcmp('a','a');
13.2.12 獲取子串的函數substring(s,n,len)和mid(s,n,len);
substring(s,n,len)函數和mid(s,n,len)函數從字符串s的第n個位置開始獲取長度爲len的字符串。
SELECT 'beijing', substring('beijing', 4, 3), mid('beijing',4,3);
13.2.13 匹配子串開始位置的函數
locate(s1,s)、position(s1 IN s)和INSTR(s,s1)這三個函數從字符串s中獲取s1的開始位置。
SELECT 'beijing', locate('jin', '00beijing'), position('jin' IN '0beijing'), INSTR('beijing','jin');
13.2.14 字符串逆序的函數reverse(s);
SELECT 'beijing', reverse('beijing');
13.2.15 返回指定位置的字符串的函數
elt(n,s1,s2,...)函數返回第n個字符串。
SELECT elt(2,'me','my','he','she');
13.2.16 返回指定字符串位置的函數
field(s,s1,s2,..)函數返回第一個與字符串s匹配的字符串的位置。
SELECT field('he','me','my','he','she');
13.2.17 返回子串位置的函數
find_in_set(s1,s2)函數返回在字符串s2中與s1匹配的字符串的位置。其中,字符串s2中包含了若干個用逗號隔開的字符串。
SELECT FIND_IN_SET('like', 'i,like,bei,jing');
13.2.18 選取字符串的函數make_set(x,s1,s2,...)函數
make_set(x,s1,s2,...)函數按x的二進制數從s1,s2,...,sn中選取字符串。
SELECT make_set(11,'a','b','c','d'), make_set(7, 'a','b','c','d');
13.3 日期和時間函數
日期和時間函數是MySQL中另外一類最經常使用的函數。日期和時間函數主要用於處理表中的日期和時間數據。日期和時間函數包括獲取當前日期的函數、獲取當前時間的函數、計算日期的函數、計算時間的函數等。
13.3.1 獲取當前日期的函數和獲取當前時間的函數
獲取當前日期: curdate()和current_date()
獲取當前時間: curtime()和current_time()
select curdate(),current_date(), curtime(),current_time();
13.3.2 獲取當前日期和時間的函數
now()、current_timestamp()、localtime()和sysdate()
select now(),current_timestamp(),localtime(),sysdate();
13.3.3 UNIX時間戳函數
UNIX_TIMESTAMP() 函數以UNIX時間戳的形式返回當前時間:UNIX_TIMESTAMP(d)函數將時間d以UNIX時間戳的形式返 回;FROM_UNIXTIME(d)函數把UNIX時間戳的時間轉換爲普通格式的時間。UNIX_TIMESTAMP(d)函數和 FROM_UNIEXTIME(d)互爲如此函數。
select now(),UNIX_TIMESTAMP(),UNIX_TIMESTAMP(NOW());
select unix_timestamp(), FROM_UNIXTIME('1256458559');
13.3.4 返回UTC日期函數和返回UTC時間的函數
UTC_DATE()函數返回UTC日期;UTC_TIME()函數返回UTC時間。其中,UTC是Universal Coordinated Time的縮寫,也就是國際協調時間。
select curdate(),UTC_DATE(), curtime(),utc_time();
13.3.5 獲取月分的函數month(d)和monthname(d)
month(d)函數返回日期d中的月分值,其取值範圍是1~12;
monthname(d)函數返回日期d中的月分的英文名稱,如January,February等。
select month(now()), monthname(now());
13.3.6 獲取星期的函數 dayname(d)、dayofweek(d)和weekday(d);
dayname(d)函數返回日期d是星期幾,顯示其英文名稱,如Monday,Tuesday等。
dayofweek(d)函數也返回日期d是星期幾,1表示日期日,2表示星期一。
weekday(d)函數也返回日期d是星期幾。0表示星期一,一表示星期二。
select dayname(now()), dayofweek(now()), weekday(now());
13.3.7 獲取星期數的函數week(d)和weekofyear(d)
返回本年第幾個星期。返回值的返回時1~53
select now(), week(now()), weekofyear(now());
13.3.8 獲取天數的函數dayofyear(d)和dayofmonth(d)
dayofyear(d)函很多天期d是本年的第幾天;
dayofmonth(d)函數返回計算日期d是本月的第幾天。
select now(), dayofyear(now()), dayofmonth(now());
13.3.9 獲取年份、季度、小時、分鐘、秒鐘的函數
year(d)函數返回日期d中的年份值;
quarter(d)函數返回日期d是本年第幾季度,值範圍是1~4
hour(t)函數是返回時間t中的小時值;
minute(t)函數是返回時間t中的分鐘值;
second(t)函數返回時間t中的秒鐘值。
select now(), year(now()), quarter(now()), hour(now()), minute(now()), second(now());
13.3.10 獲取日期的指定值函數extract(type from d);
extract(type from d)函數從日期d中獲取指定的值。這個值是什麼由type的值決定。type的取值能夠是year、month、day、hour、minute、 second。若是type的值是year,結果返回年份值;month返回月分值;day返回是幾號;hour返回小時值;minute返回分鐘 值;second返回秒鐘值。
select now(), extract(year from now()),extract(minute from now());
13.3.11 時間和秒鐘轉換的函數
TIME_TO_SEC(t)函數將時間t轉換爲秒爲單位的時間;
sec_to_time(s)函數將以秒爲單位的時間s轉換爲時分秒的格式。
time_to_sec(t)和sec_to_time(s)互爲反函數。
select now(), time_to_sec(now()), sec_to_time(58559);
13.3.12 計算日期和時間的函數
1. to_days(d)、from_days(n)和datediff(d1,d2)函數
to_days(d):日期轉換整天數
from_days(n):天數轉換成日期
datediff(d1,d2):比較天數
2. adddate(d,n)、subdate(d,n)、addtime(t,n)和subtime(t,n)函數
adddate(d,n):增長日期
subdate(d,n):減去日期
addtime(t,n):增長多少秒
subtime(t,n):減去多少秒
3. adddate(d, interval expr type)和date_add(d, interval expr type)函數
select now(), to_days(now()) as a, from_days(734070) as b, datediff(now(),'2009-10-24') as c ;
select now(),adddate(now(),3) as a, subdate(now(),3) as b;
select now(), addtime(now(),3) as c, subtime(now(),3) as d;
MySQL的日期間隔類型
類型 含義 expr表達式的形式
YEAR 年 YY
MONTH 月 MM
DAY 日 DD
HOUR 時 hh
MINUTE 分 mm
SECOND 秒 ss
YEAR_MONTH 年和月 YY和MM之間用任意符號隔開
DAY_HOUR 日和小時 DD和hh之間用任意符號隔開
DAY_MINUTE 日和分鐘 DD和mm之間用任意符號隔開
DAY_SECOND 日和秒鐘 DD他ss之間用任意符號隔開
DAY_MINUTE 時和分 hh和mm之間用任意符號隔開
HOUR_SECOND 時和秒 hh和ss之間用任意符號隔開
MINUTE_SECND 分和秒 mm和ss之間用任意符號隔開
select now(), adddate(now(), interval '1 1' YEAR_MONTH);
select now(), adddate(now(), interval '-1 -11' year_month);
13.3.13 將日期和時間格式化的函數
1. date_format(d,f)函數
2. time_format(t,f)函數
3. get_format(type,s)函數
MySQL日期時間格式
符號 含義 取值示例
%Y 以4位數字表示年份 200八、2008等
%y 以2位數字表示年份 98,99等
%m 以2位數字表示月分 01,02,...,12
%c 以數字表示月分 1,2,...,12
%M 月份的英文名 January,February,...,December
%b 月份的英文縮寫 Jan,Feb,...,Dec
%U 表示星期數,其中Sunday是星期的第一天 00~52
%u 表示星期數,其中Monday是星期的第一天 00~52
%j 以3位數字表示年中的天數 001~366
%d 以2位數字表示月中的幾號 01,02,...,31
%e 以數字表示月中的帳號 1,2,...,31
%D 以英文後綴表示月中的幾號 1st,2dn,..,
%w 以數字的形式表示星期幾 0表示Sunday,...,Sunday
%W 星期幾的英文名 Monday,...,Sunday
%a 星期幾的英文縮寫 Mon,...,Sun
%T 24小時制的時間形式 00:00:00~23:59:59
%r 12小時制的時間形式 12:00:00AN~11:59:59PM
%p 上午(AM)或下午(PM) AM或PM
%k 以數字表示24小時 0,1,...,23
%l 以數字表示12小時 1,2,...,12
%H 以2位數表示24小時 00,01,...,23
%h,%I 以2位數表示12小時 01,02,...,12
%i 以2位數表示分 00,00,...,59
%S,%s 以2位數表示時 00,01,...,59
%% 標識符% %
select now(), date_format(now(), "%b %D %Y");
select now(), date_format(now(), "%j")day, date_format(now(),"%W")week;
select now(), time_format(now(),'%r');
GET_FORMAT()函數返回的格式字符串
函數 返回的格式字符串 日期與時間的示例
get_format(date,'EUR') '%d.%m.%Y' 30.02.2010
get_format(date,'USA') '%m.%d.%Y' 02.30.2010
get_format(date,'ISO') '%Y-%m-%d' 2010-02-30
get_format(date,'INTERNAL') '%Y-%m-%d' 2010-02-30
get_format(datetime,'EUR') '%Y-%m-%d-%h.%i.%s' 2010-02-30-15.20.04
get_format(datetime,'USA') '%Y-%m-%d-%H.%i.%s' 2010-02-30-15.20.04
get_format(datetime,'JIS') '%Y-%m-%d %H:%i:%s' 2010-02-30 15:20:04
get_format(datetime,'ISO') '%Y-%m-%d %H:%i:%s' 2010-02-30 15:20:04
get_format(datetime,'INTERNAL') '%Y%m%d%H%i%s' 20100230152004
get_format(time,'EUR') '%H.%i.%S' 15.20.04
get_format(time,'USA') '%h.%i.%s %p' 03.20.04 PM
get_format(time,'JIS') '%H:%i:%s' 15:20:04
get_format(time,'ISO') '%H:%i:%s' 15:20:04
get_format(time,'internal') '%H%i%s' 15:20:04
select now(),get_format(DATETIME,'ISO'), get_format(DATE,'EUR'),get_format(TIME,'USA');
select time_format(now(), get_format(TIME,'usa'));
13.4 條件判斷函數
條件判斷函數用來在SQL語句中進行條件判斷。根據是否知足判斷條件,SQL語句執行不一樣的分支。例如,從員工表中查詢員工的業績。若是業績高於指定值n,則輸出"good"。不然,輸出"bad"。下面是各類條件判斷函數的表達式、做用和使用方法。
13.4.1 IF(expr,v1,v2)函數
若是表達式expr成立,返回結果v1,不然,返回結果v2。
select id, grade,if(grade>=60, 'PASS', 'FALL') from example.score;
13.4.2 ifnull(v1,v2)函數
create table info(
id int not null primary key auto_increment,
name varchar(20)
) default charset=utf8;
insert into info values(null, null);
select id,name,ifnull(name, 'is empty') from info;
13.4.3 case函數
1.case when expr1 then v1 [when expr2 then v2...][else vn] end
2.case expr when e1 then v2 [when e2 then v2...][else vn] end
select id,grade,case when grade>80 then 'good' when grade>60 then 'pass' else 'fall' end level from score;
select id,grade, case grade when 90 then 'good' when 90 then 'pass' when 50 then 'fail' else 'no grade' end level from score;
13.5 系統信息函數
系統信息函數用來查詢MySQL數據庫的系統信息。例如,查詢數據庫的版本,查詢數據庫的當前用戶等。 13.6 加密函數
13.5.1 獲取MySQL版本號、鏈接數、數據庫名的函數
version()函數返回數據庫的版本號;
connection_id()函數返回服務器的鏈接數,也就是到如今爲止MySQL服務的鏈接次數;
database()和schema()返回當前數據庫名
select version(), connection_id(), database(), schema();
13.5.2 獲取用戶名的函數
user()
system_user()
session_user()
current_user()
current_user
13.5.3 獲取字符串的字符集和排序方式的函數
charset(str)函數返回字符串str的字符集,通常狀況這個字符集就是系統的默認字符集;
collation(str)函數返回字符串str的字符排列方式。
13.5.4 獲取最後一個自動生成的ID值的函數
last_insert_id()函數返回最後生成的auot_increment值。
13.6 加密函數
加密函數是MySQL中用來對數據進行加密的函數。由於數據庫中有些很敏感的信息不但願被其餘人看到,就應該經過加密方式來使這些數據變成看似亂碼的數據。例如用戶的密碼,就應該通過加密。
下面是各類加密函數的名稱、做用和使用方法。
13.6.1 加密password(str)
對字符中str進行加密。通常狀況下,password(str)函數主要是用來給用戶的密碼加密的。
select password('abcd');
13.6.2 加密函數md5(str)
md5(str)函數主要對普通的數據進行加密。
select md5('abcd');
13.6.3 encode(str,pawd_str);
能夠使用字符串pswd_str來加密字符中str。加密的結果是一個二進制數,必須使用blog類型的字段來保存它。
CREATE TABLE `crypt`(
id int not null primary key auto_increment,
passwd blob
)
insert into crypt values(null, encode('abcc','aa'));
13.6.4 解密函數decode(crypt_str,pswd_str)
使用字符串pswd_str來爲crypt_str解密。crypt_str是經過encode(str,pswd_str)加密後的二進制數據。字符串pswd_str應該與加密時的字符串pswd_str是相同的。
select decode(encode('abcc','aa'),'aa');
13.7 其它函數
MySQL中除了上述函數之外,還包含了不少函數。例如format(x,n)函數來格式化數字x,inet_aton() 函數能夠將ip轉換爲數字。
13.7.1 格式化函數format(x,n);
將數字x進行格式化,將x保留到小數點後n位。這個過程須要進行四捨五入。例如format(2.356,2)返回的結果將會是2.36;
format(2.353,2)返回的結果將會是2.35。
select format(234.3456,2), format(235.345,2);
13.7.2 不一樣進行的數字進行轉換的函數
ASCII(s)返回字符串s的第一個字符的ASCII碼;
BIN(x)返回x的二進制編碼;
HEX(x)返回x的十六進制編碼;
oct(x)返回x的八進制編碼;
conv(x,f1,f2)將x從f1進制數變成f2進制數。
select ascii('abc'), bin(28),hex(28), oct(28), conv(15,10,2);
13.7.3 IP地址與數字相互轉換的函數
inet_aton('ip')函數能夠將ip地址轉換爲數字表示;
inet_ntoa(n)函數能夠將數字n轉換成ip的形式。
select inet_aton('59.65.226.15'), inet_ntoa(inet_aton('59.65.226.15'));
13.7.4 加鎖函數和解鎖函數
get_loct(name,time)函數定義一個名稱爲name、持續時間長度爲tiem秒的鎖。若是鎖定成功,返回1;若是嘗試超時,返回0;若是遇到錯誤,返回null。
release_lock(name)函數解除名稱爲name的鎖。若是解鎖成功,返回1;若是嘗試超時,返回0;若是解鎖失敗,返回null;is_free_lock(name)函數判斷是否使用名爲name的鎖。若是使用,返回0;不然,返回1。
# 給一個名爲mysql的鎖,持續時間是10秒。而後判斷這個鎖是否加上。最後解除鎖定
select get_lock('mysql',10);
select is_free_lock('mysql');
select release_lock('mysql');
select is_free_lock('mysql');
13.7.5 重複執行指定操做的函數
benchmark(count,expr)函數將表達式expr重複執行count次,而後返回執行時間。該函數能夠用來判斷MySQL處理表達式的速度。
select benchmark(10000000,now());
13.7.6 改變字符集的函數
convert(s USING cs)函數將字符串s的字符集變成cs。
# 將字符串'abc'的字符集變成gbk。
select charset('abc'),charset(convert('abc' using utf8));
13.7.7 改變字段數據的函數
cast(x as type)和convert(x,type)這兩個函數將x變成type類型。這兩個函數只對binary、char、date、datetime、 time、signed integer、unsigned integer這些類型起做用。但兩種方法只是改變了輸出值的數據類型,並無改變表中字段的類型。
create table t7(
birthday datetime
)
insert into t7 values(now());
select birthday,cast(birthday as date), convert(birthday,time) from t7;
13.8 本章實例
1. 生成三個1~100之間的隨機整數
2. 計算PI(圓周率)餘弦值和天然對數值
3. 按以下要求來操做表
a. 建立str_date表。
b. 插入記錄。id字段的值是自動增長的,賦值爲null後系統會自動添加值。dt字段要插入系統當前日期和時間,能夠使用now()函數。
c. 用last_insert_id()函數來查看最後的auto_increment值。
e. 使用upper()函數將小寫字母變成大寫;使用peverse()函數將字符串反向輸出;使用left()函數來得到字符串前端的字符。
f. 使用dayofyear()函數能夠計算dt中的日期是一年中的第幾天;使用dayname()函數來計算星期幾。
g. 使用date_format()函數來爲dt中的日期和時間設定格式。
4. 先加一個名爲'mybookc'的鎖,持續時間爲20秒。而後立刻加一個名爲'mybook2'的鎖,持續時間爲30秒。而後查詢這兩個鎖的狀態。最後解除這兩個鎖。
(1) select round(rand()*100), floor(rand()*100), ceiling(rand()*100);
(2) SELECT pi(),cos(pi()),log(pi());
(3) create table str_date(
id int auto_increment primary key,
info varchar(20),
dt datetime
);
insert into str_date values(null,'china',now());
select last_insert_id();
select info, upper(info), reverse(info), left(info,3) from str_date;
select dt,dayofyear(dt), dayname(dt) from str_date;
select dt, date_format(dt, '%b %D %Y %l:%i%s %p') from str_date;
(4) select get_lock('mbook1',20),get_lock('mybook2',30);
select is_free_lock('mybook1');
select release_lock('mybook1'),release_lock('mybook2');
13.9 上機實踐
(1)向num_test表中插入記錄
(2)在字符串"I love "和字符串"beijing"合併爲同一個字符串。
(3)返回字符串"me"在字符串"You love me.He love me."中第一次出現的位置。
(4)額頭GET_FORMAT(DATE,'EUR')返回的格式來顯示當前日期;用GET_FORMAT(TIME,'USA')返回的格式來顯示當前時間。
(5)查看當前數據庫的版本號,當前數據庫名和當前用戶。
(6)使用字符串"college"來加密字符串"university"。
use test;
create table num_test(
id int auto_increment primary key,
value float
);
insert into num_test values
(null,abs(-8)),
(null,sin(2.4)),
(null,exp(2)),
(null,pow(3,4)),
(null,mod(8,3)),
(null,radians(80));
select last_insert_id();
select concat('I love ', 'beijing');
select locate('me','you love me.He love me.');
select position('me' in 'you love me.He love me.');
select date_format(curdate(),get_format(DATE,'EUR'));
select time_format(curtime(),get_format(time,'EUR'));
select version(), database(), user();
select encode('college','university');
13.10 常見問題及解答
1. 表中birth字段存的出生日期,如何來計算年齡?
答: 年齡是經過當前年份減去出生的年份來計算的。可是brith字段中有年、月、日,這就必須從birth字段中過濾出出生的年份。MySQL中提供了 year()函數用來獲取日期中的年份。如year('2008-08-08')的返回結果是2008。因此,能夠經過year(birth)來獲取出生 的年份。能夠經過year(now())或者year(current_date())來獲取當前的年份。這二者相減就能夠得到年齡了。
2. 如何改變字符串的字符集?
答: 在安裝MySQL時就已經設置了數據庫的字符編碼。字符串的字符集與字符編碼是一個意思。MySQL中能夠經過從新配置字符集來修改字符集。也能夠在 MySQL中安裝路徑下修改my.ini。將default-charset-set的值改變來修改字符集。上面這兩種方式將改變整個數據庫的字符集。如 果只想改變某個字符串的字符集,能夠使用convert(s suing cs)函數。該函數能夠將字符串s的字符集變成cs。
3. 用戶的密碼應該怎麼加密?
答:MySQL 中能夠使用password(str)函數來給密碼加密。這個密碼是不可逆的,即便有人取得了加密後的數據,也不能經過解密來獲取密碼值。系統會將用戶注 冊時輸入的密碼經過password(str)函數來加密。將加密後的密碼存入表中。用戶登陸時,系統會將再次用戶輸入的密碼用 password(str)函數加密,將加密後的數據與表中的數據進行比較。若是相等,說明用戶輸入的密碼是正確的。
14.存儲過程和函數
存 儲過程和函數是在數據庫中定義一些SQL語句的集合,而後直接調用這些存儲過程和函數來執行已經定義好的SQL語句。存儲過程和函數能夠避免開發人員重複 編寫相同的SQL語句。並且,存儲過程和函數是在MySQL服務器中存儲和執行的,能夠減小客戶端和服務器端的數據傳輸。
- 建立存儲過程
- 建立存儲函數
- 變量的使用
- 定義條件和處理程序
- 光標的使用
- 流程控制的使用
- 調用存儲過程和函數
- 查看存儲過程和函數
- 修改存儲過程和函數
- 刪除存儲過程和函數
14.1 建立存儲過程和函數
創 建存儲過程和函數是指將常用的一組SQL語句的組合在一塊兒,並將這些SQL語句看成一個總體存儲在MySQL服務器中,例如,銀行常常須要計算用戶的 利息。不一樣類別的服務的利息是不同的。這就能夠將計算利率的SQL代碼寫成一個存儲過程或者存儲函數。只要調用這個存儲過程或者存儲函數,就能夠將不一樣 類別用戶的利息計算出來。
14.1.1 建立存儲過程
CREATE PROCEDURE sp_name
([proc_parameter[,...]])
[characteristic ...] routine_body
[IN|OUT|INOUT] param_name type
輸入|輸出|輸入輸出 存儲過程參數名稱 存儲過程的參數類型
DELIMITER &&
CREATE PROCEDURE num_from_employee (IN emp_id INT, OUT count_num INT)
READS SQL DATA
BEGIN
SELECT COUNT(*) INTO count_num
FROM employee
WHERE d_id=emp_id;
END
&&
DELIMITER ;
14.1.2 建立存儲函數
MySQL中,建立存儲函數的基本形式以下:
CREATE FUNCTION sp_name([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
delimiter &&
create function name_from_employee (emp_id int)
returns varchar(20)
begin
return (select name from employee where d_id=emp_id);
end
&&
delimiter ;
14.1.3 變量的使用
存儲過程和函數中能夠定義和使用變量。用戶能夠使用DECLARE關鍵字來定義變量。而後能夠爲變量賦值。這些變量的做用範圍是BEGIN...END程序段中。
1 定義變量
2 爲變量賦值
# 定義變量my_sql, 數據類型爲int型,默認值爲10。
DECLARE my_sql INT default 10;
# 變量賦值
set my_sql=30;
select d_id into my_sql from employee where id=2;
14.1.4 定義條件和處理程序
定 義條件和處理程序是事先定義程序執行過程當中可能遇到的問題。而且能夠在處理程序中定義解決這些問題的辦法。這種方式能夠提早預測可能出現的問題,並提出解 決辦法。這樣能夠加強程序處理問題的能力,避免程序異常中止。MySQL中都是經過DECLARE關鍵字來定義條件和處理程序。
1. 定義條件
2. 定義處理程序
DECLARE condition_name CONDITION FOR condition_value
condition_value;
sqlstate [value] sqlstate_value | mysql_error_code
"ERROR 1146(42S02)"這個錯誤,名稱爲can_not_find。能夠用兩種不一樣的方法來定義。
# 方法一:使用sqlstate_value
DECLARE can_not_find CONDITION FOR SQLSTATE '42S02';
# 方法二:使用mysql_error_code
DECLARE can_not_find CONDITION FOR 1146;
# 定義處理程序
DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
handler_type
CONTINUEW|EXIT|UNDO
condition_value
SQLSTATE[VALUE]sqlstate_value|condition_name|SQLWARNING
|NOT FOUND|SQLEXCEPTION |mysql_error_code
# 方法一:捕獲sqlsate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='CAN NOT FIND';
# 方法二:捕獲mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info='CAN NOT FIND';
# 方法三:先定義條件,而後調用
DECLARE can_not_find CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR can_not_find SET @info='CAN NOT FIND';
# 方法四:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';
# 方法五:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info='CAN NOT FIND';
# 方法六:使用SQLEXCEPTION
DECLARE exit handler for sqlexception set @info='ERROR';
14.1.5 光標的使用
查詢語句可能查詢出多條記錄,在存儲過程和存儲函數中使用光標來逐條讀取查詢結果集中的記錄。有些書上將光標稱爲遊標。光標的使用包括聲明光標、打開光標、使用光標和關閉光標。光標必須聲明在處理程序以前,而且聲明在變量和條件以後。
1. 聲明光標
DECLARE cur_employee CURSOR FOR select name, age FROM employee;
2. 打開光標
OPEN cur_employee;
3. 使用光標
FETCH cur_employee INTO emp_name,emp_age;
4. 關閉光標
CLOSE cur_employee;
14.1.6 流程控制的使用
存儲過程和存儲函數中能夠使用流程控制來控制語句的執行。MySQL中能夠使用IF語句、CASE語句、LOOP語句、LEAVE語句、ITERATE語句、REPEAT語句、WHILE語句來進行流程控制。
1. IF語句
IF age>20 then set @count1=@count1+1;
elseif age=20 then @count2=@count2+1;
else @count3=@count3+1;
end if;
if search_conditioin then statement_list
[elseif search_condition] then statement_list]...
[else statement_list]
end if;
2. CASE語句
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE;
case AGE
when 20 then set @count1=@count1+1;
else set @count2=@count2+1;
end case;
3. LOOP語句
[begin_label:]LOOP
statement_list
END LOOP [end_label]
add_num:LOOP
SET @count=@count+1;
end loop add_num;
4. LEAVE語句
add_num:LOOP
SET @count=@count+1;
if @count=100 then
leave add_num; # 結束循環,與brean很像
end loop add_num;
5. ITERATE語句
add_num:LOOP
SET @count=@count+1
if @count=100 then
leave add_num;
else if mod(@count,3)=0 then
iterate add_num;
select * from employee;
end loop add_num;
6. REPEAT語句
[begin_label:]repeat
statement_list
until search_condition
end repeat[end_label];
REPEAT
SET @count=@count+1;
UNTIL @count=100
END REPEAT;
7. WHILE語句
[begin_label:]WHILE search_condition DO
statement_list
END WHILE [end_label]
WHILE @count<100 do="" set="" count="@count+1;" end="" while="" 14="" 2="" sql="" call="" mysql="" execute="" execute="" information_schema="" user_privileges="" 14="" 2="" 1="" mysql="" call="" call="" sp_name="" parameter="" delimiter="" create="" procedure="" num_from_employee="" in="" emp_id="" int="" out="" count_num="" int="" reads="" sql="" data="" begin="" select="" count="" into="" count_num="" from="" employee="" where="" d_id="emp_id;" end="" delimiter="" call="" num_from_employee="" 1002="" n="" select="" n="" 14="" 2="" 2="" mysql="" mysql="" mysql="" mysql="" show="" variables="" like="" func="" set="" global="" log_bin_trust_function_creators="TRUE;" delimiter="" create="" function="" name_from_employee="" emp_id="" int="" returns="" varchar="" 20="" begin="" return="" select="" name="" from="" employee="" where="" id="emp_id);" end="" delimiter="" select="" name_from_employee="" 3="" 14="" 3="" show="" status="" show="" create="" information_schema="" routines="" 14="" 3="" 1="" show="" status="" show="" procedure="" functioin="" status="" like="" pattern="" show="" procedure="" status="" like="" num_from_employee="" g="" 14="" 3="" 2="" show="" create="" show="" create="" procedure="" function="" sp_name="" show="" create="" function="" num_from_employee="" 14="" 3="" 3="" information_schema="" routines="" information_schema="" routines="" select="" from="" information_schema="" routines="" where="" routine_name="sp_name" routine_name="" sp_name="" select="" from="" informatin_schema="" routines="" g="" 14="" 4="" mysql="" alter="" procedure="" alter="" function="" alter="" procedure="" function="" sp_name="" characterstic="" characteristic:="" contains="" sql="" no="" sql="" reads="" sql="" data="" modifies="" sql="" data="" sql="" security="" definer="" invoker="" comment="" string="" contains="" sql:="" sql="" no="" sql:="" sql="" reads="" sql="" data="" :="" modifies="" sql="" data:="" definer:="" invoker:="" num_from_employee="" modifies="" sql="" data="" alter="" procedure="" num_from_employee="" modifies="" sql="" data="" sql="" security="" invoker="" select="" specific_name="" sql_data_access="" security_type="" from="" information_schema="" routines="" where="" routine_name="num_from_employee" alter="" function="" name_from_employee="" reads="" sql="" data="" comment="" find_name="" select="" specific_name="" sql_data_access="" routine_comment="" from="" information_schema="" routines="" where="" routine_name="name_from_employee" 14="" 5="" mysql="" drop="" procedure="" drop="" function="" drop="" procedure="" function="" sp_name="" drop="" procedure="" num_from_employee="" drop="" function="" name_from_employee="" select="" from="" information_schema="" routines="" 14="" 6="" food="" food_price_count="" food_price_count="" price_info1="" price_info2="" count="" food="" price_info1="" price_info2="" count="" use="" example="" delimiter="" create="" procedure="" food_price_count="" in="" price_info1="" float="" in="" price_info2="" float="" out="" count="" int="" reads="" sql="" data="" begin="" temp="" declare="declare" temp="" float="" food="" price="" declare="declare" match_price="" cursor="" for="" select="" price="" from="" food="" declare="declare" exit="" handler="" for="" not="" found="" close="" match_price="" sum="" 0="" set="" sum="0;" count="" select="" count="" into="" count="" from="" food="" where="" price="">price_info1 and price<price_info2 open="" match_price="" repeat="" temp="" fetch="" match_price="" into="" temp="" temp="" price_info1="" price_info2="" if="" temp="">price_info1 and temp<price_info2 then="" set="" sum="@sum+temp;" end="" if="" 0="" until="" 0="" end="" repeat="" close="" match_price="" end="" delimiter="" drop="" procedure="" food_price_count="" 14="" 7="" teacher="" teacher_info1="" teacher_info2="" 1="" teacher_info1="" 2="" teacher_info2="" 1="" teacher_info1="" 2="" teacher_info2="" insert="" into="" teacher="" values="" null="" 1001="" 1="" 1984-11-08="" 00:00:00="" null="" 1002="" 0="" 1970-01-21="" 00:00:00="" null="" 1003="" 1="" 1976-10-30="" 00:00:00="" null="" 1004="" 1="" 1980-06-05="" 00:00:00="" delimiter="" create="" procedure="" teacher_info1="" in="" teacher_id="" int="" in="" type="" int="" out="" info="" varchar="" 20="" charset="" utf8="" reads="" sql="" data="" begin="" case="" type="" when="" 1="" then="" select="" name="" into="" info="" from="" teacher="" where="" id="teacher_id;" when="" 2="" then="" select="" year="" now="" -year="" birthday="" into="" info="" from="" teacher="" where="" id="teacher_id;" else="" select="" error="" into="" info="" end="" case="" end="" delimiter="" call="" teacher_info1="" 3="" 1="" info="" select="" info="" drop="" procedure="" teacher_info1="" delimiter="" create="" function="" teacher_info2="" teacher_id="" int="" type="" int="" returns="" varchar="" 20="" reads="" sql="" data="" begin="" declare="declare" temp="" varchar="" 20="" charset="" utf8="" set="" e="Error" if="" type="1" then="" select="" name="" into="" temp="" from="" teacher="" where="" id="teacher_id;" elseif="" type="2" then="" select="" year="" now="" -year="" birthday="" into="" temp="" from="" teacher="" where="" id="teacher_id;" else="" select="" e="" into="" temp="" end="" if="" return="" temp="" end="" delimiter="" select="" teacher_info2="" 3="" 1="" drop="" function="" teacher_info2="" select="" from="" information_schema="" routines="" g="" show="" variables="" like="" character="" set="" character_set_server="utf8;" 14="" 8="" 1="" sql="" call="" sql="" call="" 2="" in="" out="" inout="" out="" inout="" out="" inout="" return="" return="" 3="" mysql="" sql="" return="" mysql="" mysql="" 15="" mysql="" mysql="" root="" root="" root="" -="" -="" mysql="" -="" -="" root="" -="" 15="" 1="" mysql="" mysql="" mysql="" mysql="" user="" db="" host="" tables_priv="" columns_priv="" proc_priv="" 15="" 1="" 1="" user="" user="" mysql="" desc="" user="" user="" 39="" 1="" 2="" 3="" 4="" host="" user="" password="" mysql="" select_priv="" insert_priv="" update_priv="" delete_priv="" create_priv="" drop_priv="" reload_priv="" shutdown_priv="" process_priv="" file_priv="" grant_priv="" references_priv="" index_priv="" alter_priv="" show_db_priv="" super_priv="" create_tmp_table_priv="" lock_tables_priv="" execute_priv="" repl_slave_priv="" repl_client_priv="" create_view_priv="" show_view_priv="" create_routine_priv="" alter_routine_priv="" create_user_priv="" event_priv="" trigger_priv="" ss1="" ss1_type="" ss1_cipher="" x509_issuer="" x509_subject="" max_questions="" max_updates="" max_connections="" max_user_connections="" 0="" 15="" 1="" 2="" db="" host="" db="" host="" mysql="" db="" db="" host="" desc="" 1="" 2="" db="" host="" db="" user="" select_priv="" insert_priv="" update_priv="" host="" host="" db="" db="" host="" host="" host="" host="" db="" host="" db="" 15="" 1="" 3="" tables_priv="" columns_priv="" tables_priv="" columns_priv="" tables_priv="" 8="" host="" db="" user="" table_name="" table_priv="" column_priv="" timestamp="" grantor="" table_priv="" select="" insert="" update="" delete="" create="" drop="" grant="" references="" index="" alter="" column_priv="" select="" insert="" update="" references="" timestamp="" grantor="" 15="" 1="" 4="" procs_priv="" procs_priv="" desc="" procs_priv="" procs_priv="" 8="" host="" db="" user="" routine_name="" routine_type="" proc_priv="" timestamp="" grantor="" routine_name="" routine_type="" function="" procedure="" function="" procedure="" proc_price="" 3="" execute="" alter="" routine="" grant="" timestamp="" grantor="" grantor:="" excute:="" alter="" routine:="" grant:="" 15="" 2="" mysql="" mysql="" mysql="" 15="" 2="" 1="" mysql="" mysql="" mysql="" mysql="" mysql="" mysql="" mysql="" -h="" host="" name="" hostip="" -p="" port="" -u="" username="" -p="" databasename="" -e="" sql="" mysql="" -h="" 127="" 0="" 0="" 1="" -u="" root="" -p="" test="" mysql="" -h="" localhost="" -u="" root="" -p="" 3306="" -p="" mysql="" -e="" desc="" use="" mysql="" -h="" locahost="" -u="" root="" -pphptest="" mysql="" q="" quit="" exit="" 15="" 2="" 2="" mysql="" create="" user="" mysql="" user="" grant="" 1="" create="" user="" create="" user="" username="" identified="" by="" password="" password="" username="" identified="" by="" password="" password="" create="" user="" test1="" locahost="" identified="" by="" test1="" 2="" insert="" insert="" into="" mysql="" user="" host="" user="" password="" ssl_cipher="" x509_issuer="" x509_subject="" values="" localhost="" test2="" password="" test2="" flush="" privileges="" 3="" grant="" grant="" priv_type="" on="" database="" table="" to="" user="" identified="" by="" password="" password="" user="" identified="" by="" password="" password="" grant="" select="" on="" to="" test3="" localhost="" identified="" by="" test3="" 15="" 2="" 3="" drop="" user="" mysql="" user="" 1="" drop="" user="" drop="" user="" test3="" localhost="" 2="" delete="" delete="" from="" mysql="" user="" where="" user="" root="" flush="" privileges="" 15="" 2="" 4="" root="" root="" root="" root="" 1="" mysqladmin="" root="" 2="" mysql="" user="" 3="" set="" root="" mysqladmin="" -u="" username="" -p="" password="" new_password="" mysqladmin="" -u="" root="" -p="" password="" root="" enter="" password:="" update="" mysql="" user="" set="" password="PASSWORD('ROOT')" where="" user="root" and="" host="localhost" fluash="" priviliges="" set="" password="password('new_password');" flush="" privileges="" 15="" 2="" 5="" root="" 1="" set="" 2="" mysql="" user="" 3="" grant="" set="" password="" for="" username="" hostname="" password="" new_password="" set="" password="" for="" test="" localhost="" password="" test_new="" update="" mysql="" user="" set="" password="password('new_password')" where="" user="Username" and="" host="hostname" update="" mysql="" user="" set="" password="PASSWORD('test')" where="" user="test" and="" host="localhost" flush="" privileges="" grant="" pri_type="" on="" database="" table="" to="" user="" identified="" by="" password="" password="" grant="" select="" on="" to="" test="" localhost="" identified="" by="" test_new="" 15="" 2="" 6="" set="" password="PASSWORD('new_password');" mysqladmin="" -u="" test="" -ptest="" password="" test_new="" 15="" 2="" 7="" root="" root="" root="" root="" 1="" -skip-grant-tables="" mysql="" 2="" root="" 3="" windows:="" mysqld="" --skip-grant-tables="" mysqld-nt="" --skip-gant-tables="" net="" start="" mysql="" --skip-grant-tables="" linux:="" mysqld_safe="" --skip-grant-tables="" user="mysql" etc="" init="" d="" mysql="" etc="" init="" d="" mysql="" start="" --mysqld="" --skip-grant-tables="" mysql="" -u="" root="" update="" mysql="" user="" set="" password="PASSWORD('root')" where="" user="root" and="" host="localhost" flush="" privileges="" 15="" 3="" mysql="" 15="" 3="" 1="" mysql="" mysql="" mysql="" user="" user="" create="" create_priv="" drop="" drop_priv="" grant="" option="" grant_priv="" references="" references_priv="" alter="" alter_priv="" delete="" delete_priv="" index="" index_priv="" insert="" insert_priv="" select="" select_priv="" update="" update_priv="" create="" view="" create_view_priv="" show="" view="" show_view_priv="" alter="" routine="" alter_routine_priv="" create="" routine="" create_routine_priv="" execute="" execute_priv="" file="" file_priv="" create="" temporary="" table="" create_tm_table_priv="" lock="" tables="" lock_tables_priv="" create="" user="" create_user_priv="" process="" process_priv="" reload="" reload_priv="" replication="" client="" repl_client_priv="" replocation="" slave="" repl_slave_priv="" show="" database="" show_db_priv="" shutdown="" shutdown_priv="" super="" super_priv="" 15="" 3="" 2="" mysql="" grant="" mysql="" grant="" grant="" grant="" priv_type="" column_list="" on="" database="" table="" to="" user="" identified="" by="" password="" password="" user="" identified="" by="" password="" password="" with="" with_option="" with_option="" grant="" select="" update="" on="" to="" test5="" localhost="" identified="" by="" test5="" with="" grant="" option="" width="" grant="" option="" select="" host="" user="" password="" select_priv="" update_priv="" grant_priv="" from="" mysql="" user="" where="" user="test5" g="" grant="" select="" on="" mysql="" to="" test3="" localhost="" select="" host="" user="" password="" select_priv="" from="" mysql="" user="" where="" user="test3" g="" 15="" 3="" 3="" revoke="" pri_type="" column_list="" on="" database="" table="" from="" user="" user="" revoke="" all="" privileges="" grant="" option="" from="" user="" user="" revoke="" update="" on="" from="" test5="" localhost="" revoke="" all="" privileges="" grant="" option="" from="" test5="" localhost="" 15="" 3="" 4="" select="" from="" mysql="" user="" show="" greants="" show="" grants="" for="" root="" localhost="" 15="" 4="" aric="" abcdef="" test="" 1="" root="" aaabbb="" 2="" aric="" 3="" aric="" 4="" aric="" grant="" select="" update="" delete="" on="" test="" to="" aric="" localhost="" identified="" by="" abcdef="" set="" password="" for="" aric="" localhost="" select="" from="" mysql="" user="" where="" user="aric" and="" host="localhost" revoke="" delete="" on="" test="" from="" aric="" localhost="" drop="" user="" aric="" localhost="" 15="" 5="" 1="" root="" exam1="" 123456="" select="" create="" drop="" super="" grant="" 2="" exam2="" 3="" exam2="" 686868="" 4="" exam1="" exam2="" create="" drop="" 5="" root="" exam1="" exam2="" 1="" grant="" select="" create="" drop="" super="" on="" to="" exam1="" localhost="" identified="" by="" 123456="" with="" grant="" option="" 2="" create="" user="" exam2="" localhost="" 3="" mysql="" -h="" localhost="" -u="" exam2="" set="" password="password('686868';" 4="" mysql="" -h="" localhost="" -u="" exam1="" -p="" grant="" create="" drop="" on="" to="" exam2="" localhost="" 5="" revoke="" all="" privileges="" grant="" option="" from="" exam1="" localhost="" exam2="" localhost="" 15="" 6="" 1="" mysqladmin="" mysqladmin="" root="" mysqladmin="" cant="" t="" trun="" off="" logging="" error:="" access="" denied="" you="" need="" the="" super="" privilege="" for="" this="" operation="" super="" mysqladmin="" super="" mysql="" set="" password="password('新密碼')語句來修改密碼。也能夠聯繫root用戶,請求root用戶爲其修改密碼。" 2="" mysql="" mysql="" mysql="" user="" host="" host="" localhost="" mysql="" mysql="" host="" mysql="" mysql="" mysql="" host="" grant="" grant="" host="" update="" mysql="" user="" host="" 16="" -="" -="" -="" -="" 16="" 1="" 16="" 1="" 1="" mysqldump="" mysqldump="" mysqldump="" create="" inset="" create="" insert="" create="" insert="" 1="" 2="" 3="" mysqldump="" -u="" root="" -p="" root="" dbname="" table="" table="" backupname="" sql="" mysqldump="" -u="" root="" -p="" test="" student1="" c:="" backup="" sql="" mysqldump="" -u="" username="" -p="" --databases="" dbname1="" dbname2="" backupname="" sql="" mysqldump="" -u="" root="" -p="" --databases="" test="" mysql="" c:="" backup2="" sql="" mysqldump="" -u="" root="" -p="" --all-databases="" c:="" backup3="" sql="" 16="" 1="" 2="" mysql="" mysql="" mysql="" innodb="" myisam="" mysql="" 16="" 1="" 3="" mysqlhotcopy="" mysql="" mysqlhotcopy="" mysqlhotcopy="" mysqldump="" mysqlhotcopy="" perl="" linux="" mysqlhotcopy="" lock="" tables="" flush="" tables="" cp="" flush="" tables="" mysqlhotcopy="" root="" localhost="" mysqlhotcopy="" option="" dbname1="" dbnam2="" backupdir="" 16="" 2="" 16="" 2="" 1="" mysql="" mysqldump="" sql="" mysql="" create="" insert="" mysql="" create="" insert="" create="" insert="" mysql="" -u="" root="" -p="" daname="" backup="" sql="" mysql="" -u="" root="" -p="" c:="" all="" sql="" 16="" 2="" 2="" mysql="" mysql="" mysql="" mysql="" myisam="" innodb="" innodb="" windows="" mysql="" c:="" mysql="" data="" c:="" documents="" and="" settings="" all="" users="" applicatin="" data="" mysql="" mysql="" server="" 5="" 1="" data="" c:="" program="" files="" mysql="" mysql="" server="" 5="" 1="" data="" linux="" var="" lib="" mysql="" usr="" local="" mysql="" data="" usr="" local="" mysql="" var="" 16="" 3="" mysql="" mysql="" mysql="" 16="" 3="" 1="" mysql="" mysql="" mysql="" mysql="" mysql="" myisam="" 16="" 3="" 2="" mysql="" mysql="" mysql="" 4="" 0="" mysql="" 5="" 0="" 4="" 0="" mysql="" 5="" 0="" mysql="" mysql="" mysql="" mysql="" myisam="" mysqlhotcopy="" innodb="" mysqldump="" mysql="" mysql="" mysql="" mysql="" mysql="" mysql="" mysqldump="" 16="" 3="" 3="" mysql="" mysql="" oracle="" mysql="" mysql="" oracle="" mysql="" mysqldump="" sql="" sql="" sql="" sql="" server="" t-sql="" t-sql="" sql="" sql="" server="" mysql="" sql="" 16="" 4="" mysql="" xml="" html="" mysql="" 16="" 4="" 1="" select="" into="" outfile="" mysql="" select="" into="" outflile="" select="" from="" table="" where="" into="" outfile="" option="" fileds="" terminated="" by="" fields="" enclosed="" by="" fields="" optionally="" enclosed="" by="" fields="" escaped="" by="" lines="" starting="" by="" lines="" teminated="" by="" select="" from="" example2="" employee="" into="" outfile="" c:="" employee="" txt="" fields="" terminated="" by="" optionally="" enclosed="" by="" lines="" starting="" by="">'
TERMINATED BY '\r\n';
16.4.2 用mysqldump命令導出文本文件
mysqldump命令能夠備份數據庫中的數據。可是,備份時是在備份文件中保存了CREATE語句和INSERT語句。不只如此,mysqldump命令還能夠導出文本文件。其基本的語法形式以下:
mysqldump -u root -pPassword -T 目標目錄 dbname table [option];
--FILEDS-TERMINATED-BY='字符串' #設置每一個字段的分隔符
--FIELDS-ENCLOSED-BY='字符' #設置字段的值
--FIELDS-OPTIONALLY-ENCLOSED-BY='字符' #字符型的符號
--FIELDS-ESCAPED-BY='字符' # 轉義字符
--LINES-TEMINATED-BY='字符串' # 每行結尾字符
mysqldump -u root -p -T c:/test student
"--fields-terminated-by=""--fields-optionally-enclosed-by=""
mysqldump -u root -p --xml dbname table > C:/name.xml
16.4.3 用myslq命令導出文本文件
mysql命令能夠用來登陸MySQL服務器,也能夠用來還原備份文件。同時,mysql命令也能夠導出文本文件。其基本語法形式以下:
mysql -u root -p -e 'select語句' dbName > c:/name.txt
其中,-e選項就能夠執行SQL語句; 'SELECT語句'用來查詢記錄;'C:/name.txt'表示導出文件的路徑。
mysql -u root -p -e 'SELECT * from student' dbname > c:/student.txt
16.4.4 用LOAD DATA INFILE方式導入文本文件
MySQL中,能夠使用LOAD DATA INFILE命令文本文件導入到MySQL數據庫中。其基本語法形式以下:
LOAD DATA [LOCAL] INFILE file INTO TABLE table [OPTION];
# 數據文件
LOAD DATA INFLIE 'c:/student.txt' into table student
fields terminated by ',' optionally enclosed by '"';
16.4.5 用mysqlimport命令導入文本文件
MySQL中,能夠使用mysqlimport命令將文本文件導入到MySQL數據庫中。其基本語法形式以下:
mysqlimport -u root -p [--local] dbname file [option];
mysqlimport -u root -p test c:/student.txt
"--fields-terminated-by=, ""--fields-optionally-by=""
16.5 本章實例
(1)使用mysqldump命令來備份score表。備份文件存儲在D:\backup路徑下。
(2)使用mysql命令來還原score表。
(3)使用SELECT...INOT OUTFILE來導出score表中的記錄。記錄存儲到D:\backup/score.txt中。
(4)使用mysqldump命令將score表的記錄導出到XML文件中。這個XML文件存儲在D:\backup中。
1:備份
mysqldump -u root -p test score > C:\backup\score.sql
2:還原
mysql -u root -p test < C:\backup\score.sql
USE test;
DELETE FROM score;
SELECT * FROM score;
mysql -u root -p test < C:\backup\score.sql
mysql -u root -p -e "SELECT * FROM score" test
3:
SELECT * FROM test.score INTO OUTFILE 'C:/backup/score.txt'
FIELDS TERMINATED BY '\,' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\r\n';
4:
mysqldump -u root -p --xml test score > C:\backup/score.xml
16.6 上機實踐
(1)test 數據庫中建立department表。使用mysqldump命令將department表的記錄導出到C:\目錄下。
(2)刪除department表中的全部記錄。而後使用LOAD DATA INFILE語句將department.txt中的記錄加載到department表中。
(3)從新刪除department表的全部記錄,而後使用mysqlimport命令將department.txt中的記錄加載到department表中。
(4)使用mysql命令將department.txt中的記錄導出成HTML文件。
1:
mysqldump -u root -p -T C:\ test department "--fields-terminated-by=," "--fields-optionally-enclosed-by=""
2:
load data infile 'C:/department.txt' INTO TABLE department FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"';
3:
mysqlimport -u root -p test c:\department.txt "--fields-terminated-by=," "--fields-optionally-enclosed-by=""
4:
mysql -u root -p --html -e "SELECT * FROM department" test > C:\department.html
16.7 常見問題及解答
1. 如何選擇備份數據庫的方法?
答: 根據數據庫的存儲引擎的類型不一樣,備份表的方法也不同。對於MyISAM類型的表,能夠直接複製MySQL數據文件夾或者使用mysqlhotcopy 命令快速備份。複製MySQL數據庫文件夾時須要將MySQL服務中止,不然可能會出現異常。而mysqlhotcopy命令會則不須要中止MySQL服 務。mysqldump命令是最安全的備份方法。它既適合MyISAM類型的表,也適用於InnoDB類型的表。
2. 如何升級MySQL數據庫?
答:
(1)先使用mysqldump命令備份MySQL數據庫中的數據。這樣作的目的是爲了不誤操做引發MySQL數據庫中的數據丟失。
(2)中止MySQL服務。能夠直接停止MySQL服務的進程。可是最好仍是用安全的方法中止MySQL服務。這樣能夠避免緩存中的數據丟失。
(3)卸載舊版本的MySQL數據庫。一般狀況下,卸載MySQL數據庫軟件時,系統繼續保留MySQL數據庫中數據文件。
(4)安裝新版本的MySQL數據庫,並進行相應的配置。
(5)啓動MySQL服務,登陸MySQL數據庫查詢數據是否完整。若是數據不完整,使用以前備份的數據進行恢復。
17.MySQL日誌
MySQL日誌是記錄MySQL數據庫的平常操做和錯誤信息的文件。MySQL中,日誌能夠分爲二進制日誌、錯誤日誌、通用查詢日誌和慢查詢日誌。分析這些日誌文件,能夠了解MySQL數據庫的運行狀況、平常操做、錯誤信息和哪些地方須要進行優化。
- 日誌定義、做用和優缺點
- 二進制日誌
- 錯誤日誌
- 通用查詢日誌
- 慢查詢日誌
- 日誌管理
17.1 日誌簡介
日誌是MySQL數據庫的重要組成部分。日誌文件中記錄着MySQL數據庫運行期間發生的變化。當數據庫遭到意外的損害時,能夠經過日誌文件來查詢出錯緣由,而且能夠經過日誌文件進行數據恢復。
MySQL日誌能夠分爲四種,分別是二進制日誌、錯誤日誌、通用查詢日誌和慢查詢日誌。
17.2 二進制日誌
二進制日誌也叫做變量日誌(update log),主要用於記錄數據庫的變化狀況。經過二進制日誌能夠查詢MySQL數據庫中進行了哪些改變。
17.2.1 啓動和設置二進制日誌
默認狀況下,二進制日誌功能是關閉的。經過my.cnf或者my.ini文件的log-bin選項能夠開戶二進制日誌。將log-bin選項加入到my.cnf或者my.ini文件到[mysqld]組中,形式以下:
# my.cnf(Linux操做系統下) 或者my.ini(Windows操做系統下)
[mysqld]
log-bin[=DIR\[filename]]
log-bin=c:/log/mylog
17.2.2 查看二進制日誌
使用二進制格式能夠存儲更多的信息,而且能夠使寫入二進制日誌的效率更高。可是,不能直接打開並查看二進制日誌。若是須要查看二進制日誌,必須使用mysqlbinlog命令。
mysqlbinlog filename.number
mysqlbinlog mylog.000001
17.2.3 刪除二進制日誌
二進制日誌會記錄大量的信息。若是很長時間不清理二進制日誌,將會浪費不少的磁盤空間。刪除二進制日誌的方法不少,本小節將爲讀者詳細介紹如何刪除二進制日誌。
1. 刪除全部二進制日誌: reset master;
2. 根據編號來刪除二進制日誌: purge master logs to 'filename.number'
purge master logs to 'mylog.00001';
3. 根據建立時間來刪除二進制日誌
PURGE MASTER LOGS TO 'yyyy-mm-dd hh:mm:ss';
purge master logs to '2009-12-20 15:00:00';
17.2.4 使用二進制日誌還原數據庫
二進制日誌記錄了用記對數據庫中數據的改變。如INSERT語句、UPDATE語句、CREATE語句等都會記錄到二進制日誌中。一旦數據庫遭到破壞,能夠使用二進制日誌還原數據庫。
若是數據庫遭到意外損壞,首先應該使用最近的備份文件來還原數據庫。備份以後,數據庫可能進行了一些更新。這能夠使用二進制日誌來還原。由於二進制日誌存儲了更新數據庫的語句,如UPDATE語句、INSERT語句等。二進制日誌還原數據庫的命令以下:
mysqlbinlog filename.number | mysql -u root -p
drop table employee;
17.2.5 暫時中止二進制日誌功能
在配置文件中設置了log-bin選項之後,MySQL服務器將會一直開啓二進制日誌功能。刪除該選項後就能夠中止二進制日誌功能。若是須要再次啓動這個功能,又須要從新添加log-bin選項。MySQL中提供了暫時中止二進制日誌功能的語句。
若是用戶不但願本身執行的某些SQL語句記錄在二進制日誌中,那麼須要在執行這些SQL語句以前暫停二進制日誌功能。用戶能夠使用SET語句來暫停二進制日誌功能,SET語句的代碼以下:
SET SQL_LOG_BIN=0;
17.3 錯誤日誌
錯誤日誌是MySQL數據庫中最經常使用的一種日誌。錯誤日誌主要用來記錄MySQL服務的開戶、關閉和錯誤信息。
17.3.1 啓動和設置錯誤日誌
在 MySQL數據庫中,錯誤日誌功能是默認開啓的。並且,錯誤日誌沒法被禁止。默認狀況下,錯誤日誌存儲在MySQL數據庫的數據文件夾下。錯誤日誌文件通 常的名稱爲hostname.err。其中,hostname表示MySQL服務器的主機名。錯誤日誌的存儲位置能夠經過log-error選項來設置。 將log-error選項加入到my.ini或者my.cnf文件的[mysqld]組中,形式以下:
# my.cnf (Linux操做系統下)或者my.ini(Windows操做系統下)
[mysqld]
log-error=DIR/[filename]
17.3.2 查看錯誤日誌
錯誤日誌中記錄着開啓和關閉MySQL服務的時間,以及服務運行過程當中出現哪些異常等信息。若是MySQL服務出現異常,能夠到錯誤日誌中查找緣由。
錯誤日誌是以文本文件形式存儲的,能夠直接使用普通文件工具就能夠查看。Windows操做系統能夠使用文本文件查看器查看。Linux操做系統下,能夠使用vi工具或者使用gedit工具來查看。
17.3.3 刪除錯誤日誌
數據庫管理員能夠刪除很長時間之間的錯誤日誌,以保證MySQL服務器上的硬盤空間。MySQL數據庫中,能夠使用mysqladmin命令來開啓新的錯誤日誌。mysqladmin命令的語法以下:
mysqladmin -u root -p flush-logs
執行該命令後,數據庫系統會自動建立一個新的錯誤日誌。舊的錯誤日誌仍然保留着,只是已經改名爲filename.err-old。
17.4 通用查詢日誌
通用查詢日誌用來記錄用戶的全部操做,包括啓動和關閉MySQL服務、更新語句、查詢語句等。
17.4.1 啓動和設置通用查詢日誌
默認狀況下,通用查詢日誌功能是關閉的。經過my.cnf或者my.ini文件的log選項能夠開啓通用查詢日誌。將log選項加入到my.cnf或者my.ini文件的[mysqld]組中,形式以下:
# my.cnf(Linux操做系統下)或者my.ini(Windows操做系統下)
[mysqld]
log[=DIR\[filename]]
17.4.2 查看通用查詢日誌
用戶的全部操做都會記錄到通用查詢日誌中。若是但願瞭解某個用戶最近的操做,能夠查看通用查詢日誌。通用查詢日誌是以文本文件的形式存儲的。Windows操做系統能夠使用文本文件查看器查看。Linux操做系統下,能夠使用vi工具或者使用gedit工具來查看。
17.4.3 刪除通用查詢日誌
通用查詢日誌會記錄用戶的全部操做。若是數據庫的使用很是頻繁,那麼通用查詢日誌將會佔用很是大的磁盤空間。數據庫管理員能夠刪除很長時間之間的通用查詢日誌,以保證MySQL服務器上的磁盤空間。
MySQL數據庫中,也能夠使用mysqladmin命令來開啓新的通用查詢日誌。新的通用查詢日誌會直接覆蓋舊的查詢日誌,不須要再手動刪除了。mysqladmin命令的語法以下:
mysqladmin -u rot -p flush-logs
17.5 慢查詢日誌
慢查詢日誌用來記錄執行時間超過指定時間的查詢語句。經過慢查詢日誌,能夠查找出哪些查詢語句的執行效率很低,以便進行優化。
17.5.1 啓動和設置慢查詢日誌
默 認狀況下,慢查詢日誌功能是關閉的。經過my.cnf或者my.ini文件的log-show-queries選項能夠開啓慢查詢日誌。經過 long_query_time選項來設置時間值,時間以秒爲單位。若是查詢時間超過了這個時間值,這個查詢語句將被記錄到慢查詢日誌。將log- show-queries選項和long_query_time選項加入到my.cnf或者my.ini文件的[mysqld]組中,形式以下:
# my.cnf(Linux操做系統下)或者my.ini(Windows操做系統下)
[mysqld]
log-show-queries[=DIR\[filename]
long_query_time=n
17.5.2 查看通用查詢日誌
執行時間超過指定時間的查詢語句會被記錄到查詢日誌中。若是用戶但願查詢哪些查詢的執行效率低,能夠從慢查詢日誌中得到想要的信息。慢查詢日誌也是以文本文件的形式存儲的。能夠使用普通的文本文件查看工具來查看。
select benchmark(200000000,1*2);
暫停服務以後再查看慢查詢日誌
17.5.3 刪除通用查詢日誌
慢查詢日誌的刪除方法與通用查詢日誌的刪除方法是同樣的。能夠使用mysqladmin命令來刪除。也能夠使用手工方式來刪除。
mysqladmin -u root -p flush-logs
執 行該命令後,命令行會提示輸入密碼。輸入正確密碼後,將執行刪除操做。新的慢查詢日誌會直接覆蓋舊的查詢日誌,不須要再手動刪除了。數據庫管理員也能夠手 工刪除慢查詢日誌。刪除以後須要從新啓動MySQL服務。重啓以後就會生成新的慢查詢日誌。若是但願備份舊的慢查詢日誌文件,能夠將舊的日誌文件更名。然 後重啓MySQL服務。
17.6 本章實例
(1)啓動二進制日誌功能,而且將二進制日誌存儲到c:\目錄下。二進制日誌文件命令爲binlog。
my.ini或my.cnf中設置
log-bin=C:\binlog
重啓服務
(2)啓動服務後,查看二進制日誌。
mysqlbinglog c:\binlog.000001
(3)而後向test數據庫下的score表中插入兩條記錄。
user test;
insert into score values(null,901, '計算機',98);
insert into score values(null,901, '語文',80);
(4)暫停二進制日誌功能,而後再次刪除score表中的全部記錄。
set sql_log_bin=0;
select * from score;
(5)從新開啓二進制日誌功能。
set sql_log_bin=1;
(6)使用二進制日誌來恢復score表。
mysqllogbin c:\binlog.0000001 | mysql -u root -p
(7)刪除二進制日誌。
reset master;
原來二進制日誌恢復爲新的日誌
17.7 上機實踐
(1)將錯誤日誌的存儲位置設置爲C:\LOG目錄下。
(2)開啓通用查詢日誌,並設置該日誌存儲在C:\LOG目錄下。
(3)開啓慢查詢日誌,並設置該日誌存儲在C:\LOG目錄下。設置時間值爲5秒。
(4)查看錯誤日誌、通用查詢日誌和慢查詢日誌。
(5)刪除錯誤日誌。
(6)刪除通用查詢日誌和慢查詢日誌。
1:
log-error=C:/LOG/
2:
log=C:/LOG/
3:
log-slow-queries=C:/LOG/
long_query_time=5
4:
從新啓動服務
C:/log目錄下有錯誤日誌、通用查詢日誌和慢查詢日誌。
5:6:
mysqladmin -u root -p flush-logs
17.8 常見問題及解答
1. 平時應該開啓什麼日誌?
2. 如何使用二進制日誌?
18.性能優化
性能優化是經過某些有效的方法提升MySQL數據庫的性能。性能優化的目的是爲了使MySQL數據庫運行速度更快、佔用的磁盤空間更小。性能優化包括不少方面,例如優化查詢速度、優化更新速度、優化MySQL服務器等。
- 性能優化的介紹
- 優化查詢
- 優化數據庫結構
- 優化MySQL服務器
18.1 優化簡介
優化MySQL數據庫是數據庫管理員的必備技能。經過不一樣的優化方式達到提升MySQL數據庫性能的目的。
MySQL 數據庫的用戶和數據很是少的時候,很難判斷一個MySQL數據庫的性能的好壞。只有當長時間運行,而且有大量用戶進行頻繁操做時,MySQL數據庫的性能 就會體現出來了。例如,一個天天有幾百萬用戶同時在線的大型網站的數據庫性能的優劣就很明顯。這麼多用戶在線的鏈接MySQL數據庫,而且進行查詢、插 入、更新的操做。若是MySQL數據庫的性能不好,極可能沒法承受如此多用戶同時操做。試想用戶查詢一條記錄須要花費很長時間,用戶很難會喜歡這個網站。
SHOW STATUS LIKE 'value';
show status like 'connections';
show status like 'Com_select';
18.2 優化查詢
18.2.1 分析查詢語句
經過對查詢語句的分析,能夠了解查詢語句的執行狀況。MySQL中,能夠使用explain語句和describe語句來分析查詢語句。
explain select語句;
經過explain關鍵字能夠分析後面的select語句的執行狀況。而且可以分析出所查詢的表的一些內容。
explain select * from mysql.user;
describe select * from mysql.user;
id: # select語句的編號
select_type: # select語句類型 simple(不包括鏈接查詢和子查詢)
table: student # 表
type: # 鏈接的類型
possible_keys:
key:
key_len:
ref:
rows:
Extra:
18.2.2 索引對查詢速度的影響
索引能夠快速的定位表中的某條記錄。使用索引能夠提升數據庫查詢的速度,從而提升數據庫的性能。
若是查詢時不使用索引,查詢語句將查詢表中的全部字段。這樣查詢的速度會很慢。若是使用索引進行查詢,查詢語句只查詢索引字段。這樣能夠減小查詢的記錄數,達到提升查詢速度的目的。
explain select * from student where name="張三" \G
create index idx_name on student(name);
explain select * from student where name="張三" \G
18.2.3 使用索引查詢
索引能夠提升查詢的速度。可是有些時間即便查詢時使用的是索引,但索引並無起做用。
1. 查詢語句中使用LIKE關鍵字
explain select * from student where name like '%四' \G
explain select * from student where name like '李%' \G
使用like關鍵字的時候索引字段的搜索必須開頭必須有值開始
2. 查詢語句中使用多列索引
使用第一個索引字段的時候纔會起做用
create index idx_birth_depart on student(birth,department);
explain select * from student where birth > 1990;
explain select * from student where department like '中文%';
3. 查詢語句中使用OR關鍵字
兩個字段都有索引的時候索引查詢,其中一個字段沒有索引時不會使用索引查詢。
explain select * from student where name="張三" or gender="女" \G
explain select * from student where name="張三" or id=905 \G
18.2.4 優化子查詢
很 多查詢中須要使用子查詢。子查詢能夠使查詢語句很靈活,但子查詢的執行效率不高。子查詢時,MySQL須要爲內層查詢語句的查詢結果創建一個臨時表。而後 外層查詢語句再臨時表中查詢記錄。查詢完畢後,MySQL須要撤銷這些臨時表。所以,子查詢的速度會受到必定的影響。若是查詢的數據量比較大,這種影響就 會隨之增大。在MySQL中能夠使用鏈接查詢來替代子查詢。鏈接查詢不須要創建臨時表,其速度比子查詢要快。
18.3 優化數據庫結構
數據庫結構是否合理,須要考慮是否存在冗餘、對錶的查詢和更新的速度、表中字段的數據類型否合理等多方面的內容。
18.3.1 將字段不少的表分解成多個表
有些表在設置時設置了不少的字段。這個表中有些字段的使用頻率很低。當這個表的數據量很大時,查詢數據的速度就會很慢。
對於這種字段特別多且有些字段的使用頻率很低的表,能夠將其分解成多個表。
create table student_extra(
id int primary key,
extra varchar(255)
);
select * from student,student_extra where studnet.id=student_extra.id;
18.3.2 增長中間表
有時候須要常常查詢某兩個表中的幾個字段。若是常常進行聯表查詢,會下降MySQL數據庫的查詢速度。對於這種狀況,能夠創建中間表來提升查詢速度。
先分析常常須要同時查詢哪幾個表中的哪些字段。而後將這些字段創建一箇中間表,並從原來那幾個表將數據插入到中間表中。以後就能夠使用中間表來進行查詢和統計了。
desc student;
desc score;
create table temp_score(
id int not null,
name varchar(20) not null,
grade float
) default charset=utf8;
insert into temp_score select student.id,student.name,score.grade from student,score where student.id=score.stu_id;
18.3.3 增長冗餘字段
設計數據庫表的時候儘可能讓表達到三範式。可是,有時候爲了提升查詢速度,能夠有意識的在表中增長冗餘字段。
表 的規範化程序越高,表與表之間的關係就越多。查詢時可能常常須要多個表之間進行鏈接查詢。而進行鏈接操做會下降查詢速度。例如,學生的信息存儲在 student表中,院系信息存儲在department表中,經過student表中的dept_id字段與department表創建關聯關係。若是 要查詢一個學生所在系的名稱,必須從student表中查找學生所在院系的編號(dept_id),而後根據這個編號去department查找系的名 稱。若是常常須要進行這個操做時,鏈接查詢會浪費不少的時候。所以能夠在student表中增長一個冗餘字段dept_name,該字段用來存儲學生所在 院系的名稱。這樣就不用每次都進行鏈接操做了。
18.3.4 優化插入記錄的速度
插入記錄時,索引、唯一性校驗都會影響到插入記錄的速度。並且,一次插入多條記錄和屢次插入記錄所耗費的時間是不同的。根據這些狀況,分別進行不一樣的優化。
1. 禁用索引
插入記錄的時候,MySQL會根據對錶的索引插入的數據進行排序。若是插入大量數據的時候,這些排序會會下降插入數據的速度。爲這解決這個問題,首先插入數據以前先關閉當前表的索引,等數據插入完畢以後再開啓索引。
ALTER TABLE 表名 disable keys; # 禁用當前表的索引
ALTER TABLE 表名 enable keys; # 開啓當前表的索引
2. 禁用唯一性檢查
插入數據的時候,會檢測數據的惟一性校驗這會下降大量數據的插入速度。
#禁用唯一性檢查
set unique_checks=0;
# 開啓唯一性檢查
set unique_checks=1;
3. 優化insert語句
1.一次性插入多條語句(減小數據庫鏈接,速度更優)
2.屢次插入語句(相對慢)
18.4 分析表、檢查表和優化表
分析表主要做用是分析關鍵字的分佈。
檢查表主要做用是檢查表是否存在錯誤。
優化表主要做用是消除刪除或者更新形成空間浪費。
18.4.1 分析表
使用analyze語句的時候對當前表進行只讀鎖,在分析表的時候只能讀取數的數據,不能更新他插入記錄。可以分析InnoDb和MyISAM類型的表。
ANALYZE TABLE 表名1[,表名2...];
analyze table score;
Table Op Msg_type Msg_text
test.score analyze status OK
Op:
analyze
check
optimize
Msg_type:
status(狀態)
warnings(警告)
error(錯誤)
18.4.2 檢查表(包括視圖表)
CHECK TABLE 表名1[,表名2...][options]
options:只適用於MyISAM類型,且只讀鎖
CHECK TABLE score;
18.4.3 優化表
適用於引擎類型:InnoDB和MyISAM
適用於數據類型:varchar、blob和text類型的字段
只讀鎖
OPTIMIZE table 表名1[,表名2...]
optimize table score;
18.5 優化MySQL服務器
優化MySQL服務器能夠從兩個方面來理解。一個是從硬件方面來進行優化。另外一個是從MySQL服務的參數進行優化。經過這些優化方式,能夠提供MySQL的運行速度。可是這部分的內容很難理解,通常只有專業的數據庫管理員才能進行這一類的優化。
18.5.1 優化服務器硬件
服務器的硬件性能直接決定着MySQL數據庫的性能。例如,增長內存和提升硬盤的讀寫速度,這可以提升MySQL數據庫的查詢、更新的速度。
隨 着硬件技術的成熟、硬件的價格也隨之下降。如今普通的我的電話都已配置了2G內存,甚至一些我的電腦配置4G內存。由於內存的讀寫速度比硬盤的讀寫速度 快。能夠在內存中爲MySQL設置更多的緩衝區,這樣能夠提升MySQL訪問的速度。若是將查詢頻率很高的記錄存儲在內存中,那查詢速度就會很快。
如 果條件容許,能夠將內存提升到4G。而且選擇my-innodb-heavy-4G.ini做爲MySQL數據庫的配置文件。可是,這個配置文件主要支持 InnoDB存儲引擎的表。若是使用2G內存,能夠選擇my-huge-ini做爲配置文件。並且,MySQL所在的計算機最好是專用數據庫服務器。這樣 數據庫能夠徹底利用該機器的資源。
18.5.2 優化MySQL的參數
內存中會爲MySQL保留部分的緩存區。這些緩存區能夠提升MySQL數據庫的處理速度。緩存區的大小都是在MySQL的配置文件中進行設置的。
MySQL中比較重要的配置參數都在my.cnf或者my.ini文件[mysqld]組中。
innodb_buffer_pool_size=36M
18.6 本章實例
(1)查看InnoDB表的查詢的記錄數和更新的記錄數。
show status like 'Innodb_rows_read' \G
show status like 'Innodb_rows_updated' \G
(2)分析查詢語句的性能,select語句以下:
explain select * from score where stu_id=902 \G
analyze table score;
18.7 上機實踐
(1)查看MySQL服務器的鏈接數、查詢次數和慢查詢的次數
show status like 'Connections';
show status like 'Com_select';
show status like 'Slow_queries';
(2)檢查score表
check table score;
(3)優化score表
optimize table socre;
18.9 常見問題及解答
1. 如何使用查詢緩存區?
查 詢緩存區提升查詢的速度,這種方式只適用於修改操做少且常常執行相同的查詢操做的狀況。默認狀況下,查詢緩存區是禁止的,由於 query_cache_size的默認值爲0。query_cache_size能夠設置有效的使用空間。query_cache_type能夠設置查 詢緩衝區的開啓狀態,其取值爲0、1或者2。在my.cnf或者my.ini中加入下面的語句:
# my.cnf(Linux)或者my.ini(Windows)
[mysqld]
query_cache_size=20M
query_cache_type=1
query_cache_type取值爲1時表示開啓查詢緩存區。在查詢語句中加上SQL_NO_CACHE關鍵字,該查詢語句將不使用查詢緩存區。能夠使用FLUSH QUERY CACHE語句來清理查詢緩存區中的碎片。
2. 爲何查詢語句中的索引沒有發揮做用?
在 不少狀況下,雖然查詢語句中使用了索引,可是索引並無發揮做用。例如,在WHERE條件的LIKE關鍵字匹配的字符串以"%"開頭,這種狀況下索引不會 起做用。WHERE條件中使用OR關鍵字來鏈接多個查詢條件,若是有一個條件沒有使用索引,那麼其它的索引也不會起做用。若是使用多列索引時,多列索引第 一個字段沒有使用,那麼這個多列索引也不起做用。根據這些狀況,必須對這些語句進行相應的優化。
19.Java訪問MySQL數據庫
20.PHP訪問MySQL數據庫
現 在最流行的動態網站開發的軟件組合是LAMP。LAMP是Linux、Apache、MySQL和PHP的縮寫。PHP具備簡單易用、功能強大和開放性等 特色,這使PHP已經成爲了網絡世界中最流行的編程語言之一。PHP能夠經過mysql接口或者mysqli接口來訪問MySQL數據庫。
20.1 PHP鏈接MySQL數據庫
PHP可能經過mysql接口或者mysqli接口來訪問MySQL數據庫。若是但願正常的使用PHP,那麼須要適當的配置PHP與Apache服務器。同時,PHP中加入了mysql接口和mysqli接口後,纔可以順利訪問MySQL數據庫。
20.1.1 Windows下操做系統下配置PHP
1.首先安裝Apache服務器:
2.安裝PHP
(1)若是尚未安裝PHP,能夠在http://www.php.net/downloads.php 中下載PHP。Windows操做系統下推薦下載PHP 5.2.11 zip package。
在 Windows操做系統中,將PHP的軟件包解壓到C:\php目錄下。須要在Apache服務器的配置文件httpd.conf中添加一些信息。 Apache服務器的默認路徑爲C:\Program Files\Apache Software Foundation\Apache2.2。http.conf文件在Apache服務器目錄下的conf文件夾中。在httpd.conf中加入下面的 信息:
LoadModule php5_module
"C:/php/php5apache2_2.dll"
AddType applicatin/x-httpd-php .php
(2)php.ini-recommended()複製到C:\WINDOWS\目錄下
(3)添加參數:
;;;;;;;動態加載mysql和mysqli接口;;;;;;;;;;;;;;;;;;;;;;;
extension_dir="C:/php/ext"
extension=php_mysql.dll
extension=php_mysqli.dll
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(4)C:\php目錄下的libmysql.dll複製到C:\WINDOWS目錄下
(5)在Apachehtdocs目錄下建立一個文件名爲test.php。
test.php文件內容:
<?php
php_info();
?>
20.1.2 Linux操做系統下配置PHP
Linux 操做系統下推薦下載PHP 5.2.11(tar.gz)。下載網址爲:http://www.php.net/downloads.php 。下載完成後將php-5.2.11.tar.gz複製到/usr/local/src目錄下,而後在該目錄下解壓和安裝。假設新下載的php軟件包存儲 在/home/skydao/download目錄下。使用下面的語句來安裝PHP:
shell> cp /home/skydao/download/php-5.2.11.tar.gz /usr/local/src/
shell> cd /usr/local/src/
shell> tar -xzvf php-5.2.11
shell> cd php-5.2.11
shell> ./configure --prefix=/usr/local/php --with-mysql=/usr/local --with-mysqli=/usr/bin/mysql_config
shell> make
shell> make install
shell> make clean
20.1.6 鏈接MySQL數據庫
php能夠經過mysql接口來鏈接MySQL數據庫,也能夠經過mysqli接口來鏈接MySQL數據庫。
$connection = mysql_connect('host/IP','username','password');
# 指定登陸到哪一個數據庫
$connection = mysql_connect('localst','root','','test');
mysqli接口有兩個比較經常使用的內部類。分別是mysqli和mysqli_reult。
<?php
$connection = new mysqli('localhot','root','password','test'); // 建立鏈接
if (mysqli_connect_errno()) { // 判斷是否鏈接成功
ech '<p>鏈接失敗'.mysqli_connect_errno().'</p>'; // 輸出鏈接失敗的信息
exit(); // 退出程序
} else {
echo '<p>鏈接成功</p>'; // 顯示鏈接成功
}
?>
20.2 PHP操做MySQL數據庫
連 接MySQL數據庫以後,PHP能夠經過query()函數對數據進行查詢、插入、更新、刪除等操做。可是query()函數一次只能執行一條SQL語 句。若是須要一次執行多個SQL語句,須要使用multi_query()函數。PHP經過query()函數和multi_query()函數能夠方便 的操做MySQL數據庫。
20.2.1 執行SQL語句
PHP能夠經過query()函數來執行SQL語句。若是SQL語句是INSERT語句、UPDATE語句、DELETE語句等,語句執行成功query()返回true,不然返回false。而且,能夠經過affected_rows()函數獲取發生變化的記錄數。
# 執行INSERT語句
$result = $connection->query("INSERT INTO score VALUES(NULL,908, '法語',88");
if ($result) {
echo '<p>INSERT語句執行成功</p>'; // 輸出INSERT語句執行成功
echo '<p>插入的記錄數:'.$connection->affected_rows.'</p>'; // 返回插入的記錄數
} else {
echo '<p>INSERT語句執行失敗</p>'; // 輸出INSERT語句執行失敗
}
$result = $connection->query('SELECT * FROM socre'); // 執行SELECT語句
if ($result) {
echo '<p>SELECT語句執行成功</p>';
echo '<p>查詢的記錄數:'.$result->num_rows.'</p>'; // 輸出查詢的記錄數
echo '<p>查詢的字段數:'.$result->field_count.'</p>'; // 輸出查詢的字段數
} else {
echo '<p>SELECT語句執行失敗</p>'; // 輸出SELECT語句執行失敗的信息
}
20.2.2 處理查詢結果
query()函數成功的執行SELECT語句後,會返回一個mysqli_result對象$result。SELECT語句的查詢結果都存儲在$result中。mysqli接口中提供了四種方法來讀取數據。
$rs = $result->fetch_row(); $rs[$num]
$rs = $result->fetch_array(); $rs[$num]或$rw['columnName']
$rs = $result->fetch_assoc(); $rs['columnName']
$rs = $result->fetch_object(); $rs->columnName;
$result = $connection->query('SELECT * FROM core');
# 判斷是否還有記錄,若是有記錄,經過fetch_row()方法返回記錄的值;若是沒有記錄,返回FALSE
while ($row=$result->fetch_row()) {
echo '<p>'.$row[0].','.$row[1].','.$row[2].','.$row[3].'</p>';
}
while ($row=$result->fetch_assoc()) {
echo '<p>'.$row['id'].','.$row['stu_id'].','.$row['c_name'].','.$row['grade'].'</p>';
}
while ($row=$result->fetch_array()) {
echo '<p>'.$row[0].','.$row['stu_id'].','.$row[2].','.$row['grade'].'</p>';
}
while ($row=$result->fetch_object()) {
echo '<p>'.$row->id.','.$row->stu_id].','.$row->c_name.','.$row->grade.'</p>';
}
20.2.3 獲取查詢結果的字段名
通 過fetch_fields()函數能夠獲取查詢結果的詳細信息,這個函數返回對象數組。經過這個對象數組能夠獲取字段名、表名等信息。例如,$info = $result->fetch_fields()能夠產生一個對象數組$fino。而後經過$info[$sn]->name獲取字段 名,$info[$n]->table獲取表名。
$result = $connection->query('SELECT * FROM score');
$num = $result->field_count; // 計算查詢的字段數
$info = $result->fetch_fields(); // 獲取記錄的字段名、表名等信息
echo '<p>table:' . $info[0]->table.'</p>'; // 輸出表的名稱
for($i=0; $i<$num; $i++){
echo $info[$i]->name . "\t"; // 輸出字段的名稱
}
20.2.4 一次執行多個SQL語句
query() 函數一次只能執行一條SQL語句,而multi_query()函數能夠一次執行多個SQL語句。若是第一個SQL語句正確執行,那麼 multi_query()函數返回true。不然,返回false。PHP中使用store_result()函數返回獲取multi_query() 函數執行查詢的記錄。一次只能獲取一個SQL語句的執行結果。能夠使用next_result()函數來判斷下一個SQL語句的結果是否存在,若是存 在,next_result()函數返回true,不然返回false。
$sql = 'SELECT * FROM score;SELECT * FROM student';
$rows = $connection->multi_query($sql);
if ($rows) {
$result = $connection->store_result(); // 將查詢結果賦值給$result
while ($row = $result->fetch_object()){
echo '<p>'.$row->id."\t".$row->stu_id."\t".$row->c_name."\t".$row->grade.'</p>';
}
# 判斷是否還有下一個SELECT語句
if ($connection->next_result()) {
while ($row=$result->fetch_object()) {
echo '<p>'.$row->id."\t".$row->name."\t".$row->gender."\t".$row->birth.'</p>';
}
}
}
20.2.5 處理帶參數的SQL語句
PHP中能夠執行帶參數的SQL語句。帶參數的SQL語句中能夠不指定某個字段的值,而使用問號(?)代替。而後在後面的語句中指定值來替換掉問號。經過prepare()函數將帶參數的SQL語句進行處理。
經過prepare()函數將帶參數的SQL語句進行處理
$stmt = $mysqli->prepare("INSERT INTO table(name1,name2) values(?,?)");
使用bind_param()函數中將數據類型與相應的變量對應
$stmt->bind_param('idsb',$var1,$var2,$var3,$var4);
i:int/tiny7/tinyint/......
d:float/double/...
s:char/varchar/text
b:blob
經過execute()方法執行SQL語句
$stmt->execute();
示例:
$stmt = $mysqli->prepare('INSERT INTO socre(id,stu_id,c_name,grade') VALUES(?,?,?,?)');
$stmt->bind_param('iisi',$id,$stu_id,$c_name,$grade); // 給變量設置數據類型
# 給每一個變量賦值
$id=15;
$stu_id=908;
$c_name='數學';
$grade=85;
$stmt->execute(); // 執行INSERT語句
$id=16;
$stu_id=909;
$c_name='數學';
$grade=88;
$stmt->execute(;
20.2.6 關閉建立的對象
對MySQL數據庫的訪問完成後,必須關閉建立的對象。鏈接MySQL數據庫時建立了$connection對象,處理SQL語句的執行結果時建立了$result對象。操做完成後,這些對象必須使用close()方法來關閉。
$result->close();
$connection->close();
$stmt->close();
20.3 PHP備份與還原MySQL數據庫
PHP語言中可能執行mysqldump命令來備份MySQL數據庫,也能夠執行mysql命令來還原MySQL數據庫。PHP中使用system()函數或者exec()函數來調用mysqldump命令和mysql命令。
20.3.1 PHP備份MySQL數據庫
PHP能夠經過system()函數或者exec()函數來調用mysqldump命令。
system("mysqldump -h localhost -u root -pPassword database [table] > dir:\backup.sql");
exec() 函數的使用方法與system()函數是同樣的。這裏直接將mysqldump命令看成系統命令來調用。這須要將MySQL的應用程序的路徑添加到系統變 量的Path變量中。若是不想把MySQL的應用程序的路徑添加到Path變量中,能夠使用mysqldump命令的完整路徑。假設mysqldump在 c:\mysql\bin目錄下,system()函數的形式以下:
system("C:/mysql/bin/mysqldump -h localhost -u root -pPassword database [table] > dir:/backup.sql");
20.3.2
20.3.3
20.3.4
20.3.5
20.4
20.5
21.C#訪問MySQL數據庫
22.駕校管理系統