mysql資料庫筆記
sql筆記
資料庫定義
【資料庫】
儲存資料的倉庫
本質:檔案系統加伺服器
常見資料庫產品:
mysql
oracle
sql server
sqlite
db2
庫 - 資料夾 , 存放的是表
表 - 檔案, 存放的是真正的資料
【SQL】
結構化查詢語言
相當於資料庫中的“普通話”
每種資料庫可能會有自己特殊的命令 - "方言"
1. DDL: 資料定義語言, 建表建庫
2. DML: 資料操縱語言, 增刪改,
- DQL 查
3. DCL: 資料控制語言, 新增使用者 賦予許可權
【操作】
桌面執行mysql方法
修改環境變數,path的值後面加’;’加mysql.exe的父目錄
桌面shift+右鍵在當前介面執行cmd
1. 進入
mysql -u root -p
Password:
2. 檢視庫
show databases;
3. 建庫
create database bwf;
4. 使用庫
use bwf;
5. 檢視庫中的表
show tables;
6. 建表
學生表
student
id name age
create table student(
id INT PRIMARY KEY AUTO_INCREMENT,
name varchar(20) NOT NULL,
age INT NOT NULL DEFAULT 18);
DDL(資料庫定義語言)
建表
id name age
Drop talbe if esists student
create table student(
id INT PRIMARY KEY AUTO_INCREMENT,
name varchar(20) NOT NULL,
age INT NOT NULL DEFAULT 18);
新增外來鍵約束
constraint fk_uid foreign key (欄位) references 外來鍵的表(外來鍵表的欄位)
新增聯合主鍵約束
PRIMARY KEY (欄位1,欄位2)
刪除表
DROP TABLE student;
修改表
增加欄位(整數)
ALTER TABLE student ADD height INT;
修改欄位(浮點數)
ALTER TABLE student MODIFY height DOUBLE;
修改欄位(欄位名,浮點數)
ALTER TABLE student CHANGE height DOUBLE;
刪除欄位
ALTER TABLE student DROP COLUMN height;
索引
1. 提高查詢效率的資料庫物件
2. 通過關聯關鍵字的方式提高查詢效率(類似於書的目錄)
3. 資料庫會自動為主鍵和唯一列新增索引
什麼時候適合使用索引呢?
1. 經常出現在where子句中的欄位
2. 經常出現在group by子句中的欄位
3. 重複值很少的欄位
什麼時候不適合用索引呢
1. 重複值很多的欄位
2. 很大的欄位
操作:
提高查詢效率 -> 從效率瓶頸出發
減少磁碟讀取的次數 -> B樹
查詢18歲的學生
select *
from student
where age='18';
根據年齡建立索引
create index index_age
on student(age);
刪除索引
drop index index_age
on student;
DML(資料庫操縱語言)
增
插入 1, 張三, 18 注意: 字串和日期時間 必須加上 ''
插入完整記錄
INSERT INTO student VALUES (1, '張三', 18);
插入部分記錄
INSERT INTO student (name, age) VALUES ('張三', 18);
插入多條完整記錄
INSERT INTO student VALUES (3, '李四', 19),(4, '王武', 28),(5, '趙柳', 39);
刪(不做)
全部刪除
DELETE FROM student;
刪除部分(條件)
DELETE FROM student WHERE id > 3;
改
UPDATE student SET age=18;
大於20歲的人全部改回20歲
UPDATE student SET age = 20 WHERE age > 20;
DQL(資料查詢語言)
查
查詢所有的列
SELECT * FROM student;
SELECT id, name FROM student;
查看錶結構
DESC student;
SHOW CREATE TABLE student;
結果:
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`age` int(11) NOT NULL DEFAULT '18',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
引擎:預設innodb,預設字符集為utf-8,一個漢字佔3個位元組,gbk佔2個位元組
【函式】
【數學函式】
求絕對值
SELECT ABS(-5);
求比這個數大的最小整數
SELECT CEILING(-6.1);
SELECT CEIL(-6.1);
求比這個數小的最大整數
SELECT FLOOR(-6.1);
求最大值
SELECT GREATEST(100,5,13);
求最小值
SELECT LEAST(5,3,7);
求模 %
SELECT MOD(10, 6);
四捨五入
SELECT ROUND(10.5);
SELECT ROUND(10.516, 2);
截斷
SELECT TRUNCATE(10.51999, 2);
求隨機數
SELECT RAND();
SELECT RAND(5);
求平方根
SELECT SQRT(100);
【字串函式】
字串長度
SELECT LENGTH('hello');
SELECT LENGTH('你好');
Utf-8編碼格式,一個漢字佔3個位元組
全部小寫
SELECT LCASE('hELlo');
SELECT LOWER('hELlo');
全部大寫
SELECT UCASE('hELlo');
SELECT UPPER('hELlo');
子串位置 - MYSQL中索引從1開始
SELECT POSITION('a' IN 'java');
替換
SELECT REPLACE('yesy','y','hh');
插入 - 從第2個位置開始的1個字元 替換成 xx
SELECT INSERT ('hello', 2, 1, 'xx');
拼接 -
SELECT CONCAT('hello','my','sql');
間隔符拼接
SELECT CONCAT_WS(',', 'hello','my','sql');
取左邊的字元
SELECT LEFT('hello', 3);
取右邊的字元
SELECT RIGHT('hello', 3);
往左邊填充字元
SELECT LPAD('hello',10,'x');
往右邊填充字元
SELECT RPAD('hello',10,'y');
去左邊空格
SELECT LTRIM(' h e ll o ');
去右邊空格
SELECT RTRIM(' h e ll o ');
去左右空格
SELECT TRIM(' h e ll o ');
子串
從第3位開始取, 取5個
SELECT SUBSTRING('51testing', 3, 5);
從第3位開始取, 取到底
SELECT SUBSTRING('51testing', 3);
【日期時間函式】
當前系統時間
SELECT SYSDATE();
SELECT NOW();
當前日期
SELECT CURRENT_DATE();
當前時間
SELECT CURRENT_TIME();
當前時間戳
SELECT CURRENT_TIMESTAMP();
獲取年份
SELECT YEAR('98/9/3');
獲取月份
SELECT MONTH('2018-9-3');
獲取月份的名字
SELECT MONTHNAME('2018-9-3');
日期加法
SELECT DATE_ADD(NOW(),INTERVAL 3 MONTH);
【聚合函式】
求平均值
SELECT AVG(age) FROM student;
求最大值
SELECT MAX(age) FROM student;
求最小值
SELECT MIN(age) FROM student;
求和
SELECT SUM(age) FROM student;
求記錄數
SELECT COUNT(age) FROM student;
【建表】
學生表
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT DEFAULT 18,
height DOUBLE);
課程表
CREATE TABLE lesson(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
teacher VARCHAR(255) DEFAULT '陳老師');
分數表
CREATE TABLE score(
sid INT,
lid INT,
score INT NOT NULL,
CONSTRAINT fk_sid FOREIGN KEY (sid) REFERENCES student(id),
CONSTRAINT fk_lid FOREIGN KEY (lid) REFERENCES lesson(id),
-- 聯合主鍵
CONSTRAINT pk_sid_lid PRIMARY KEY (sid, lid));
加入資料
INSERT INTO student VALUES (1, '張三', 18, 169);
INSERT INTO student VALUES (2, '李四', 16, 160);
INSERT INTO student VALUES (3, '王五', 19, 181);
INSERT INTO student VALUES (4, '趙六', 29, 175);
INSERT INTO student VALUES (5, '田七', 37, 170);
INSERT INTO student VALUES (6, '王八', 108, 16);
INSERT INTO lesson VALUES (1, '前置課程', '陳老師');
INSERT INTO lesson VALUES (2, 'javaSE', '陳老師');
INSERT INTO lesson VALUES (3, '資料庫', '錢老師');
INSERT INTO lesson VALUES (4, '網頁製作', '董老師');
INSERT INTO lesson VALUES (5, 'javaEE', '朱老師');
INSERT INTO lesson VALUES (6, 'javaSE', '韓老師');
單表查詢
SELECT * FROM student;
SELECT id, name, age, height FROM student;
別名查詢(AS可以省略)
SELECT id AS 學號, name AS 姓名, age AS 年齡, height AS 身高 FROM student;
SELECT id 學號, name 姓名, age 年齡, height 身高 FROM student;
去重查詢
查詢所有課程的種類
SELECT DISTINCT name FROM lesson;
查詢所有參加考試的學生學號
SELECT DISTINCT sid FROM score;
運算查詢
SELECT score + 10 FROM score;
SELECT id, name, age + 10, height FROM student;
條件記錄查詢
保留170以上的
SELECT * FROM student WHERE height > 170;
保留[160, 170]
SELECT * FROM student WHERE height >= 160 AND height <= 170;
SELECT * FROM student WHERE height BETWEEN 160 AND 170;
空值查詢
查詢身高是空的學生資訊
SELECT * FROM student WHERE height IS NULL;
查詢身高不是空的學生資訊
SELECT * FROM student WHERE height IS NOT NULL;
集合中記錄查詢
查詢分數是59 69 79分的記錄
SELECT * FROM score WHERE score IN (59, 69 ,79);
查詢分數不是59 69 79分的記錄
SELECT * FROM score WHERE score NOT IN (59, 69 ,79);
模糊查詢
查詢所有姓王的學生記錄 _ 匹配一個字元 % 可以匹配任意多字元
SELECT * FROM student WHERE name LIKE '王_';
SELECT * FROM student WHERE name LIKE '王%';
排序查詢
按照年齡排序 預設是升序
SELECT * FROM student ORDER BY age (ASC);
按照年齡降序
SELECT * FROM student ORDER BY age DESC;
多欄位排序
年齡排序, 年齡相同時按照身高排序
SELECT * FROM student ORDER BY age DESC, height;
從成績表中查詢記錄, 按照成績降序排序, 成績相同按照課程id升序排序, 成績和課程id都相同, 按照學號升序排序
SELECT * FROM score ORDER BY score DESC, lid ASC, sid ASC;
限制數量查詢(重點)
只看前5條
SELECT * FROM student LIMIT 5;
前2條不要了, 再拿5條
SELECT * FROM student LIMIT 2,5;
分頁查詢(重點)
每頁顯示2條
第1頁
SELECT * FROM student LIMIT 0,2;
第2頁
SELECT * FROM student LIMIT 2,2;
第3頁
SELECT * FROM student LIMIT 4,2;
第4頁
SELECT * FROM student LIMIT 6,2;
規律: 後面一個引數就是每頁顯示個數, 前面一個引數是 (頁數-1)*每頁顯示個數
分組查詢
SELECT lid, AVG(score) FROM score GROUP BY lid;
SELECT lid, score FROM score GROUP BY lid;
多表查詢
SELECT * FROM student;
SELECT * FROM score;
1. 交叉連線 8 * 4 , 7 * 3 -> 56 , 7
SELECT * FROM student, score;
SELECT * FROM student CROSS JOIN score;
2. 內連線 - 只能保留兩個表都有的資料
SELECT * FROM student, score WHERE student.id = score.sid;
SELECT * FROM student INNER JOIN score WHERE id = sid;
查詢所有學生的學號 姓名 考試科目 任課老師和考試分數
SELECT student.id, student.name, lesson.name, lesson.teacher, score.score
FROM student, lesson, score
WHERE student.id = score.sid AND score.lid = lesson.id;
3. 外連線
左外連線 - 保留左表全部資料的前提下, 把右表拼接上來
SELECT *
FROM student LEFT JOIN score
ON student.id = score.sid;
SELECT *
FROM score LEFT JOIN student
ON student.id = score.sid;
右外連線 - 保留右表全部資料的前提下, 把左表拼接上來
SELECT *
FROM score RIGHT JOIN student
ON student.id = score.sid;
子查詢
單行單列子查詢
查詢年齡比張三大的學生資訊
SELECT *
FROM student
WHERE age > (SELECT age FROM student WHERE name = '張三');
查詢考了100分的學生資訊
SELECT *
FROM student
WHERE id = (SELECT sid FROM score WHERE score = 100);
SELECT student.*
FROM student,score
WHERE id = sid AND score = 100;
查詢年齡和身高都和張三一樣的學生資訊
SELECT *
FROM student
WHERE age = (SELECT age FROM student WHERE name = '張三')
AND height = (SELECT height FROM student WHERE name = '張三')
單行多列子查詢
SELECT *
FROM student
WHERE (age, height) = (SELECT age, height FROM student WHERE name = '張三');
多行單列子查詢
查詢考了59分的學生資訊
1. IN 關鍵字 - 查詢的條件是在子查詢的查詢結果中
SELECT *
FROM student
WHERE id IN (SELECT sid FROM score WHERE score = 59);
查詢所有參加過考試的學生資訊
SELECT *
FROM student
WHERE id IN (SELECT DISTINCT sid FROM score);
2. ANY 關鍵字 - 查詢的條件滿意子查詢返回結果的任意一條記錄
查詢比張三, 李四, 王五中任意一個人年齡大的學生資訊
SELECT *
FROM student
WHERE age > ANY (SELECT age FROM student WHERE name IN('張三', '李四', '王五'));
SELECT *
FROM student
WHERE age > (SELECT MIN(age) FROM student WHERE name IN('張三', '李四', '王五'));
3. ALL 關鍵字 - 查詢的條件滿足子查詢返回結果的所有記錄
查詢比張三,李四,王五年齡都大的學生資訊
SELECT *
FROM student
WHERE age > ALL (SELECT age FROM student WHERE name IN ('張三','李四','王五'));
SELECT *
FROM student
WHERE age > (SELECT MAX(age) FROM student WHERE name IN('張三','李四','王五'));
4. EXISTS 關鍵字: 查詢時遍歷外表, 每次查詢都會執行exists子句, 存在記錄時為真
SELECT * FROM student WHERE age > 20;
查詢參加過考試的學生
SELECT *
FROM student
WHERE EXISTS (
SELECT *
FROM score
WHERE student.id = score.sid);
SELECT *
FROM score
WHERE 4 = score.sid
疑點
select 要顯示的結果,可以帶聚合函式
From
Where 在記錄之前就對記錄進行過濾
Group by 分類聚合的欄位
Having :對聚合(分組)後的記錄過濾
select count(*)和select count(1)的區別
一般情況下,Select Count (*)和Select Count(1)兩著返回結果是一樣的
假如表沒有主鍵(Primary key), 那麼count(1)比count(*)快,
如果有主鍵的話,那主鍵作為count的條件時候count(主鍵)最快
如果你的表只有一個欄位的話那count(*)就是最快的
count(*) 跟 count(1) 的結果一樣,都包括對NULL的統計,而count(column) 是不包括NULL的統計
TPL(事務處理語言)
【事務 Transaction】
1. 概念
作為一個單獨單元的一條或者多條SQL語句組成
這個單元的每一條SQL語句都是相互依賴的
必須每一條SQL語句都成功的執行, 才可以說這個事務成功的執行了
如果有一條語句執行出錯, 那麼整個事務就會回滾
回到事務開始以前的狀態
轉賬
A給B轉100元
餘額表
使用者名稱 餘額
A 100
B 50
A-100 B-50
UPDATE 餘額表 SET 餘額 = 餘額 - 100 WHERE 使用者名稱 = 'A';
A-0 B-50
UPDATE 餘額表 SET 餘額 = 餘額 + 100 WHERE 使用者名稱 = 'B';
A-0 B-150
2. 事務的特點 ACID:
原子性(Atomicity):
事務的多條SQL語句是一個不可分割的完整邏輯單元
一致性(Consistency):
事務中的每條SQL語句要麼都是成功執行的, 要麼都失敗了
如果一個事務成功執行了, 那麼裡面的每一條SQL語句都成功執行了
如果一個事務失敗了, 那麼裡面的每一條SQL語句都失敗了
隔離性(Isolation)
不同的事務是相互隔離的
不同的事務相互訪問的時候
得到的資料要麼是事務發生以前的資料
要麼是事務發生以後的資料
永續性(Durability)
一旦事務完成提交, 對資料的修改就是永久的
3. 操作
開啟事務 START TRANSACTION;
儲存到S1 SAVEPOINT s1;
設定一個節點
回滾到S1, ROLLBACK TO s1;
回到s1節點,然後繼續執行ROLLBACK TO s1後面的語句!
回滾 ROLLBACK;
回到開頭,然後繼續執行ROLLBACK後面的語句!
提交 COMMIT;
檢視 View
一張或多張表的資料子集的邏輯表現
1. 檢視不是表,不是一個物理的實體,只是一個邏輯表現
2. 檢視中的資料是來源於表的
3. 檢視的本質就是子查詢
作用:
1. 對資料安全保護
2. 簡化查詢語句
3. 更清晰的表達查詢
建立檢視
create view v_emp10
as
select empno,ename,job from emp where deptno=10;
建立檢視,如果已存在檢視則替換,並把列名自定義
create or replace view v_emp10 (id,name,job)
as
select empno,ename,job from emp where deptno=10;
select *from v_emp10;
刪除
drop view v_emp10 ;
新建部門檢視
CREATE VIEW v_dept
AS
SELECT * FROM dept;
從部門檢視中查詢資料
SELECT * FROM v_dept;
往檢視中插入資料
INSERT INTO v_dept VALUES (50, '教學部', '漕河涇');
從表中查詢資料
SELECT * FROM dept;
問題: 能不能修改檢視中的資料呢?
錯誤答案1: 能
錯誤答案2: 不能
正確答案: 有的檢視能, 有的檢視不能
建立一個各個部門平均工資檢視
CREATE VIEW v_dept_avgsal
AS
SELECT dname, avg(sal)
FROM emp RIGHT JOIN dept
ON emp.deptno = dept.deptno
GROUP BY dname;
從檢視中查詢資料
SELECT * FROM v_dept_avgsal;
INSERT INTO v_dept_avgsal VALUES ('教研部', 20000);
插入失敗,因為avg(sal)資料根本不存在
儲存過程和函式
【儲存過程】
定義一個儲存過程
CREATE PROCEDURE proc1()
BEGIN
SELECT 1+1;
SELECT NOW();
SELECT LEFT('HAHA',2);
END
刪除儲存過程
DROP PROCEDURE proc1;
呼叫儲存過程
CALL proc1();
使用者變數
可以先在使用者變數中儲存值, 然後再引用它
這樣就可以將值從一條語句傳遞到另一條語句
* 使用者變數和連線有關
SET @x = 'hello';
SELECT @x;
SELECT 'world' INTO @y;
SELECT @y;
SET @z = 1+2+3;
SELECT @z;
查詢的結果儲存到x變數中:
SELECT (@x:=age) FROM student WHERE name = '張三';
SELECT @x;
SELECT * FROM student WHERE age = @x;
建立帶引數的儲存過程
引數型別
IN - 只能將引數的值傳入過程, 在過程中的修改對變數沒有影響, 就是個預設值
OUT - 引數的值傳不進過程中, 但是在過程中對其修改的結果會影響變數的結果
INOUT - 既能傳入, 對其進行的修改又能傳出來
CREATE PROCEDURE proc2(IN p INT)
BEGIN
SELECT p;
SET p = 2;
SELECT p;
END
DROP PROCEDURE proc2;
SET @p = 1;
CALL proc2(@p);
SELECT @p;
結果:1,2,1
CREATE PROCEDURE proc3(OUT p INT)
BEGIN
SELECT p;
SET p = 2;
SELECT p;
END
SET @p = 1;
CALL proc3(@p);
SELECT @p;
結果:null,2,2
CREATE PROCEDURE proc4(INOUT p INT)
BEGIN
SELECT p;
SET p = 2;
SELECT p;
END
SET @p = 1;
CALL proc4(@p);
SELECT @p;
結果:1,2,2
【函式】
CREATE FUNCTION func1() RETURNS INT
BEGIN
RETURN 1;
END
函式必須放在查詢語句中呼叫
SELECT func1();
SELECT NOW();
已經寫好的函式
函式和儲存過程的區別:
- 呼叫方式不同
- 儲存過程沒有返回值,函式有返回值