文章目錄
- 一、數據庫概述
- 二、數據庫的安裝與配置
- 三、sql概述
- 四、Sql的分類
- 4.1 DDL:操作數據庫、表、列等
- 4.2 DML操作(重要)
- 4.3 DQL操作
- 創建學生表:stu
- 僱員表:emp
- 部門表:dept
- 1基礎查詢
- 2條件查詢
- 2.1條件查詢介紹
- 2.2查詢性別爲女,並且年齡50的記錄
- 2.3查詢學號爲S_1001,或者姓名爲liSi的記錄
- 2.4查詢學號爲S_1001,S_1002,S_1003的記錄
- 2.5查詢學號不是S_1001,S_1002,S_1003的記錄
- 2.6查詢年齡爲null的記錄
- 2.7查詢年齡在20到40之間的學生記錄
- 2.8查詢性別非男的學生記錄
- 2.9查詢姓名不爲null的學生記錄
- 3模糊查詢
- 3.1查詢姓名由5個字母構成的學生記錄
- 3.2查詢姓名由5個字母構成,並且第5個字母爲“i”的學生記錄
- 3.3查詢姓名以“z”開頭的學生記錄
- 3.4查詢姓名中第2個字母爲“i”的學生記錄
- 3.5查詢姓名中包含“a”字母的學生記錄
- 4字段控制查詢
- 5排序 order by 列名 asc(默認) desc
- 6聚合函數 sum avg max min count
- 7分組查詢
- 8LIMIT 方言
- 五、數據的完整性
- 六、多表查詢(重要)
- 七、MySQL中的函數
- 八、MySQL數據庫的備份與恢復
一、數據庫概述
- 數據庫(DataBase,DB):指長期保存在計算機的存儲設備上,按照一定規則組織起來,可以被各種用戶或應用共享的數據集合。(文件系統)
- 數據庫管理系統(DataBase Management System,DBMS):指一種操作和管理數據庫的大型軟件,用於建立、使用和維護數據庫,對數據庫進行統一管理和控制,以保證數據庫的安全性和完整性。用戶通過數據庫管理系統訪問數據庫中的數據。
數據庫軟件應該爲數據庫管理系統,數據庫是通過數據庫管理系統創建和操作的。
數據庫:存儲、維護和管理數據的集合。
二、數據庫的安裝與配置
卸載
1.停止mysql服務 net stop mysql 啓動mysql服務 net start mysql
2.卸載mysql
3.找到mysql 安裝目錄下的 my.ini datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
停止MySQL
1添加刪除程序中卸載MySQL
2到安裝目錄刪除MySQL
3刪除:C:\Documents and Settings\All Users\Application Data\MySQL
C:\ProgramData\MySQL
4查看註冊表:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services
搜索mysql,找到一律幹掉!
不需要重啓電腦(win xp),直接重新安裝即可
* 修改密碼
運行cmd
* 安裝成功了打開cmd --> mysql -uroot -p你的密碼
* 修改mysql root用戶密碼
1) 停止mysql服務 運行輸入services.msc 停止mysql服務
或者 cmd --> net stop mysql
2) 在cmd下 輸入 mysqld --skip-grant-tables 啓動服務器 光標不動 (不要關閉該窗口)
3) 新打開cmd 輸入mysql -u root -p 不需要密碼
use mysql;
update user set password=password(‘abc’) WHERE User=‘root’;
4) 關閉兩個cmd窗口 在任務管理器結束mysqld 進程
5) 在服務管理頁面 重啓mysql 服務
密碼修改完成
數據庫中一行記錄與對象之間的關係
列:字段
行:一條記錄(實體)
public class User{
private int id;
private String name;
private int age;
}
三、sql概述
SQL:Structure Query Language。(結構化查詢語言)
SQL被美國國家標準局(ANSI)確定爲關係型數據庫語言的美國標準,後來被國際化標準組織(ISO)採納爲關係數據庫語言的國際標準。
各數據庫廠商都支持ISO的SQL標準。普通話
各數據庫廠商在標準的基礎上做了自己的擴展。方言
四、Sql的分類
DDL**(Data Definition Language):數據定義語言,用來定義數據庫對象:庫、表、列等; CREATE、 ALTER、DROP
DML***(Data Manipulation Language):數據操作語言,用來定義數據庫記錄(數據); INSERT、 UPDATE、 DELETE
DCL(Data Control Language):數據控制語言,用來定義訪問權限和安全級別;
DQL*****(Data Query Language):數據查詢語言,用來查詢記錄(數據)。SELECT
注意:sql語句以;結尾
4.1 DDL:操作數據庫、表、列等
使用的關鍵字:CREATE、 ALTER、 DROP
4.1.1操作數據庫
創建
create database mydb1;
Create database mydb2 character set gbk;
Create database mydb3 character set gbk COLLATE gbk_chinese_ci;
查詢
查看當前數據庫服務器中的所有數據庫
show databases;
修改
查看服務器中的數據庫,並把mydb2的字符集修改爲utf8;
alter database mydb2 character set utf8;
刪除
drop database mydb3;
其他:
查看當前使用的數據庫
select database();
切換數據庫
use mydb2;
4.1.2操作數據表
-
語法:
create table 表名( 字段1 字段類型, 字段2 字段類型, ... 字段n 字段類型 );
-
常用數據類型:
int:整型
double:浮點型,例如double(5,2)表示最多5位,其中必須有2位小數,即最大值爲999.99;
char:固定長度字符串類型; char(10) 'abc ’
varchar:可變長度字符串類型;varchar(10) ‘abc’
text:字符串類型;
blob:字節類型;
date:日期類型,格式爲:yyyy-MM-dd;
time:時間類型,格式爲:hh:mm:ss
timestamp:時間戳類型 yyyy-MM-dd hh:mm:ss 會自動賦值
datetime:日期時間類型 yyyy-MM-dd hh:mm:ss
當前數據庫中的所有表
show tables;
查看錶的字段信息
desc表名;
降序排列(descend 的縮寫)
asc
升序排列(ascend 的縮寫)
在上面員工表的基本上增加一個image列。
alter table 表名add字段 字段類型;
修改job列,使其長度爲60。
alter table 表名 modify 字段 字段類型;
刪除image列,一次只能刪一列。
alter table 表名 drop 字段名image;
表名改爲user。
rename table 舊錶名 to user;
查看錶格的創建細節
show create table 表名;
show create database db_news;
修改表的字符集爲gbk
alert table 表名character set gbk;
列名name修改爲username
alter table 表名 change name username varchar(100);
刪除表
drop table user ;
4.2 DML操作(重要)
查詢表中的所有數據
select * from 表名;
DML是對錶的數據進行增、刪、改的操作。不要與DDL混淆了。
insert 、update、 delete
小知識: 在mysql中,字符串類型和日期類型都要用單引號括起來。‘tom’ ‘2015-09-04’ 空值:null
4.2.1插入操作:insert:
語法: insert into 表名(列名1,列名2 ...)values(列值1,列值2...);
注意:列名與列值的類型、個數、順序要一一對應。
可以把列名當做java中的形參,把列值當做實參。
值不要超出列定義的長度。
如果插入空值,請使用null
插入的日期和字符一樣,都使用引號括起來。
練習 :
create table emp(
id int,
name varchar(100),
gender varchar(10),
birthday date,
salary float(10,2),
entry_date date,
resume text
);
insert into emp(id,name,gender,birthday,salary,entry_date,resume)
values(1,'zhangsan','female','1990-5-10',10000,'2015-5-5-','good girl');
INSERT INTO emp(id,name,gender,birthday,salary,entry_date,resume)
VALUES(2,'lisi','male','1995-5-10',10000,'2015-5-5','good boy');
INSERT INTO emp(id,name,gender,birthday,salary,entry_date,resume)
VALUES(3,'wangwu','male','1995-5-10',10000,'2015-5-5','good boy');
批量插入:
insert into emp values
(4,'zs','m','2015-09-01',10000,'2015-09-01',NULL),
(5,'li','m','2015-09-01',10000,'2015-09-01',NULL),
(6,'ww','m','2015-09-01',10000,'2015-09-01',NULL);
4.2.2 修改操作 update:
語法:update 表名 set 列名1=列值1,列名2=列值2 ··· where 列名=值
練習:
將所有員工薪水修改爲5000元。
update emp set salary=5000
將姓名爲’zs’的員工薪水修改爲3000元。
update emp set salary=3000 where name=’ zhangsan’;
將姓名爲’aaa’的員工薪水修改爲4000元,job改爲ccc。
update emp set salary=4000,gender='female' where name='lisi';
將wu的薪水在原有基礎上增加1000元。
update emp set salary=salary+1000 where gender='male';
4.2.3 刪除操作 delete
語法 : delete from 表名 where 列名=值
練習 :
刪除表中名稱爲’zs’的記錄。
delete from emp where name=‘zs’;
刪除表中所有記錄。
delete from emp;
使用truncate刪除表中記錄。
truncate table emp;
delete 刪除表中的數據,表結構還在;刪除後的數據可以找回
truncate 刪除是把表直接DROP掉,然後再創建一個同樣的新表。
刪除的數據不能找回。執行速度比DELETE快。
4.3 DQL操作
DQL數據查詢語言 (重要)
數據庫執行DQL語句不會對數據進行改變,而是讓數據庫發送結果集給客戶端。
查詢返回的結果集是一張虛擬表。
查詢關鍵字:select
語法:select 列名 from表名
語法:
select列名
from表名
where condition /*行條件*/
group by grouping_columns /*對結果分組*/
having condition /*分組後的行條件*/
order by sorting_columns /*對結果分組*/
limit offset_start, row_count /*結果限定*/
創建學生表:stu
create table stu (
sid CHAR(6),
sname VARCHAR(50),
age INT,
gender VARCHAR(50)
);
INSERT INTO stu VALUES('S_1001', 'liuYi', 35, 'male');
INSERT INTO stu VALUES('S_1002', 'chenEr', 15, 'female');
INSERT INTO stu VALUES('S_1003', 'zhangSan', 95, 'male');
INSERT INTO stu VALUES('S_1004', 'liSi', 65, 'female');
INSERT INTO stu VALUES('S_1005', 'wangWu', 55, 'male');
INSERT INTO stu VALUES('S_1006', 'zhaoLiu', 75, 'female');
INSERT INTO stu VALUES('S_1007', 'sunQi', 25, 'male');
INSERT INTO stu VALUES('S_1008', 'zhouBa', 45, 'female');
INSERT INTO stu VALUES('S_1009', 'wuJiu', 85, 'male');
INSERT INTO stu VALUES('S_1010', 'zhengShi', 5, 'female');
INSERT INTO stu VALUES('S_1011', 'xxx', NULL, NULL);
僱員表:emp
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm decimal(7,2),
deptno INT
) ;
INSERT INTO emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
部門表:dept
CREATE TABLE dept(
deptno INT,
dname varchar(14),
loc varchar(13)
);
INSERT INTO dept values(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept values(20, 'RESEARCH', 'DALLAS');
INSERT INTO dept values(30, 'SALES', 'CHICAGO');
INSERT INTO dept values(40, 'OPERATIONS', 'BOSTON');
1基礎查詢
1.1查詢所有列
select * from 表名;
1.2查詢指定列
select 字段1,字段2,字段3 from 表名;
2條件查詢
2.1條件查詢介紹
條件查詢就是在查詢時給出WHERE子句,在WHERE子句中可以使用如下運算符及關鍵字:
=、!=、<>、<、<=、>、>=;
between…and;
in(set);
IS NULL; IS NOT NULL
AND;
OR;
NOT;
2.2查詢性別爲女,並且年齡50的記錄
select * from stu
where gender='female' and ge<50;
2.3查詢學號爲S_1001,或者姓名爲liSi的記錄
select * from stu
where sid ='S_1001' or sname='liSi';
2.4查詢學號爲S_1001,S_1002,S_1003的記錄
select * from stu
where sid in('S_1001','S_1002','S_1003');
2.5查詢學號不是S_1001,S_1002,S_1003的記錄
select * from tab_student
where s_number not in('S_1001','S_1002','S_1003');
2.6查詢年齡爲null的記錄
select * from stu
where age is null;
2.7查詢年齡在20到40之間的學生記錄
select * from stu
where age>=20 and age<=40;
或者
select * from stu
where age between 20 and 40;
2.8查詢性別非男的學生記錄
select * from stu
where gender!='male';
或者
select * from stu
where gender<>'male';
或者
select * from stu
where not gender='male';
2.9查詢姓名不爲null的學生記錄
select * from stu
where sname is not null;
或者
select * from stu
where not sname is null;
3模糊查詢
當想查詢姓名中包含a字母的學生時就需要使用模糊查詢了。模糊查詢需要使用關鍵字like。
通配符:
_ 任意一個字符
%:任意0~n個字符
‘%張%’ ‘張_’
3.1查詢姓名由5個字母構成的學生記錄
select * from stu
where sname like '_____';
模糊查詢必須使用like關鍵字。其中 “”匹配任意一個字母,5個“”表示5個任意字母。
3.2查詢姓名由5個字母構成,並且第5個字母爲“i”的學生記錄
select * from stu
where sname like '____i';
3.3查詢姓名以“z”開頭的學生記錄
select * from stu
where sname like 'z%';
其中“%”匹配0~n個任何字母。
3.4查詢姓名中第2個字母爲“i”的學生記錄
select * from stu
where sname like '_i%';
3.5查詢姓名中包含“a”字母的學生記錄
select * from stu
where sname like '%a%';
4字段控制查詢
4.1去除重複記錄
去除重複記錄(兩行或兩行以上記錄中系列的上的數據都相同),例如emp表中sal字段就存在相同的記錄。
當只查詢emp表的sal字段時,那麼會出現重複記錄,那麼想去除重複記錄,需要使用 distinct 明顯的,區別的:
select distinct sal from emp;
4.2查看僱員的月薪與佣金之和
因爲sal和comm兩列的類型都是數值類型,所以可以做加運算。如果sal或comm中有一個字段不是數值類型,那麼會出錯。
select *,sal+comm from emp;
comm列有很多記錄的值爲NULL,因爲任何東西與NULL相加結果還是NULL,所以結算結果可能會出現NULL。下面使用了把NULL轉換成數值0的函數ifnull:
select *,sal+IFNULL(comm,0) from emp;
4.3給列名添加別名
在上面查詢中出現列名爲sal+IFNULL(comm,0),這很不美觀,現在我們給這一列給出一個別名,爲total:
select *, sal+IFNULL(comm,0) as total from emp;
給列起別名時,是可以省略AS關鍵字的:複雜別名需要加單引號
5排序 order by 列名 asc(默認) desc
5.1查詢所有學生記錄,按年齡升序排序
select * from stu
order by sage asc;
或者
select * from stu
order by sage;
5.2查詢所有學生記錄,按年齡降序排序
select * from stu
order by sage desc;
5.3 查詢所有僱員,按月薪降序排序,如果月薪相同時,按編號升序排序
select * from emp
order by sal desc,empno asc;
6聚合函數 sum avg max min count
聚合函數是用來做縱向運算即字段運算的函數:
count():統計指定列不爲NULL的記錄行數;
max():計算指定列的最大值,如果指定列是字符串類型,那麼使用字符串排序運算;
min():計算指定列的最小值,如果指定列是字符串類型,那麼使用字符串排序運算;
sum():計算指定列的數值和,如果指定列類型不是數值類型,那麼計算結果爲0;
avg():計算指定列的平均值,如果指定列類型不是數值類型,那麼計算結果爲0;
6.1COUNT
當需要縱向統計時可以使用COUNT()。
查詢emp表中記錄數:
SELECT COUNT(*) AS cnt FROM emp;
查詢emp表中有佣金的人數:
SELECT COUNT(comm) cnt FROM emp;
注意,因爲count()函數中給出的是comm列,那麼只統計comm列非NULL的行數。
查詢emp表中月薪大於2500的人數:
SELECT COUNT(*) FROM emp
WHERE sal > 2500;
統計月薪與佣金之和大於2500元的人數:
SELECT COUNT(*) AS cnt FROM emp WHERE sal+IFNULL(comm,0) > 2500;
查詢有佣金的人數,有領導的人數:
SELECT COUNT(comm), COUNT(mgr) FROM emp;
6.2SUM和AVG
當需要縱向求和時使用sum()函數。
查詢所有僱員月薪和:
SELECT SUM(sal) FROM emp;
查詢所有僱員月薪和,以及所有僱員佣金和:
SELECT SUM(sal), SUM(comm) FROM emp;
查詢所有僱員月薪+佣金和:
SELECT SUM(sal+IFNULL(comm,0)) FROM emp;
統計所有員工平均工資:
SELECT AVG(sal) FROM emp;
6.3MAX和MIN
查詢最高工資和最低工資:
SELECT MAX(sal), MIN(sal) FROM emp;
7分組查詢
當需要分組查詢時需要使用GROUP BY子句,例如查詢每個部門的工資和,這說明要使用部門來分組。
注:凡和聚合函數同時出現的列名,一定要寫在group by 之後
7.1 分組查詢
查詢每個部門的部門編號和每個部門的工資和:
select deptno, SUM(sal) from emp
GROUP BY deptno;
查詢語句中有 組字段,sum函數,按組求和,是先查出所有的行再按組求和
查詢每個部門的部門編號以及每個部門的人數:
SELECT deptno,COUNT(*) FROM emp
GROUP BY deptno;
查詢每個部門的部門編號以及每個部門工資大於1500的人數:
SELECT deptno,COUNT(*) FROM emp
WHERE sal>1500
GROUP BY deptno;
7.2 HAVING子句-重點理解
查詢工資總和大於9000的部門編號以及工資和:
SELECT deptno, SUM(sal)
FROM emp
GROUP BY deptno
HAVING SUM(sal) > 9000;
注:having與where的區別:
1. having是在分組後對數據進行過濾.
where是在分組前對數據進行過濾
2 .having後面可以使用聚合函數(統計函數)
where後面不可以使用聚合函數。
WHERE是對分組前記錄的條件,如果某行記錄沒有滿足WHERE子句的條件,那麼這行記錄不會參加分組;而HAVING是對分組後數據的約束。</>
8LIMIT 方言
limit用來限定查詢結果的起始行,以及總行數。
8.1查詢5行記錄,起始行從0開始
SELECT * FROM emp LIMIT 0, 5;
注意,起始行從0開始,即第一行開始!
8.2查詢10行記錄,起始行從3開始
SELECT * FROM emp LIMIT 3, 10;
8.3分頁查詢
如果一頁記錄爲10條,希望查看第3頁記錄應該怎麼查呢?
第一頁記錄起始行爲0,一共查詢10行;
第二頁記錄起始行爲10,一共查詢10行;
第三頁記錄起始行爲20,一共查詢10行;
8.4查詢代碼的書寫順序和執行順序
查詢語句書寫順序:select – from- where- group by- having- order by-limit
查詢語句執行順序:from - where -group by - having - select - order by-limit
五、數據的完整性
作用:保證用戶輸入的數據保存到數據庫中是正確的。
確保數據的完整性 = 在創建表時給表中添加約束
完整性的分類:
實體完整性
域完整性
引用完整性
1、實體完整性
實體:即表中的一行(一條記錄)代表一個實體(entity)
實體完整性的作用:標識每一行數據不重複。
約束類型: 主鍵約束(primary key) 唯一約束(unique) 自動增長列(auto_increment)
1.1主鍵約束(primary key)
特點:數據唯一,且不能爲null
例:
第一種添加方式:
CREATE TABLE student(
Id int primary key,
Name varchar(50)
);
第二種添加方式:此種方式優勢在於,可以創建聯合主鍵
CREATE TABLE student(
id int,
Name varchar(50),
Primary key(id)
);
CREATE TABLE student(
id int,
Name varchar(50),
Primary key(id,name)
);
第三種添加方式:
CREATE TABLE student(
Id int,
Name varchar(50)
);
alter table student add primary key(id);
1.2唯一約束(unique):
CREATE TABLE student(
Id int primary key,
Name varchar(50) unique
);
1.3自動增長列(auto_increment)
給主鍵添加自動增長的數值,列只能是整數類型,但是如果刪除之前增長的序號,後面再添加的時候序號不會重新開始,而是會接着被刪除的那一列的序號
CREATE TABLE student(
Id int primary key auto_increment,
Name varchar(50)
);
INSERT INTO student(name) values(‘tom’);
2、域完整性
域完整性的作用:限制此單元格的數據正確,不對照此列的其它單元格比較
域代表當前單元格
域完整性約束:數據類型 非空約束(not null) 默認值約束(default)
Check約束(mysql不支持) check();
1.1 數據類型:(數值類型、日期類型、字符串類型)
1.2 非空約束:not null
CREATE TABLE student(
Id int pirmary key,
Name varchar(50) not null,
Sex varchar(10)
);
INSERT INTO student values(1,’tom’,null);
1.3 默認值約束 default
CREATE TABLE student(
Id int pirmary key,
Name varchar(50) not null,
Sex varchar(10) default ‘男’
);
insert into student1 values(1,'tom','女');
insert into student1 values(2,'jerry',default);
3、引用完整性(參照完整性)
要有外鍵必須先有主鍵,主鍵和外鍵的類型必須一致
外鍵約束:FOREIGN KEY
例:
CREATE TABLE student(
sid int pirmary key,
name varchar(50) not null,
sex varchar(10) default ‘男’
);
create table score(
id int,
score int,
sid int , -- 外鍵列的數據類型一定要與主鍵的類型一致
CONSTRAINT fk_score_sid foreign key (sid) references student(id)
);
constraint 約束
約束名稱(必須唯一) foreign key (本表的外鍵字段) references 主表(主鍵)
第二種添加外鍵方式。
ALTER TABLE score1 ADD CONSTRAINT fk_stu_score(約束名稱,必須唯一) FOREIGN KEY(sid) REFERENCES stu(id);
4、表與表之間的關係
一對一:例如t_person表和t_card表,即人和身份證。這種情況需要找出主從關係,即誰是主表,誰是從表。人可以沒有身份證,但身份證必須要有人才行,所以人是主表,而身份證是從表。設計從表可以有兩種方案:
在t_card表中添加外鍵列(相對t_user表),並且給外鍵添加唯一約束;
給t_card表的主鍵添加外鍵約束(相對t_user表),即t_card表的主鍵也是外鍵。
一對多(多對一):最爲常見的就是一對多!一對多和多對一,這是從哪個角度去看得出來的。t_user和t_section的關係,從t_user來看就是一對多,而從t_section的角度來看就是多對一!這種情況都是在多方創建外鍵!
多對多:例如t_stu和t_teacher表,即一個學生可以有多個老師,而一個老師也可以有多個學生。這種情況通常需要創建中間表來處理多對多關係。例如再創建一張表t_stu_tea表,給出兩個外鍵,一個相對t_stu表的外鍵,另一個相對t_teacher表的外鍵。
六、多表查詢(重要)
多表查詢有如下幾種:
合併結果集;union 、 union all
連接查詢
內連接 [inner] join on
外連接 outer join on
左外連接 left [outer] join
右外連接 right [outer] join
全外連接(MySQL不支持)full join
自然連接 natural join
子查詢
1 合併結果集
- 作用:合併結果集就是把兩個select語句的查詢結果合併到一起!
- 合併結果集有兩種方式:
UNION:去除重複記錄,例如:SELECT * FROM t1 UNION SELECT * FROM t2;
UNION ALL:不去除重複記錄,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。
要求:被合併的兩個結果:列數、列類型必須相同。
2、連接查詢 (非常重要)
連接查詢就是求出多個表的乘積,例如t1連接t2,那麼查詢出的結果就是t1*t2。
連接查詢會產生笛卡爾積,假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積爲{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以擴展到多個集合的情況。
那麼多表查詢產生這樣的結果並不是我們想要的,那麼怎麼去除重複的,不想要的記錄呢,當然是通過條件過濾。通常要查詢的多個表之間都存在關聯關係,那麼就通過關聯關係去除笛卡爾積。
你能想像到emp和dept表連接查詢的結果麼?emp一共14行記錄,dept表一共4行記錄,那麼連接後查詢出的結果是56行記錄。
也就你只是想在查詢emp表的同時,把每個員工的所在部門信息顯示出來,那麼就需要使用主外鍵來去除無用信息了。
使用主外鍵關係做爲條件來去除無用信息
select * from emp,dept where emp.deptno=dept.deptno;
上面查詢結果會把兩張表的所有列都查詢出來,也許你不需要那麼多列,這時就可以指定要查詢的列了。
SELECT emp.ename,emp.sal,emp.comm,dept.dname
FROM emp,dept
WHERE emp.deptno=dept.deptno;
還可以爲表指定別名,然後在引用列時使用別名即可。
SELECT e.ename,e.sal,e.comm,d.dname
FROM emp AS e,dept AS d
WHERE e.deptno=d.deptno;
2.1 內連接
上面的連接語句就是內連接,但它不是SQL標準中的查詢方式,可以理解爲方言!SQL標準的內連接爲:
SELECT *
FROM emp e
INNER JOIN dept d
ON e.deptno=d.deptno;
內連接的特點:查詢結果必須滿足條件。例如我們向emp表中插入一條記錄:
其中deptno爲50,而在dept表中只有10、20、30、40部門,那麼上面的查詢結果中就不會出現“張三”這條記錄,因爲它不能滿足e.deptno=d.deptno這個條件。
2.2 外連接(左連接、右連接)
外連接的特點:查詢出的結果存在不滿足條件的可能。
左外連接:
SELECT * FROM emp e
LEFT OUTER JOIN dept d
ON e.deptno=d.deptno;
左連接是先查詢出左表(即以左表爲主),然後查詢右表,右表中滿足條件的顯示出來,不滿足條件的顯示NULL。
這麼說你可能不太明白,我們還是用上面的例子來說明。其中emp表中“張三”這條記錄中,部門編號爲50,而dept表中不存在部門編號爲50的記錄,所以“張三”這條記錄,不能滿足e.deptno=d.deptno這條件。但在左連接中,因爲emp表是左表,所以左表中的記錄都會查詢出來,即“張三”這條記錄也會查出,但相應的右表部分顯示NULL。
右外連接
右連接就是先把右表中所有記錄都查詢出來,然後左表滿足條件的顯示,不滿足顯示NULL。
例如在dept表中的40部門並不存在員工,但在右連接中,如果dept表爲右表,那麼還是會查出40部門,但相應的員工信息爲NULL。
SELECT * FROM emp e
RIGHT OUTER JOIN dept d
ON e.deptno=d.deptno;
連接查詢心得:
連接不限與兩張表,連接查詢也可以是三張、四張,甚至N張表的連接查詢。通常連接查詢不可能需要整個笛卡爾積,而只是需要其中一部分,那麼這時就需要使用條件來去除不需要的記錄。這個條件大多數情況下都是使用主外鍵關係去除。
兩張表的連接查詢一定有一個主外鍵關係,三張表的連接查詢就一定有兩個主外鍵關係,
所以在大家不是很熟悉連接查詢時,首先要學會去除無用笛卡爾積,那麼就是用主外鍵關係作爲條件來處理。如果兩張表的查詢,那麼至少有一個主外鍵條件,三張表連接至少有兩個主外鍵條件。
3、自然連接
大家也都知道,連接查詢會產生無用笛卡爾積,我們通常使用主外鍵關係等式來去除它。而自然連接無需你去給出主外鍵等式,它會自動找到這一等式:
兩張連接的表中名稱和類型完全一致的列作爲條件,
例如emp和dept表都存在deptno列,並且類型一致,所以會被自然連接找到!
當然自然連接還有其他的查找條件的方式,但其他方式都可能存在問題!
SELECT * FROM emp NATURAL JOIN dept;
SELECT * FROM emp NATURAL LEFT JOIN dept;
SELECT * FROM emp NATURAL RIGHT JOIN dept;
4、子查詢(非常重要)
一個select語句中包含另一個完整的select語句。
子查詢就是嵌套查詢,即SELECT中包含SELECT,如果一條語句中存在兩個,或兩個以上SELECT,那麼就是子查詢語句了。
- 子查詢出現的位置:
where後,作爲條爲被查詢的一條件的一部分;
from後,作表; - 當子查詢出現在where後作爲條件時,還可以使用如下關鍵字:
any
all - 子查詢結果集的形式:
單行單列(用於條件)
單行多列(用於條件)
多行單列(用於條件)
多行多列(用於表)
練習:
1、工資高於JONES的員工。
分析:
查詢條件:工資>JONES工資,其中JONES工資需要一條子查詢。
第一步:查詢JONES的工資
SELECT sal FROM emp WHERE ename=‘JONES’
第二步:查詢高於甘寧工資的員工
SELECT * FROM emp WHERE sal > (${第一步})
結果:
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='JONES')
2、查詢與SCOTT同一個部門的員工。
子查詢作爲條件
子查詢形式爲單行單列
3、工資高於30號部門所有人的員工信息
分析:
SELECT * FROM emp WHERE sal>(SELECT MAX(sal) FROM emp WHERE deptno=30);
查詢條件:工資高於30部門所有人工資,其中30部門所有人工資是子查詢。高於所有需要使用all關鍵字。
第一步:查詢30部門所有人工資
SELECT sal FROM emp WHERE deptno=30;
第二步:查詢高於30部門所有人工資的員工信息
SELECT * FROM emp WHERE sal > ALL (${第一步})
結果:
SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30)
子查詢作爲條件
子查詢形式爲多行單列(當子查詢結果集形式爲多行單列時可以使用ALL或ANY關鍵字)
4、查詢工作和工資與MARTIN(馬丁)完全相同的員工信息
分析:
查詢條件:工作和工資與MARTIN完全相同,這是子查詢
第一步:查詢出MARTIN的工作和工資
SELECT job,sal FROM emp WHERE ename='MARTIN'
第二步:查詢出與MARTIN工作和工資相同的人
SELECT * FROM emp WHERE (job,sal) IN (${第一步})
結果:
SELECT * FROM emp WHERE (job,sal) IN (SELECT job,sal FROM emp WHERE ename='MARTIN')
5、有2個以上直接下屬的員工信息
SELECT * FROM emp WHERE empno IN(SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>=2);
子查詢作爲條件
子查詢形式爲單行多列
6、查詢員工編號爲7788的員工名稱、員工工資、部門名稱、部門地址
分析:(無需子查詢)
查詢列:員工名稱、員工工資、部門名稱、部門地址
查詢表:emp和dept,分析得出,不需要外連接(外連接的特性:某一行(或某些行)記錄上會出現一半有值,一半爲NULL值)
條件:員工編號爲7788
第一步:去除多表,只查一張表,這裏去除部門表,只查員工表
SELECT ename, sal FROM emp e WHERE empno=7788
第二步:讓第一步與dept做內連接查詢,添加主外鍵條件去除無用笛卡爾積
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, dept d
WHERE e.deptno=d.deptno AND empno=7788
第二步中的dept表表示所有行所有列的一張完整的表,這裏可以把dept替換成所有行,但只有dname和loc列的表,這需要子查詢。
第三步:查詢dept表中dname和loc兩列,因爲deptno會被作爲條件,用來去除無用笛卡爾積,所以需要查詢它。
SELECT dname,loc,deptno FROM dept;
第四步:替換第二步中的dept
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, (SELECT dname,loc,deptno FROM dept) d
WHERE e.deptno=d.deptno AND e.empno=7788
子查詢作爲表
子查詢形式爲多行多列
5、自連接:自己連接自己,起別名
求7369員工編號、姓名、經理編號和經理姓名
SELECT e1.empno , e1.ename,e2.mgr,e2.ename
FROM emp e1, emp e2
WHERE e1.mgr = e2.empno AND e1.empno = 7369;
練習:
求各個部門薪水最高的員工所有信息
select e.* from emp e,
–部門最高工資
(select max(sal) maxsal,deptno from emp
group by deptno) a
where e.deptno = a.deptno
and e.sal =a.maxsal
七、MySQL中的函數
一、數學函數
ABS(x) 返回x的絕對值
BIN(x) 返回x的二進制(OCT返回八進制,HEX返回十六進制)
CEILING(x) 返回大於x的最小整數值
EXP(x) 返回值e(自然對數的底)的x次方
FLOOR(x) 返回小於x的最大整數值
GREATEST(x1,x2,...,xn)返回集合中最大的值
LEAST(x1,x2,...,xn) 返回集合中最小的值
LN(x) 返回x的自然對數
LOG(x,y)返回x的以y爲底的對數
MOD(x,y) 返回x/y的模(餘數)
PI()返回pi的值(圓周率)
RAND()返回0到1內的隨機值,可以通過提供一個參數(種子)使RAND()隨機數生成器生成一個指定的值。
ROUND(x,y)返回參數x的四捨五入的有y位小數的值
SIGN(x) 返回代表數字x的符號的值
SQRT(x) 返回一個數的平方根
TRUNCATE(x,y) 返回數字x截短爲y位小數的結果
二、聚合函數(常用於GROUP BY從句的SELECT查詢中)
AVG(col)返回指定列的平均值
COUNT(col)返回指定列中非NULL值的個數
MIN(col)返回指定列的最小值
MAX(col)返回指定列的最大值
SUM(col)返回指定列的所有值之和
GROUP_CONCAT(col) 返回由屬於一組的列值連接組合而成的結果
三、字符串函數
ASCII(char)返回字符的ASCII碼值
BIT_LENGTH(str)返回字符串的比特長度
CONCAT(s1,s2...,sn)將s1,s2...,sn連接成字符串
CONCAT_WS(sep,s1,s2...,sn)將s1,s2...,sn連接成字符串,並用sep字符間隔
INSERT(str,x,y,instr) 將字符串str從第x位置開始,y個字符長的子串替換爲字符串instr,返回結果
FIND_IN_SET(str,list)分析逗號分隔的list列表,如果發現str,返回str在list中的位置
LCASE(str)或LOWER(str) 返回將字符串str中所有字符改變爲小寫後的結果
LEFT(str,x)返回字符串str中最左邊的x個字符
LENGTH(s)返回字符串str中的字符數
LTRIM(str) 從字符串str中切掉開頭的空格
POSITION(substr,str) 返回子串substr在字符串str中第一次出現的位置
QUOTE(str) 用反斜槓轉義str中的單引號
REPEAT(str,srchstr,rplcstr)返回字符串str重複x次的結果
REVERSE(str) 返回顛倒字符串str的結果
RIGHT(str,x) 返回字符串str中最右邊的x個字符
RTRIM(str) 返回字符串str尾部的空格
STRCMP(s1,s2)比較字符串s1和s2
TRIM(str)去除字符串首部和尾部的所有空格
UCASE(str)或UPPER(str) 返回將字符串str中所有字符轉變爲大寫後的結果
四、日期和時間函數
CURDATE()或CURRENT_DATE() 返回當前的日期
CURTIME()或CURRENT_TIME() 返回當前的時間
DATE_ADD(date,INTERVAL int keyword)返回日期date加上間隔時間int的結果(int必須按照關鍵字進行格式化),如:SELECTDATE_ADD(CURRENT_DATE,INTERVAL 6 MONTH);
DATE_FORMAT(date,fmt) 依照指定的fmt格式格式化日期date值
DATE_SUB(date,INTERVAL int keyword)返回日期date加上間隔時間int的結果(int必須按照關鍵字進行格式化),如:SELECTDATE_SUB(CURRENT_DATE,INTERVAL 6 MONTH);
DAYOFWEEK(date) 返回date所代表的一星期中的第幾天(1~7)
DAYOFMONTH(date) 返回date是一個月的第幾天(1~31)
DAYOFYEAR(date) 返回date是一年的第幾天(1~366)
DAYNAME(date) 返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE);
FROM_UNIXTIME(ts,fmt) 根據指定的fmt格式,格式化UNIX時間戳ts
HOUR(time) 返回time的小時值(0~23)
MINUTE(time) 返回time的分鐘值(0~59)
MONTH(date) 返回date的月份值(1~12)
MONTHNAME(date) 返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE);
NOW() 返回當前的日期和時間
QUARTER(date) 返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE);
WEEK(date) 返回日期date爲一年中第幾周(0~53)
YEAR(date) 返回日期date的年份(1000~9999)
一些示例:
獲取當前系統時間:
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP());
SELECT EXTRACT(YEAR_MONTH FROM CURRENT_DATE);
SELECT EXTRACT(DAY_SECOND FROM CURRENT_DATE);
SELECT EXTRACT(HOUR_MINUTE FROM CURRENT_DATE);
返回兩個日期值之間的差值(月數):
SELECT PERIOD_DIFF(200302,199802);
在Mysql中計算年齡:
SELECT DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(birthday)),'%Y')+0 AS age FROM employee;
這樣,如果Brithday是未來的年月日的話,計算結果爲0。
下面的SQL語句計算員工的絕對年齡,即當Birthday是未來的日期時,將得到負值。
SELECT DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(birthday, '%Y') -(DATE_FORMAT(NOW(), '00-%m-%d') <DATE_FORMAT(birthday, '00-%m-%d')) AS age from employee
五、加密函數
AES_ENCRYPT(str,key) 返回用密鑰key對字符串str利用高級加密標準算法加密後的結果,調用AES_ENCRYPT的結果是一個二進制字符串,以BLOB類型存儲
AES_DECRYPT(str,key) 返回用密鑰key對字符串str利用高級加密標準算法解密後的結果
DECODE(str,key) 使用key作爲密鑰解密加密字符串str
ENCRYPT(str,salt) 使用UNIXcrypt()函數,用關鍵詞salt(一個可以惟一確定口令的字符串,就像鑰匙一樣)加密字符串str
ENCODE(str,key) 使用key作爲密鑰加密字符串str,調用ENCODE()的結果是一個二進制字符串,它以BLOB類型存儲
MD5() 計算字符串str的MD5校驗和
PASSWORD(str) 返回字符串str的加密版本,這個加密過程是不可逆轉的,和UNIX密碼加密過程使用不同的算法。
SHA() 計算字符串str的安全散列算法(SHA)校驗和
示例:
複製代碼 代碼如下:
SELECT ENCRYPT('root','salt');
SELECT ENCODE('xufeng','key');
SELECT DECODE(ENCODE('xufeng','key'),'key');#加解密放在一起
SELECT AES_ENCRYPT('root','key');
SELECT AES_DECRYPT(AES_ENCRYPT('root','key'),'key');
SELECT MD5('123456');
SELECT SHA('123456');
六、控制流函數
MySQL有4個函數是用來進行條件操作的,這些函數可以實現SQL的條件邏輯,允許開發者將一些應用程序業務邏輯轉換到數據庫後臺。
MySQL控制流函數:
CASE WHEN[test1] THEN [result1]...ELSE [default] END如果testN是真,則返回resultN,否則返回default
CASE [test] WHEN[val1] THEN [result]...ELSE [default]END 如果test和valN相等,則返回resultN,否則返回default
IF(test,t,f) 如果test是真,返回t;否則返回f
IFNULL(arg1,arg2) 如果arg1不是空,返回arg1,否則返回arg2
NULLIF(arg1,arg2) 如果arg1=arg2返回NULL;否則返回arg1
這些函數的第一個是IFNULL(),它有兩個參數,並且對第一個參數進行判斷。如果第一個參數不是NULL,函數就會向調用者返回第一個參數;如果是NULL,將返回第二個參數。
如:
SELECT IFNULL(1,2), IFNULL(NULL,10),IFNULL(4*NULL,'false');
NULLIF()函數將會檢驗提供的兩個參數是否相等,如果相等,則返回NULL,如果不相等,就返回第一個參數。
如:
SELECT NULLIF(1,1),NULLIF('A','B'),NULLIF(2+3,4+1);
和許多腳本語言提供的IF()函數一樣,MySQL的IF()函數也可以建立一個簡單的條件測試,這個函數有三個參數,第一個是要被判斷的表達式,如果表達式爲真,IF()將會返回第二個參數,如果爲假,IF()將會返回第三個參數。
如:
SELECTIF(1<10,2,3),IF(56>100,'true','false');
IF()函數在只有兩種可能結果時才適合使用。然而,在現實世界中,我們可能發現在條件測試中會需要多個分支。在這種情況下,MySQL提供了CASE函數,它和PHP及Perl語言的switch-case條件例程一樣。
CASE函數的格式有些複雜,通常如下所示:
複製代碼 代碼如下:
CASE [expression to be evaluated]
WHEN [val 1] THEN [result 1]
WHEN [val 2] THEN [result 2]
WHEN [val 3] THEN [result 3]
......
WHEN [val n] THEN [result n]
ELSE [default result]
END
這裏,第一個參數是要被判斷的值或表達式,接下來的是一系列的WHEN-THEN塊,每一塊的第一個參數指定要比較的值,如果爲真,就返回結果。所有的WHEN-THEN塊將以ELSE塊結束,當END結束了所有外部的CASE塊時,如果前面的每一個塊都不匹配就會返回ELSE塊指定的默認結果。如果沒有指定ELSE塊,而且所有的WHEN-THEN比較都不是真,MySQL將會返回NULL。
CASE函數還有另外一種句法,有時使用起來非常方便,如下:
CASE
複製代碼 代碼如下:
WHEN [conditional test 1] THEN [result 1]
WHEN [conditional test 2] THEN [result 2]
ELSE [default result]
END
這種條件下,返回的結果取決於相應的條件測試是否爲真。
示例:
複製代碼 代碼如下:
mysql>SELECT CASE 'green'
WHEN 'red' THEN 'stop'
WHEN 'green' THEN 'go' END;
SELECT CASE 9 WHEN 1 THEN 'a' WHEN 2 THEN 'b' ELSE 'N/A' END;
SELECT CASE WHEN (2+2)=4 THEN 'OK' WHEN(2+2)<>4 THEN 'not OK' END ASSTATUS;
SELECT Name,IF((IsActive = 1),'已激活','未激活') AS RESULT FROMUserLoginInfo;
SELECT fname,lname,(math+sci+lit) AS total,
CASE WHEN (math+sci+lit) < 50 THEN 'D'
WHEN (math+sci+lit) BETWEEN 50 AND 150 THEN 'C'
WHEN (math+sci+lit) BETWEEN 151 AND 250 THEN 'B'
ELSE 'A' END
AS grade FROM marks;
SELECT IF(ENCRYPT('sue','ts')=upass,'allow','deny') AS LoginResultFROM users WHERE uname = 'sue';#一個登陸驗證
七、格式化函數
DATE_FORMAT(date,fmt) 依照字符串fmt格式化日期date值
FORMAT(x,y) 把x格式化爲以逗號隔開的數字序列,y是結果的小數位數
INET_ATON(ip) 返回IP地址的數字表示
INET_NTOA(num) 返回數字所代表的IP地址
TIME_FORMAT(time,fmt) 依照字符串fmt格式化時間time值
其中最簡單的是FORMAT()函數,它可以把大的數值格式化爲以逗號間隔的易讀的序列。
示例:
複製代碼 代碼如下:
SELECT FORMAT(34234.34323432,3);
SELECT DATE_FORMAT(NOW(),'%W,%D %M %Y %r');
SELECT DATE_FORMAT(NOW(),'%Y-%m-%d');
SELECT DATE_FORMAT(19990330,'%Y-%m-%d');
SELECT DATE_FORMAT(NOW(),'%h:%i %p');
SELECT INET_ATON('10.122.89.47');
SELECT INET_NTOA(175790383);
八、類型轉化函數
爲了進行數據類型轉化,MySQL提供了CAST()函數,它可以把一個值轉化爲指定的數據類型。類型有:
BINARY,CHAR,DATE,TIME,DATETIME,SIGNED,UNSIGNED
示例:
複製代碼 代碼如下:
SELECT CAST(NOW() AS SIGNED INTEGER),CURDATE()+0;
SELECT 'f'=BINARY 'F','f'=CAST('F' AS BINARY);
九、系統信息函數
DATABASE() 返回當前數據庫名
BENCHMARK(count,expr) 將表達式expr重複運行count次
CONNECTION_ID() 返回當前客戶的連接ID
FOUND_ROWS() 返回最後一個SELECT查詢進行檢索的總行數
USER()或SYSTEM_USER() 返回當前登陸用戶名
VERSION() 返回MySQL服務器的版本
示例:
複製代碼 代碼如下:
SELECT DATABASE(),VERSION(),USER();
SELECTBENCHMARK(9999999,LOG(RAND()*PI()));#該例中,MySQL計算LOG(RAND()*PI())表達式9999999次。
八、MySQL數據庫的備份與恢復
1生成SQL腳本 導出數據
在控制檯使用mysqldump
命令可以用來生成指定數據庫的腳本文本,
但要注意,腳本文本中只包含數據庫的內容,而不會存在創建數據庫的語句!所以在恢復數據時,還需要自已手動創建一個數據庫之後再去恢復數據。
mysqldump –u用戶名 –p密碼 數據庫名>生成的腳本文件路徑
mysqldump -uroot -p321210 db_news>C:\Users\fish>my.sql
現在可以在C盤下找到mydb1.sql文件了!
注意,mysqldump命令是在Windows控制檯下執行,無需登錄mysql!!!
2執行SQL腳本 恢復數據
前提:必須先創建數據庫名
執行SQL腳本需要登錄mysql,然後進入指定數據庫,纔可以執行SQL腳本!!!
執行SQL腳本不只是用來恢復數據庫,也可以在平時編寫SQL腳本,然後使用執行SQL 腳本來操作數據庫!大家都知道,在黑屏下編寫SQL語句時,就算發現了錯誤,可能也不能修改了。所以我建議大家使用腳本文件來編寫SQL代碼,然後執行之!
SOURCE C:\mydb1.sql
注意,在執行腳本時需要先行覈查當前數據庫中的表是否與腳本文件中的語句有衝突!例如在腳本文件中存在create table a的語句,而當前數據庫中已經存在了a表,那麼就會出錯!
還可以通過下面的方式來執行腳本文件:
mysql -uroot -p123 mydb1<c:\mydb1.sql
mysql –u用戶名 –p密碼 數據庫<要執行腳本文件路徑
source C:\Users\fish\my.sql
這種方式無需登錄mysql!
注意:在CMD下 命令不能加;