一, Sql的分類
1,DDL(Data Definition Language):數據定義語言,用來定義數據庫對象:庫、表、列等; CREATE、 ALTER、DROP
2,DML(Data Manipulation Language):數據操作語言,用來定義數據庫記錄(數,據); INSERT、 UPDATE、 DELETE
3,DCL(Data Control Language):數據控制語言,用來定義訪問權限和安全級別;
4,DQL(Data Query Language):數據查詢語言,用來查詢記錄(數據)。
SELECT
- 注意:sql語句以;結尾
二,DDL:操作數據庫、表、列等
使用的關鍵字:CREATE、 ALTER、 DROP
1,操作數據庫
1,創建
create database 數庫庫名;//創建數據庫
Create database mysql02 character set gbk;//創建數據庫並輸入類型爲gbk
Create database mysql03 character set gbk COLLATE gbk_chinese_ci;
2,查詢
1,查看當前數據庫服務器中的所有數據庫
show databases;
2,查看前面創建的數據庫的定義信息,,
Show create database mysq01;
3,刪除前面創建的數據庫
Drop database數庫庫名;
3,修改
1, 查看服務器中的數據庫,並把mydb2的字符集修改爲utf8;
alter database mysql02 character set utf8;
4,刪除
drop database mydb3;
5,其他
1,查看當前使用的數據庫
select database();
2,切換數據庫
use mydb2;
2,操作數據表
1,創建表
create table 表名(
字段1 字段類型,
字段2 字段類型,
...
字段n 字段類型
);
2,常用數據類型
(1)int:整型
(2) double:浮點型,例如double(5,2)表示最多5位,其中必須有2位小數,即最大值爲999.99;
(3) char:固定長度字符串類型; char(10) 'abc ’
(4) varchar:可變長度字符串類型;varchar(10) ‘abc’
(5) text:字符串類型;
(6) blob:字節類型;
(7) date:日期類型,格式爲:yyyy-MM-dd;
(8)time:時間類型,格式爲:hh:mm:ss
(9) timestamp:時間戳類型 yyyy-MM-dd hh:mm:ss 會自動賦值
(10)datetime:日期時間類型 yyyy-MM-dd hh:mm:ss
3,創建一個員工表
顯示當前數據庫中的所有表
SHOW TABLES;
查看錶的字段信息
DESC 表名;
在上面員工表的基本上增加一列。
ALTER TABLE 表名 ADD 字段名 字段類型;
修改列,使其長度爲60。
ALTER TABLE 表名 MODIFY字段名varchar(60);
刪除列,一次只能刪一列。
ALTER TABLE 表名 DROP字段名;
表名修改。
RENAME TABLE 表名 TO 新表名;
查看錶格的創建細節
SHOW CREATE TABLE 表;
修改表的字符集爲gbk
ALTER TABLE 表名 CHARACTER SET gbk;
列名修改
ALTER TABLE 表名 CHANGE 列名 新列名 數據類型;
4,刪除表
DROP TABLE 表名;
三,DML操作
查詢表中的所有數據
SELECT * FROM 表名;
DML是對錶中的數據進行增、刪、改的操作。不要與DDL混淆了。
INSERT 、UPDATE、 DELETE
小知識:
在mysql中,字符串類型和日期類型都要用單引號括起來。‘tom’ ‘2015-09-04’
空值:null
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);
2,修改操作 UPDATE
語法:
UPDATE 表名 SET 列名1=列值1,列名2=列值2 。。。 WHERE 列名=值
練習:
(1)將所有員工薪水修改爲5000元。
UPDATE emp SET salary=5000
(2)將姓名爲’zs’的員工薪水修改爲3000元。
UPDATE emp SET salary=3000 WHERE name=’ zhangsan’;
(3)將姓名爲’aaa’的員工薪水修改爲4000元,job改爲ccc。
UPDATE emp SET salary=4000,gender='female' WHERE name='lisi';
(4)將wu的薪水在原有基礎上增加1000元。
UPDATE emp SET salary=salary+1000 WHERE gender='male';
3 ,刪除操作 DELETE
語法 :
DELETE FROM 表名 【WHERE 列名=值】
練習 :
(1)刪除表中名稱爲’zs’的記錄。
DELETE FROM emp WHERE name=‘zs’;
(2)刪除表中所有記錄。
DELETE FROM emp;
(3)使用truncate刪除表中記錄。
TRUNCATE TABLE emp;
注:
DELETE 刪除表中的數據,表結構還在;刪除後的數據可以找回
TRUNCATE 刪除是把表直接DROP掉,然後再創建一個同樣的新表。刪除的數據不能找回。執行速度比DELETE快。
四, DQL操作
DQL數據查詢語言 (重要)
數據庫執行DQL語句不會對數據進行改變,而是讓數據庫發送結果集給客戶端。
查詢返回的結果集是一張虛擬表。
查詢關鍵字:SELECT
語法:
SELECT selection_list //要查詢的列名稱
FROM table_list //要查詢的表名稱
WHERE condition //行條件
GROUP BY grouping_columns //對結果分組
HAVING condition //分組後的行條件
ORDER BY sorting_columns //對結果分組
LIMIT offset_start, row_count //結果限定
練習
1 基礎查詢
1.1 查詢所有列
SELECT * FROM stu;
1.2 查詢指定列
SELECT sid, sname, age FROM stu;
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 age<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關鍵字的:
SELECT *,sal+IFNULL(comm,0) total FROM emp;
也可以給emp添加別名
SELECT SUM(e.sal+IFNULL(e.coom,0)) total FROM emp e;
SELECT e.* FROM emp e;
SELECT emp.empno,emp.job FROM emp;
這句話是有問題的:
SELECT emp.empno,a.job FROM emp a; //取過別名後不能再用原表名。
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 age 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.1 COUNT
當需要縱向統計時可以使用COUNT()。
(1) 查詢emp表中記錄數:
SELECT COUNT(*) AS cnt FROM emp;
(2) 查詢emp表中有佣金的人數:
SELECT COUNT(comm) cnt FROM emp;
注意,因爲count()函數中給出的是comm列,那麼只統計comm列非NULL的行數。
(3)查詢emp表中月薪大於2500的人數:
SELECT COUNT(*) FROM emp
WHERE sal > 2500;
(4)統計月薪與佣金之和大於2500元的人數:
SELECT COUNT(*) AS cnt FROM emp WHERE sal+IFNULL(comm,0) > 2500;
(5) 查詢有佣金的人數,有領導的人數:
SELECT COUNT(comm), COUNT(mgr) FROM emp;
6.2 SUM和AVG
當需要縱向求和時使用sum()函數。
(1)查詢所有僱員月薪和:
SELECT SUM(sal) FROM emp;
(2)查詢所有僱員月薪和,以及所有僱員佣金和:
SELECT SUM(sal), SUM(comm) FROM emp;
(3) 查詢所有僱員月薪+佣金和:
SELECT SUM(sal+IFNULL(comm,0)) FROM emp;
(4) 統計所有員工平均工資:
SELECT AVG(sal) FROM emp;
6.3 MAX和MIN
(1)查詢最高工資和最低工資:
SELECT MAX(sal), MIN(sal) FROM emp;
7 分組查詢
當需要分組查詢時需要使用GROUP BY子句,例如查詢每個部門的工資和,這說明要使用部門來分組。
注:凡和聚合函數同時出現的列名,一定要寫在group by 之後
7.1 分組查詢
(1) 查詢每個部門的部門編號和每個部門的工資和:
SELECT deptno, SUM(sal)
FROM emp
GROUP BY deptno
(2)查詢每個部門的部門編號以及每個部門的人數:
SELECT deptno,COUNT(*)
FROM emp
GROUP BY deptno;
(3)查詢每個部門的部門編號以及每個部門工資大於1500的人數:
SELECT deptno,COUNT(*)
FROM emp
WHERE sal>1500
GROUP BY deptno;
7.2 HAVING子句
(1) 查詢工資總和大於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是對分組後數據的約束。
**8 LIMIT **
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行;
Int curPage //當前頁
Int pageSize //每頁共顯示多少條數據
pageCont //總頁數
select * from emp limit ((curpage-1)*pagesize,pagesize);
//例如,查詢第三頁的數據,則Int curPage=3
8.3 查詢代碼的書寫順序和執行順序
查詢語句書寫順序: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(
classid int,
stuid int,
name varchar(50),
primary key(classid,stuid)
);
第三種添加方式:
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)
sqlserver數據庫 (identity) oracle數據庫( sequence)
給主鍵添加自動增長的數值,列只能是整數類型
create table( id int(10) auto_increment primary key) auto_increment=1
2、域完整性
域完整性的作用:限制此單元格的數據正確,不對照此列的其它單元格比較
域代表當前單元格
域完整性約束:數據類型 非空約束(not null) 默認值約束(default)
check約束(mysql不支持)check(sex=‘男’ or sex=‘女’)
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)
);
第二種添加外鍵方式。
ALTER TABLE score1 ADD CONSTRAINT fk_stu_score FOREIGN KEY(sid) REFERENCES stu(id);
4、 表與表之間的關係
(1)一對一:例如t_person表和t_card表,即人和身份證。這種情況需要找出主從關係,即誰是主表,誰是從表。人可以沒有身份證,但身份證必須要有人才行,所以人是主表,而身份證是從表。設計從表可以有兩種方案:
在t_card表中添加外鍵列(相對t_user表),並且給外鍵添加唯一約束;
給t_card表的主鍵添加外鍵約束(相對t_user表),即t_card表的主鍵也是外鍵。
(2) 一對多(多對一):最爲常見的就是一對多!一對多和多對一,這是從哪個角度去看得出來的。t_user和t_section的關係,從t_user來看就是一對多,而從t_section的角度來看就是多對一!這種情況都是在多方創建外鍵!
(3)多對多:例如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 合併結果集
(1) 作用:合併結果集就是把兩個select語句的查詢結果合併到一起!
(2)合併結果集有兩種方式:
UNION:去除重複記錄,例如:
SELECT * FROM t1 UNION SELECT * FROM t2;
UNION ALL:不去除重複記錄,例如:
SELECT * FROM t1 UNION ALL SELECT * FROM t2。
(3) 要求:被合併的兩個結果:列數、列類型必須相同。
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表的同時,把每個員工的所在部門信息顯示出來,那麼就需要使用主外鍵來去除無用信息了。
(1)使用主外鍵關係做爲條件來去除無用信息
SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;
(2)上面查詢結果會把兩張表的所有列都查詢出來,也許你不需要那麼多列,這時就可以指定要查詢的列了。
SELECT emp.ename,emp.sal,emp.comm,dept.dname
FROM emp,dept
WHERE emp.deptno=dept.deptno;
(3)還可以爲表指定別名,然後在引用列時使用別名即可。
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。
2.3 右連接
右連接就是先把右表中所有記錄都查詢出來,然後左表滿足條件的顯示,不滿足顯示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')
SELECT * FROM emp WHERE job=(select job from emp where enmae='MARTIN')and sal=(select
sal from emp where enmae='MARTIN')
5、有2個以上直接下屬的員工信息
SELECT * FROM emp WHERE empno IN(
SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>=2);
子查詢作爲條件
子查詢形式爲單行多列
5、查詢員工編號爲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
子查詢作爲表
子查詢形式爲多行多列
6、自連接:自己連接自己,起別名
求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
七、視圖
– 是由來自數據庫中的一個或多個表或多個表的字段所組成的一個虛擬的表。
CREATE OR REPLACE VIEW v_name
AS
SELECT * FROM emp e;
八、索引(index)
用來快速定位查找對應記錄的
數據庫表中的字節段沒有索引則查詢時按照FTS(full table Scan)查
以高水位線進行全表掃描
索引倚靠rowid來實現快速定位一條記錄
1.數據庫默認創建索引
表的主鍵,唯一鍵會自動創建索引
自定義索引字段
create index index_ename on emp(ename);
適合建立索引的情況
1.頻繁查詢的字段
2.經常作爲查詢條件的字段
3.數據集比較大,查詢的結果小
4.連接查詢的連接字段
不適合建立索引的情況;
1.使用不頻繁的字段
2.經常更新的字段
3.數據集比較大,查詢結果大
索引失效
1.索引字段使用函數,導致索引失效
2.索引字段進行運算
3.使用like關鍵字查詢
刪除索引
DROP INDEX index_name ON talbe_name
ALTER TABLE table_name DROP INDEX index_name
九、MySQL中的函數
時間日期相關函數
ADDTIME (date2 ,time_interval ) 將time_interval加到date2
CURRENT_DATE ( ) 當前日期
CURRENT_TIME ( ) 當前時間
CURRENT_TIMESTAMP ( ) 當前時間戳
DATE (datetime ) 返回datetime的日期部分
DATE_ADD (date2 , INTERVAL d_value d_type ) 在date2中加上日期或時間
DATE_SUB (date2 , INTERVAL d_value d_type ) 在date2上減去一個時間
DATEDIFF (date1 ,date2 ) 兩個日期差
NOW ( ) 當前時間
YEAR|Month|Day(datetime ) 年月日
字符串相關函數
CHARSET(str) 返回字串字符集
CONCAT (string2 [,… ]) 連接字串
INSTR (string ,substring ) 返回substring在string中出現的位置,沒有返回0
UCASE (string2 ) 轉換成大寫
LCASE (string2 ) 轉換成小寫
LEFT (string2 ,length ) 從string2中的左邊起取length個字符
LENGTH (string ) string長度
REPLACE (str ,search_str ,replace_str ) 在str中用replace_str替換search_str
STRCMP (string1 ,string2 ) 逐字符比較兩字串大小,
SUBSTRING (str , position [,length ]) 從str的position開始,取length個字符
LTRIM (string2 ) RTRIM (string2 ) trim 去除前端空格或後端空格
數學相關函數
ABS (number2 ) 絕對值
BIN (decimal_number ) 十進制轉二進制
CEILING (number2 ) 向上取整
CONV(number2,from_base,to_base) 進制轉換
FLOOR (number2 ) 向下取整
FORMAT (number,decimal_places ) 保留小數位數
HEX (DecimalNumber ) 轉十六進制
LEAST (number , number2 [,…]) 求最小值
MOD (numerator ,denominator ) 求餘
RAND([seed]) RAND([seed])
十、MySQL數據庫的備份與恢復
1 生成SQL腳本 導出數據
在控制檯使用mysqldump命令可以用來生成指定數據庫的腳本文本,但要注意,腳本文本中只包含數據庫的內容,而不會存在創建數據庫的語句!所以在恢復數據時,還需要自已手動創建一個數據庫之後再去恢復數據。
mysqldump –u用戶名 –p密碼 數據庫名>生成的腳本文件路徑
現在可以在C盤下找到mydb1.sql文件了!
mysqldump -uroot -p123 mysql04> d:mysql04.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密碼 數據庫<要執行腳本文件路徑
mysql -uroot -p123 stumanage<F:\stumanage.sql
這種方式無需登錄mysql!
注意:在CMD下 命令不能加;