MySQL总论
1. MySQL基本概念
1.1.? 數(shù)據(jù)庫的概念
數(shù)據(jù)庫,簡而言之就是存儲數(shù)據(jù)的倉庫,可以按照一定的數(shù)據(jù)結(jié)構(gòu)存儲管理大量的數(shù)據(jù)及數(shù)據(jù)與數(shù)據(jù)之間的關(guān)系,它本質(zhì)上是一種信息管理系統(tǒng)。數(shù)據(jù)庫根據(jù)存儲采用的數(shù)據(jù)結(jié)構(gòu)的不同可以分為許多種,其中常見的有層次式數(shù)據(jù)庫、網(wǎng)絡(luò)式數(shù)據(jù)庫、關(guān)系型數(shù)據(jù)庫。其中關(guān)系型數(shù)據(jù)庫占據(jù)著市場的主流。
1.2.? 關(guān)系型數(shù)據(jù)庫
關(guān)系型數(shù)據(jù)庫是建立在關(guān)系模型基礎(chǔ)上的數(shù)據(jù)庫。這種定義聽起來十分抽象,這里我們不深入討論什么叫做“關(guān)系模型”--大學(xué)計算機專業(yè)專門有一門課叫“離散數(shù)學(xué)”專門討論過關(guān)系模型 --,只是簡單的表述為 利用表來存儲數(shù)據(jù),用表和表之間的關(guān)系保存數(shù)據(jù)之間的關(guān)系的數(shù)據(jù)庫稱為關(guān)系型數(shù)據(jù)庫,這個定義不太嚴(yán)謹(jǐn),但是更好理解。
1.3.? 常見的關(guān)系型數(shù)據(jù)庫
商業(yè)數(shù)據(jù)庫:
Oracle -- 甲骨文公司開發(fā),市場占有率第一
SQLServer -- 微軟公司開發(fā),.Net技術(shù)中常用
DB2 -- IBM公司開發(fā)
Sybase -- Sybase公司開發(fā)
開源數(shù)據(jù)庫:
MySql -- 瑞典MySql AB研發(fā),非常受歡迎,已經(jīng)被Oracle收購
SQLite -- 小型輕量級開源關(guān)系型數(shù)據(jù)庫,常用作嵌入式設(shè)備數(shù)據(jù)庫
1.4.? MySql數(shù)據(jù)庫的安裝配置
1.4.1.MySQL安裝配置
安裝配置步驟見附加文檔
1.4.2.MySQL安裝目錄
MySQL的數(shù)據(jù)存儲目錄為data,data目錄通常在\MySQLServer5.1\data位置。在data下的每個目錄都代表一個數(shù)據(jù)庫。
MySQL的安裝目錄下:
??? bin目錄中都是可執(zhí)行文件;
??? my.ini文件是MySQL的配置文件;
1.5.? 基本命令
1.5.1.啟動和關(guān)閉mysql服務(wù)器
啟動:net start mysql;
關(guān)閉:net stop mysql;
在啟動mysql服務(wù)后,打開windows任務(wù)管理器,會有一個名為mysqld.exe的進程運行,所以mysqld.exe才是MySQL服務(wù)器程序。
1.5.2.客戶端登錄退出mysql
在啟動MySQL服務(wù)器后,我們需要使用管理員用戶登錄MySQL服務(wù)器,然后來對服務(wù)器進行操作。登錄MySQL需要使用MySQL的客戶端程序:mysql.exe
登錄:mysql -u root -p 123 -h localhost;
-u:后面的root是用戶名,這里使用的是超級管理員root;
-p:后面的123是密碼,這是在安裝MySQL時就已經(jīng)指定的密碼;
-h:后面給出的localhost是服務(wù)器主機名,它是可以省略的,例如:mysql -u root -p 123;
退出:quit或exit;
在登錄成功后,打開windows任務(wù)管理器,會有一個名為mysql.exe的進程運行,所以mysql.exe是客戶端程序。
2. MySql常見概念
2.1.? 數(shù)據(jù)庫服務(wù)器
指的就是一個數(shù)據(jù)庫管理程序,這個程序可以管理多個數(shù)據(jù)庫。
2.2.? 數(shù)據(jù)庫
一個數(shù)據(jù)庫服務(wù)器可以管理多個數(shù)據(jù)庫,可以認為是一個數(shù)據(jù)的“倉庫”,一般一個web應(yīng)用對應(yīng)一個數(shù)據(jù)庫。
2.3.? 表
在保存應(yīng)用實體數(shù)據(jù)時,通常會在數(shù)據(jù)庫中創(chuàng)建多個表,以保存應(yīng)用程序?qū)嶓w數(shù)據(jù)。一般來說應(yīng)用程序中的一個javabean類可以對應(yīng)一張數(shù)據(jù)庫表。
2.4.? 表記錄
表中以一行記錄保存一條信息,這樣的一條記錄稱為表記錄。可以認為一個javabean對象對應(yīng)一條表記錄。
3. SQL語言
3.1.? 基本概念
3.1.1.SQL
SQL--Structured Query Language, 結(jié)構(gòu)化查詢語言,是關(guān)系型數(shù)據(jù)庫通用的操作語言。
是一種非過程性語言。
由美國國家標(biāo)準(zhǔn)局(ANSI)與國際標(biāo)準(zhǔn)化組織(ISO)制定SQL標(biāo)準(zhǔn)。各大數(shù)據(jù)庫廠商都對其做了實現(xiàn)。所以我們只要學(xué)會了SQL語言,就可以操作各大關(guān)系型數(shù)據(jù)庫了。
為加強SQL的語言能力,各廠商增強了過程性語言的特征,增加了一些非標(biāo)準(zhǔn)的SQL,這樣的SQL稱為該數(shù)據(jù)庫的“方言”。
SQL是用來存取關(guān)系數(shù)據(jù)庫的語言,具有查詢、操縱、定義和控制關(guān)系型數(shù)據(jù)庫的四方面功能
3.2.? 操作數(shù)據(jù)庫
3.2.1.創(chuàng)建數(shù)據(jù)庫
語法:
CREATE? DATABASE? [IF NOT EXISTS]? db_name? [create_specification [, create_specification] ...]
create_specification:
[DEFAULT] CHARACTER SET charset_name? |? [DEFAULT] COLLATE collation_name
其中charset_name是為數(shù)據(jù)庫指定的默認字符集
Collate是為數(shù)據(jù)庫指定的默認校對規(guī)則
校對規(guī)則是在字符集內(nèi)用于比較字符的一套規(guī)則,可以控制select查詢時where條件大小寫是否敏感的規(guī)則。
練習(xí):
~創(chuàng)建一個名稱為mydb1的數(shù)據(jù)庫。
??? CREATE DATABASE mydb1;
~創(chuàng)建一個使用gbk字符集的mydb2數(shù)據(jù)庫。
??? CREATE DATABASE mydb2 CHARACTER SET gbk;
~創(chuàng)建一個使用utf8字符集,并帶校對規(guī)則的mydb3數(shù)據(jù)庫。
??? CREATE DATABASE mydb3 CHARACTER SET utf8 COLLATE utf8_bin;
3.2.2.查看數(shù)據(jù)庫
語法:
顯示所有數(shù)據(jù)庫:
SHOW DATABASES
顯示數(shù)據(jù)庫創(chuàng)建語句:
?SHOW CREATE DATABASE db_name
練習(xí):
~查看當(dāng)前數(shù)據(jù)庫服務(wù)器中的所有數(shù)據(jù)庫
?? SHOW DATABASES;
~查看前面創(chuàng)建的mydb2數(shù)據(jù)庫的定義信息
?? SHOW CREATE DATABASE mydb2;
3.2.3.修改數(shù)據(jù)庫
語法:
ALTER DATABASE db_name??[alter_specification [, alter_specification] ...]
alter_specification:???
[DEFAULT] CHARACTER SET charset_name? | [DEFAULT] COLLATE collation_name
練習(xí):
~查看服務(wù)器中的數(shù)據(jù)庫,并把mydb2庫的字符集修改為utf8
?? ALTER DATABASE mydb2 CHARACTER SET utf8;
3.2.4.刪除數(shù)據(jù)庫
語法:
DROP DATABASE? [IF EXISTS]? db_name
練習(xí):
~刪除前面創(chuàng)建的mydb1數(shù)據(jù)庫
?? DROP DATABASE mydb1;
3.2.5.選擇數(shù)據(jù)庫
語法:
選擇數(shù)據(jù)庫:use db_name;
查詢當(dāng)前選擇的數(shù)據(jù): select database();
沒有退出數(shù)據(jù)庫的命令,如果想退出當(dāng)前數(shù)據(jù)庫進入另一個數(shù)據(jù),直接use 另一個數(shù)據(jù)庫 就可以了
3.3.? 操作表
3.3.1.SQL中常見數(shù)據(jù)類型
1)字符串型
VARCHAR:
變長的字符串,需要在聲明字段時指定能存儲的最大字符數(shù),真實占用的空間取決于存入的字符數(shù),存入的越多占用空間越多。適合保存內(nèi)容長度不定的字符類型數(shù)據(jù)。能包含數(shù)據(jù)的大小,mysql5.0以前0~255字節(jié),mysql5.0以后0~65535字節(jié)
CHAR:
定長字符串,需要在聲明字段時指定固定字符數(shù)。即使存入的字符數(shù)少于該長度,該字段也會占用該固定長度。適合存儲長度不變的字符類型數(shù)據(jù)。能包含數(shù)據(jù)的大小,0~255字節(jié)
2)大數(shù)據(jù)類型
BLOB:
大二進制類型,可以存入二進制類型的數(shù)據(jù),通過這個字段,可以將圖片、音頻、視頻等數(shù)據(jù)以二進制的形式存入數(shù)據(jù)庫。最大為4GB。
TEXT:
大文本,被聲明為這種類型的字段,可以保存大量的字符數(shù)據(jù),最大為4GB。
注意:text屬于mysql的方言,在其他數(shù)據(jù)庫中為clob類型
3)數(shù)值型
TINYINT:占用1個字節(jié),相對于java中的byte
SMALLINT:占用2個字節(jié),相對于java中的short
INT:占用4個字節(jié),相對于java中的int
BIGINT:占用8個字節(jié),相對于java中的long
FLOAT:4字節(jié)單精度浮點類型,相對于java中的float
DOUBLE:8字節(jié)雙精度浮點類型,相對于java中的double
4)邏輯型
BIT:
位類型,可以存儲指定位的值,可以指定位的個數(shù),如果不指定則默認值為1位,即只能保存0或1,對應(yīng)到j(luò)ava中可以是boolean型。
5)日期型
DATE:日期
TIME:時間
DATETIME:日期時間
TIMESTAMP:時間戳
**DATETIME和TIMESTAMP的區(qū)別?
* DATETIME和TIMESTAMP顯示的結(jié)果是一樣的,都是固定的"YYYY-MM-DD HH:MM:SS"的格式
* DATETIME支持的范圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。TIMESTAMP的顯示范圍是'1970-01-01 00:00:00'到2037年,且其實際的存儲值為1970年到當(dāng)前時間的毫秒數(shù)。
* 在建表時,列為TIMESTAMP的日期類型可以設(shè)置一個默認值,而DATETIME不行。
* 在更新表時,可以設(shè)置TIMESTAMP類型的列自動更新時間為當(dāng)前時間。
3.3.2.字段約束
字段的約束:約束了表中一個字段的值需要符合的條件
1)定義主鍵約束
通常每張表都會有一個字段或多個字段聯(lián)合起來唯一標(biāo)識表記錄,這樣的字段稱為這張表的主鍵。我們可以為這樣的字段增加主鍵約束。主鍵約束要求字段必須不能為空且值必須唯一。
增加主鍵約束:PRIMARY KEY
可以在定義主鍵時指定主鍵的自動增長auto_increment,這樣主鍵就不需要人為的維護,在新增記錄時不需要指定主鍵的值,數(shù)據(jù)庫會自動維護一個計數(shù)器,每次計數(shù)器的值+1后作為主鍵,保證主鍵的唯一性。
2)定義唯一約束
如果需要指定某個字段的值不能重復(fù),可以為該字段指定唯一約束
增加唯一約束:unique
3)定義非空約束
如果需要指定某個字段的值不能為空,可以為該字段指定非空約束
增加非空約束:not null
4)外鍵約束
??? 見3.6
3.3.3.新增表
語法:
CREATE TABLE table_name
(
field1? datatype,
field2? datatype,
field3? datatype
)[character set 字符集] [collate 校對規(guī)則]
field:指定列名 datatype:指定列類型
?
注意:創(chuàng)建表時,要根據(jù)需保存的數(shù)據(jù)創(chuàng)建相應(yīng)的列,并根據(jù)數(shù)據(jù)的類型定義相應(yīng)的列類型。
創(chuàng)建表時,一般不需要指定字符集編碼和校對規(guī)則,和數(shù)據(jù)庫保持一致即可。
?
練習(xí)
~創(chuàng)建employee表
| 字段 | 屬性 |
| id | 整型 |
| name | 字符型 |
| gender | 字符型 |
| birthday | 日期型 |
| entry_date | 日期型 |
| job | 字符型 |
| salary | 小數(shù)型 |
| resume | 大文本型 |
?
?
?
?
?
?
?
?
?
?
?
?
create table employee(id int primary key auto_increment,name varchar(20) unique,gender bit not null,birthday date,entry_date date,job varchar(100),salary double,resume text);3.3.4.查看表
語法:
查看表結(jié)構(gòu):
desc tabName
查看當(dāng)前所有表:
show tables
查看當(dāng)前數(shù)據(jù)庫表建表語句
show create table tabName;
3.3.5.修改表
語法:
增加列:
ALTER TABLE tabname ADD (column datatype [DEFAULT expr][, column datatype]...);
?
修改列:
ALTER TABLE tabname MODIFY (column datatype [DEFAULT expr][, column datatype]...);
?
刪除列:
ALTER TABLE tabname DROP (column);
?
修改表名:
ALTER TABLE old_tabname RENAME TO new_tabname;
或
RENAME TABLE old_tabname TO new_tabname;
?
修改列名稱:
ALTER TABLE tabname CHANGE [column] old_col_name new_col_name datatype
?
修改列的順序:
ALTER TABLE tabname MODIFY col_name1 datatype AFTER col_name2;
?
修改表的字符集:
ALTER TABLE tabname CHARACTER SET character_name;
練習(xí):
~在上面員工表的基礎(chǔ)上增加一個image列。
alter table employee add image blob;
~修改job列,使其長度為60。
alter table employee modify job varchar(60);
~刪除gender列。
alter table employee drop gender;
~表名改為user。
alter table employee rename to user;
??? 或
rename table employee to user;
~列名name修改為username
alter table user change name username varchar(20);
~將image插入到gender列的后面
alter table user modify image blob after gender;
~修改表的字符集為utf8
alter table user character set utf8;
3.3.6.刪除表
語法:
DROP TABLE tabname;
練習(xí):
~刪除user表
drop table user;
3.4.? 操作表記錄
3.4.1.INSERT
語法:
INSERT INTO tabname [(column [, column...])] VALUES (value [, value...]);
注意:
插入的數(shù)據(jù)應(yīng)與字段的數(shù)據(jù)類型相同
數(shù)據(jù)的大小應(yīng)在列的規(guī)定范圍內(nèi)
在values中列出的數(shù)據(jù)位置必須與被加入的列的排列位置相對應(yīng)
字符串和日期格式的數(shù)據(jù)要用單引號引起來
如果要插入所有字段可以省寫列列表,直接按表中字段順序?qū)懼盗斜?/p>
?
練習(xí):
~向員工表中插入三條數(shù)據(jù)
insert into employee (id,name,gender,birthday,entry_date,job,salary,resume)values(null,'張飛',1,'1990-09-09','2000-01-01','打手',998.0,'真的很能打...');insert into employeevalues(null,'關(guān)羽',0,'1990-08-08','1990-08-09','財神',9999999.0,'公司掙錢就指著他了...');insert into employeevalues(null,'劉備',1,'1990-06-06','1990-09-09','ceo',10.0,'公司的 ceo,基本沒啥事干..'),(null,'趙云',1,'2010-06-01','2010-06-01','保鏢',400.0,'老板的 貼身護衛(wèi)...');3.4.2.mysql亂碼解決:
查看當(dāng)前數(shù)據(jù)庫中字符集配置:
show variables like'character%';
其中:
client是客戶端使用的字符集。
connection是連接數(shù)據(jù)庫的字符集設(shè)置類型,如果程序沒有指明連接數(shù)據(jù)庫使用的字符集類型就按照服務(wù)器端默認的字符集設(shè)置。
database是數(shù)據(jù)庫服務(wù)器中某個庫使用的字符集設(shè)定,如果建庫時沒有指明,將使用服務(wù)器安裝時指定的字符集設(shè)置。???
results是數(shù)據(jù)庫給客戶端返回時使用的字符集設(shè)定,如果沒有指明,使用服務(wù)器默認的字符集。??????
server是服務(wù)器安裝時指定的默認字符集設(shè)定。??????
system是數(shù)據(jù)庫系統(tǒng)使用的字符集設(shè)定。(utf-8不可修改)
?
set names xxx; 命令是客戶端通知服務(wù)器和當(dāng)前客戶端交互時使用什么編碼,但是這種方式每次新開客戶端都需要通知服務(wù)器 很麻煩???
我們可以修改mysql/my.ini,將default-character-set=gbk,這是修改服務(wù)器默認認為的客戶端的字符集編碼
這樣一來,大部分人都是gbk的客戶端,不需要設(shè)置任何東西,連進來就沒亂碼.如果有個別的人客戶端不是gbk,也可以通過set names xxx;的方式聲明自己的編碼集,也沒有亂碼.
?
3.4.3.UPDATE
語法:
UPDATE tab_name SET col_name1=expr1 [, col_name2=expr2 ...]??[WHERE where_definition]???
UPDATE語法可以用新值更新原有表行中的各列。
SET子句指示要修改哪些列和要給予哪些值。
WHERE子句指定應(yīng)更新哪些行。如沒有WHERE子句,則更新所有的行。
練習(xí):
~將所有員工薪水修改為5000元。
update employee set salary=5000;
~將姓名為’張飛’的員工薪水修改為3000元。
update employee set salary=3000 where name='張飛';
~將姓名為’關(guān)羽’的員工薪水修改為4000元,job改為”耍大刀”。
update employee set salary=4000,job='耍大刀' where name='關(guān)羽';???
~將劉備的薪水在原有基礎(chǔ)上增加1000元。
update employee set salary=salary+1000 where name='劉備';
?
3.4.4.DELETE
語法:
delete from tab_name?[WHERE where_definition]
where用來篩選要刪除的記錄,如果不使用where子句,將刪除表中所有數(shù)據(jù)。
delete語句不能刪除某一列的值(可使用update)
delete語句僅刪除記錄,不刪除表本身。如要刪除表,使用drop table語句。
TRUNCATE TABLE tab_name語句也可以刪除表中數(shù)據(jù),它和delete有所不同。delete是一條條刪除記錄,truncate是摧毀整表再重建相同結(jié)構(gòu)的表,truncate效率更高。
?
練習(xí):
~刪除表中名稱為’張飛’的記錄。
delete from employee where name='張飛';
~刪除表中所有記錄。
delete from employee;
~使用truncate刪除表中記錄。
truncate table employee;
?
3.4.5.SELECT
(1)基本的查詢
語法:
SELECT [DISTINCT] *|{column1, column2. column3..} FROM table;
select 指定查詢哪些列的數(shù)據(jù)。
column指定列名。
*號代表查詢所有列。
from指定查詢哪張表。
DISTINCT可選,指顯示結(jié)果時,是否剔除重復(fù)數(shù)據(jù)
練習(xí):
create table exam(id int primary key auto_increment,name varchar(20) not null,chinese double,math double,english double);insert into exam values(null,'關(guān)羽',85,76,70);insert into exam values(null,'張飛',70,75,70);insert into exam values(null,'趙云',90,65,95);insert into exam values(null,'張三豐',82,79,null);~查詢表中所有學(xué)生的信息。
select * from exam;
~查詢表中所有學(xué)生的姓名和對應(yīng)的英語成績。
select name,english from exam;
~過濾表中重復(fù)數(shù)據(jù)。
select distinct english from exam;
~在所有學(xué)生分?jǐn)?shù)上加10分特長分顯示。
select name,english+10 ,chinese+10 ,math+10 from exam;
~統(tǒng)計每個學(xué)生的總分。
select name,english+math+chinese from exam;
~使用別名表示學(xué)生總分。
select name as 姓名,english+math+chinese as 總分 from exam;
select name 姓名,english+math+chinese 總分 from exam;
select name english from exam;//~!這是錯的
?
(2)使用where子句的查詢
語法:
Select *|列名 from tablename [WHERE where_definition]
其中Where子句中支持:?
Like語句中,% 代表零個或多個任意字符,_ 代表一個字符,例first_name like ‘_a%’;
?
練習(xí):
~查詢姓名為關(guān)羽的學(xué)生成績
select * from exam where name='關(guān)羽';
~查詢英語成績大于90分的同學(xué)
select * from exam where english > 90;
~查詢總分大于230分的所有同學(xué)
select name 姓名,english+math+chinese 總分 from exam where english+math+chinese>230;
~查詢語文分?jǐn)?shù)在 80-100之間的同學(xué)。
???????? ???????? select name,chinese from exam where chinese between 80 and 100;
~查詢數(shù)學(xué)分?jǐn)?shù)為75,76,77的同學(xué)。再查詢分?jǐn)?shù)不在這個范圍內(nèi)的同學(xué)
??? select name,math from exam where math in (75,76,77);
??? select name,math from exam where math not in (75,76,77);
~查詢所有姓張的學(xué)生成績。
select * from exam where name like '張%';
select * from exam where name like '張_';
select * from exam where name like '張__';
~查詢數(shù)學(xué)分>70,語文分>80的同學(xué)。
select * from exam where math>70 and chinese>80;
?
(3)排序查詢
語法:
SELECT column1, column2. column3.. FROM table order by column asc|desc;
Order by 指定排序的列,排序的列即可是表中的列名,也可以是select 語句后指定的列名。
Asc 升序、Desc 降序
ORDER BY 子句應(yīng)位于SELECT語句的結(jié)尾。
?
練習(xí):
~對英語成績排序后輸出。
select name ,english from exam order by english desc;
~對總分排序按從高到低的順序輸出
??? select name 姓名, ifnull(english,0)+ifnull(math,0)+ifnull(chinese,0) 總分 from exam order by 總分 desc;
~對姓張的學(xué)生成績排序輸出
select name 姓名, ifnull(english,0)+ifnull(math,0)+ifnull(chinese,0) 總分 from exam where name like '張%' order by 總分 desc;
?
(4)聚合函數(shù)
SQL提供的聚合函數(shù)有計數(shù)函數(shù)COUNT()、求和函數(shù)SUM()、平均值函數(shù)AVG()、最大值函數(shù)MAX()、最小值函數(shù)MIN()等。如下表:
| 函數(shù)名稱 | 函數(shù)功能 |
| COUNT() | 返回選取結(jié)果集中行的數(shù)目 |
| SUM() | 返回選取結(jié)果集中所有值的總和 |
| AVG() | 返回選取結(jié)果集中所有值的平均值 |
| MAX() | 返回選取結(jié)果集中所有值的最大值 |
| MIN() | 返回選取結(jié)果集中所有值的最小值 |
?
?
?
?
?
?
?
?
?
語法:
求符合條件的記錄中指定列的記錄數(shù)
??? select count(列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的和值
??? Select sum(列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的平均值
??? Select avg (列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的最大值
??? Select max(列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的最小值
??? Select min(列名)… from tablename [WHERE where_definition]
練習(xí):
~統(tǒng)計一個班級共有多少學(xué)生?
select count(*) from exam;
~統(tǒng)計數(shù)學(xué)成績大于75的學(xué)生有多少個?
select count(*) from exam where math>75;
~統(tǒng)計總分大于230的人數(shù)有多少?
select count(name) from exam
where ifnull(english,0)+ifnull(math,0)+ifnull(chinese,0) >230;
~統(tǒng)計一個班級數(shù)學(xué)總成績?
select sum(math) from exam;
~統(tǒng)計一個班級語文、英語、數(shù)學(xué)各科的總成績
select sum(math) ,sum(english),sum(chinese) from exam;
~統(tǒng)計一個班級語文、英語、數(shù)學(xué)的成績總和
select sum(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) from exam;
~統(tǒng)計一個班級語文成績平均分
select sum(chinese)/count(*) from exam;
~求一個班級數(shù)學(xué)平均分?
select avg(math) from exam;
~求一個班級總分平均分?
select avg(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) ?? ???????? from exam;
~求班級最高分和最低分
select max(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) ???????? from exam;
select min(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) ? ???????? from exam;
(5)分組查詢
語法:
SELECT column1, column2. column3.. FROM???? table group by column having ...
?
練習(xí):
create table orders(id int,product varchar(20),price float);insert into orders(id,product,price) values(1,'電視',900);insert into orders(id,product,price) values(2,'洗衣機',100);insert into orders(id,product,price) values(3,'洗衣粉',90);insert into orders(id,product,price) values(4,'桔子',9);insert into orders(id,product,price) values(5,'洗衣粉',90);?
~對訂單表中商品歸類后,顯示每一類商品的總價
select product ,sum(price) from orders group by product;
~查詢購買了幾類商品,并且每類總價大于100的商品
select product ,sum(price)
??? from orders group by product having sum(price) >100;
~查詢單價小于100而總價大于100的商品的名稱.
??? select product
??? from orders
??? where price < 100 group by product having sum(price)>100;
?
**where子句和having子句都可以進行過濾器,但是使用場景有所不同:
* where子句對分組之前的數(shù)據(jù)進行過濾,不能使用聚合函數(shù)
* having子句對分組之后的數(shù)據(jù)進行過濾,可以使用聚合函數(shù)
* 使用where子句的地方都可以用having替代,但是使用having的地方一般不能用 where替代
3.5.? mysql數(shù)據(jù)庫的備份與恢復(fù)
3.5.1.備份數(shù)據(jù)庫:
cmd窗口中使用mysqldump 備份數(shù)據(jù)庫
mysqldump -u root -p db_name > c:/xxx.sql
例如:mysqldump -u root -p mydb2 > c:/mydb2.sql
3.5.2.恢復(fù)數(shù)據(jù)庫:
方式1:cmd窗口中使用mysql命令 恢復(fù)數(shù)據(jù)庫,注意,只能恢復(fù)數(shù)據(jù)庫中的數(shù)據(jù),不能恢復(fù)數(shù)據(jù)庫本身!所以要提前建好數(shù)據(jù)庫.
mysql -u root -p db_name < c:/xxx.sql
例如:mysql -u root -p mydb2 < c:/mydb2.sql
?
方式2:在mysql命令下,source xxx.sql,這個命令的作用就是,在當(dāng)前位置執(zhí)行sql文件中的所有的sql.首先新建出數(shù)據(jù)庫,進入數(shù)據(jù)庫,在source執(zhí)行備份的sql文件即可。
例如:source c:/xxx.sql
注意:如果在cmd窗口下,執(zhí)行出現(xiàn)“拒絕訪問”提示,用管理員打開cmd窗口即可。
3.6.? 外鍵約束
3.6.1.外鍵概念
數(shù)據(jù)庫用表來保存數(shù)據(jù),但是現(xiàn)實中,數(shù)據(jù)和數(shù)據(jù)之間往往具有一定的關(guān)系,在設(shè)計表時應(yīng)該如何來保存這種關(guān)系呢?我們來看如下圖。
?
一個部門可以具有多個員工,而一個員工只能屬于一個部門。對于這種類型的關(guān)系我們稱之為1對多的關(guān)系。
那么我們該如何保存他們之間的關(guān)系呢?
可不可以在dept表中設(shè)計一張表記錄部門中員工的信息呢?
?
我們發(fā)現(xiàn)這是不可行的,因為一個部門中可能有多個員工,這就導(dǎo)致emp_id中一個字段可能需要保存多個值,這是不可行的。
那么反過來,可否在emp表保存員工所屬部門id呢?
這種方式是可行的,因為一個員工只能屬于一個部門,dept_id中只需存儲一個值即可。
雖然我們設(shè)計了這樣的字段保存兩表之間的關(guān)系,但是數(shù)據(jù)庫并不知道這樣的關(guān)系。我們可以設(shè)想,如下的情況。
“公司老總發(fā)現(xiàn)科技部不掙錢,決定解散科技部”,對應(yīng)到數(shù)據(jù)庫時,就是如下的sql
delete from dept where id = 004;
正確的執(zhí)行后,數(shù)據(jù)庫中的數(shù)據(jù)變?yōu)槿缦?/p>
?
我們發(fā)現(xiàn)“555 郭德綱”人還在,所屬部門卻沒有了,數(shù)據(jù)之間的對應(yīng)關(guān)系出現(xiàn)了問題,我們稱為違反了數(shù)據(jù)庫的“完整性”。
之所以產(chǎn)生這樣的問題,是因為雖然我們知道dept_id要參考dept表的id列,但是數(shù)據(jù)庫并不知道,所以在刪除數(shù)據(jù)造成違反“不完整”性的情況下數(shù)據(jù)庫沒有任何提示。
為了防止這樣的問題產(chǎn)生,可以通過外鍵明確的通知數(shù)據(jù)庫維系這種關(guān)系。
一旦任何操作違反了這種關(guān)系,數(shù)據(jù)庫會阻止并報錯。
?
3.6.2.建表時增加外鍵:
foreign key(ordersid) references orders(id)
3.6.3.修改方式增加外鍵:
alter table book add [constraint FK_BOOK] foreign key(pubid) references pub_com(id) [on delete restrict] [on update restrict];
?
可以明確指定外鍵的名稱,如果不指定外鍵的名稱,mysql會自動為你創(chuàng)建一個外鍵名稱。
RESTRICT : 只要本表格里面有指向主表的數(shù)據(jù), 在主表里面就無法刪除相關(guān)記錄。
CASCADE : 如果在foreign key 所指向的那個表里面刪除一條記錄,那么在此表里面的跟那個key一樣的所有記錄都會一同刪掉。
??? ??? ??? ???
3.6.4.刪除外鍵
alter table 表名 drop foreign key 外鍵名
3.6.5.實驗外鍵
略
4. 多表設(shè)計
4.1.? 多表設(shè)計概念
在講解外鍵時,我們提到了表和表之間往往存在著一定的關(guān)系,那么除了上述的1對多關(guān)系外還有哪些種關(guān)系呢?又如何設(shè)計外鍵來保存這些不同的關(guān)系呢?下面,我們一起來討論表和表中的三種關(guān)系。
4.2.? 三種關(guān)系及外鍵設(shè)計
一對一表和表之間的關(guān)系分為三種,分別是1對1、1對多、多對多,下面就用具體的例子講解這三種關(guān)系
4.2.1.?
班級表和教室表之間的關(guān)系,一個班級只能在一個教室上課,一個教室也只能放下一個班級,這種關(guān)系就稱為一對一的關(guān)系,對于一對一的關(guān)系,可以在任意一方保存另一方的主鍵作為外鍵保存兩表之間的關(guān)系。
?
?
4.2.2.一對多
學(xué)生表和班級表的關(guān)系,一個班級可以有多個學(xué)生而一個學(xué)生只能屬于一個班級,這種關(guān)系稱為一對多的關(guān)系,對于一對多的關(guān)系,可以在多的一方設(shè)計外鍵保存一的一方的主鍵作為外鍵保存兩表之間的關(guān)系。
?
4.2.3.多對多:
學(xué)生表和教師表的關(guān)系,一個學(xué)生可以由多個老師教授,一個老師也可以教授多個學(xué)生,這種關(guān)系稱為多對多的關(guān)系,對于多對多的關(guān)系,需要設(shè)計一張第三方關(guān)系表保存兩張表主鍵之間的對應(yīng)關(guān)系。
?
5.????? 多表查詢
5.1.? 多表查詢概念
表和表之間往往是存在關(guān)系的,而有時我們需要的數(shù)據(jù)在多張表中,如何跨著多張表查詢數(shù)據(jù)呢?這就涉及到多表查詢了
準(zhǔn)備數(shù)據(jù):
create table dept(id int primary key auto_increment,name varchar(20));insert into dept values(null,'財務(wù)部'),(null,'人事部'),(null,'科技部'),(null,'銷售部'); create table emp(id int primary key auto_increment,name varchar(20),dept_id int);insert into emp values(null,'張飛',1),(null,'關(guān)羽',2),(null,'劉備',3),(null,'趙云',5);需求:查詢所有部門名稱和對應(yīng)的員工名稱。5.2.? 多表查詢設(shè)計
5.2.1.笛卡爾積查詢:
這是一種最原始的查詢方式,其實就是兩張表相乘的結(jié)果,如果左表有m條記錄,右表有n條記錄,則查詢出來m*n條記錄.雖然查出數(shù)據(jù)了,但是其中包含了大量錯誤的數(shù)據(jù),所以這種查詢我們通常不使用。
select * from dept,emp;
?
?
5.2.2.內(nèi)連接查詢
內(nèi)連接查詢:只查詢左邊表有且右邊表也有的數(shù)據(jù),本質(zhì)上是依據(jù)外鍵關(guān)系,在笛卡爾積查詢的基礎(chǔ)上過濾出正確的數(shù)據(jù)。通過觀察結(jié)果,我們發(fā)現(xiàn)結(jié)果中只有兩邊都有對應(yīng)數(shù)據(jù)的數(shù)據(jù)才能被查出來。
select * from dept ,emp where dept.id = emp.dept_id;
select * from dept inner join emp on dept.id = emp.dept_id;
?
5.2.3.外連接查詢:
內(nèi)連接查詢只能查找出兩邊表都有對應(yīng)數(shù)據(jù)的數(shù)據(jù),如果兩邊冗余的數(shù)據(jù)也需要查詢時該怎么辦呢?
(1)左外連接查詢:在內(nèi)連接的基礎(chǔ)上增加上左邊表有而有邊表沒有的記錄
select * from dept left join emp on dept.id = emp.dept_id;
?
#其中,left join 也可以寫成 left outer join;
(2)右外連接查詢:在內(nèi)連接的基礎(chǔ)上增加上右邊表有而左邊表沒有的記錄
select * from dept right join emp on dept.id = emp.dept_id;
?
#其中,right join 也可以寫成 right outer join;
(3)全外連接查詢:在內(nèi)連接的基礎(chǔ)上增加左邊表有而右邊表沒有的記錄和右邊表有而左邊表沒有的記錄
#mysql 不支持全外連接,但是其他的數(shù)據(jù)庫支持,比如SQL Server
select * from dept full join emp on dept.id = emp.dept_id;
?
#我們可以在mysql中使用union關(guān)鍵字模擬全外連接
select * from dept left join emp on dept.id = emp.dept_id
union
select * from dept right join emp on dept.id = emp.dept_id;
?
#其中,full join 也可以寫成 full outer join;
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/chuijingjing/p/10307320.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
- 上一篇: 端口映射与主机映射
- 下一篇: dbcp_c3p0连接mysql8.0.