我自己學習數據庫也有一段時間了但是隻用了SqlServer和mysql,我就想着來一波總結
我們直接來第一個問題:數據庫的四個基本概念是什麼
嗯,數據、數據庫、數據庫管理系統、數據庫系統是與數據庫技術密切相關的4個基本概念,讓我們一個個來
- 數據(data):數據是數據庫對象中的基本對象。數據到底是什麼東西呢?數字?不僅僅是數字,數字只是一種簡單的數據,數據有很多種類,比如文本(text),圖形(graph),圖像(image),音頻(audio),視頻(video),學生的成績信息等等這些都是數據.往往這個數據的具體含義和當前的語義是分不開的,比如90可以是成績也可以是某件物品對的價格
- 數據庫(Database):通俗的來說就是存放數據的倉庫。這個倉庫存在於計算機中,其中的數據是按一定的格式存放的。嚴格的來說,數據庫是長期存儲在計算機內、有組織、可共享的大量數據的集合。數據庫中的數據按一定的數據模型組織、描述和存儲、具有較小的冗餘度、較大的數據獨立性、和易擴展性,並可爲各種用戶共享
- 數據庫管理系統(Database Management System,DBMS):用於高效的獲取和維護數據的系統軟件。主要功能如下:
- 數據定義功能
- 數據組織、存儲和管理
- 數據操作功能
- 數據庫的事物管理和運行管理
- 數據庫的建立和維護
- 其他的功能
- 數據庫系統(Database System,DBS):是由數據庫、數據庫管理系統、應用程序和數據庫管理員、組成的存儲、管理、處理和維護的系統
數據庫系統的示意圖
第二問:說一說你瞭解的常見的關係型數據庫
說起sql數據庫大家都知道現在用的最多的關係型數據庫有Oracle,Mysql,Sqlserver。現在在企業級別的開發工作中大部分是Oracle和Mysql,我到現在還只學習過SqlServer和mysql通過這一段的學習,對於數據庫的學習我認爲有如下重點,從頭開始當然要學習好一些數據模型和理解數據庫系統的三級模式結構,說到sql當然要把sql 的增刪改查玩的溜一點,不然怎麼入土。說實話對於增刪改查的難點在於多表的連表查詢,當然數據庫設計的冗餘度也影響着寫查詢語句的代碼量和邏輯結構.在多表的查詢中有join關鍵字,是否使用join,怎麼用join是根據需要查詢的信息和表之間的關係決定的。瞭解完增刪改查,再就是索引、視圖、觸發器、存儲過程、遊標、事務處理。在我的學習過程中其實覺得自己想通了邏輯,連表查詢並不是很難。還是要動手實踐,邏輯複雜的可以分部完成
** 第三問:自己有設計過數據庫嗎?設計數據庫有什麼原則?那麼在建表的工程中要注意什麼?要遵循哪些語法規則?**
數據庫的設計原則:
1. 字段的原子性
解釋:字段裏面存放的數據在邏輯意義上不能再分割。
2. 字段長度
解釋:字符串儘量將大小控制在末尾預留3-5個字符位置,但是不要太長;id形式的數值一般使用Long類型,數據庫裏面使用bigint。
3. 字段使用次數
解釋:對於較爲頻繁使用(修改)最好使用獨立數數字、簡短的單詞(縮寫)、單個字符,不要使用較長的中文、英文描述。一般會在“狀態修改”這個業務邏輯上進行適用。
4. 預留字段、刪除字段
解釋:設計表的時候可以先預留一個空白字段,方便以後擴展;無論何時,儘量不要去刪除數據庫裏面的字段或者行(數據內容)。
5. 標記字段
解釋:可以通過“標記”來表示是否還需要繼續訪問某些數據。
6. 主鍵設計
解釋:標識一個表中數據的唯一性,不一定非要和業務邏輯相關,最好不相關,就只用來記錄一條數據的存在!!!一般使用自增形成!!!不要嘗試修改主鍵列中的數據!!!
7. 外鍵設計
解釋:儘量不要建立外鍵,保證表自身的獨立性,通過程序設計中的業務邏輯連接某兩個列,來達到關聯的行爲。各種表中同一個外鍵的字段名需要保持一致,爲了方便使用和維護。
8. 動靜分離
解釋:從業務邏輯出發,將一些固定(長時間)不變的內容集中在一起;經常需要修改的內容集中在一起。
9. 關係映射
解釋:多表映射,儘量拆分可以拆分的列(按照業務邏輯的要求來考量),多個表之間最好使用 相關的ID 來進行邏輯上的關聯
10. NULL值
解釋:儘量不要有NULL在表裏,在建表的時增設默認值。
其他:
1. 在設計表的時候包含兩個字段:crt_time(某條數據的創建時間)、upd_time(某條數據最後修改的時間)
2. 表設計中,字段命名一般會增加前後綴
對於建表來說,怎麼說,我覺得是考驗一個人的邏輯能力,只有認真的把各個模塊分析清除,找到表與表之間的關係才能設計好表,對於一個表的數量較少的數據庫而言,通過冗餘也是可以簡化數據庫的設計的,但是對於大的項目而言,冗餘度一定不能高,最好表與表之間的關聯項只有一個,而且一般是以id爲關聯項,如果關聯項過多,那麼在修改數據的過程中就會導致修改的過程過於複雜,而且表與表之間的相對獨立更加的複合設計的原則。
對於語法規範而言,不管是在數據庫中還是在別的地方都吃過命名中文的虧,不要問爲什麼,你儘量寫英文就對了。下面是我總結的一些規範:
- 命名儘量用英文,不區分大小寫,但建議關鍵字大寫,表名、列名小寫
- 爲了區分是視圖還是表建議在表的前面加上tb,在視圖前加上vi。
- 每條命令最好用分號結尾
- 每條命令根據需要,可以進行縮進 或換行,這個很重要,對於一張表或者兩張表的查詢而言或許體現不出什麼優勢,在多表查詢時更能體現邏輯性
- 註釋
單行註釋:#註釋文字
單行註釋:-- 註釋文字
多行註釋:/* 註釋文字 */
第四問:說出sql中最常見的命令和常見的函數?
常見命令(增刪改查的另說):
- create database 創建庫
- drop database 刪除庫
- show databases; 查看所有的數據庫
- use 庫名; 打開指定 的庫
- show tables ; 顯示庫中的所有表
- show tables from 庫名;顯示指定庫中的所有表
- create table 表名(
字段名 字段類型,
字段名 字段類型
); 創建表- desc 表名; 查看指定表的結構 select * from 表名;顯示錶中的所有數據
修改表的命令:
修改表 alter
語法:ALTER TABLE 表名 ADD|MODIFY|DROP|CHANGE COLUMN 字段名 【字段類型】;
①修改字段名
ALTER TABLE studentinfo CHANGE COLUMN sex gender CHAR;
②修改表名
ALTER TABLE stuinfo RENAME [TO] studentinfo;
③修改字段類型和列級約束
ALTER TABLE studentinfo MODIFY COLUMN borndate DATE ;
④添加字段
ALTER TABLE studentinfo ADD COLUMN email VARCHAR(20) first;
⑤刪除字段
ALTER TABLE studentinfo DROP COLUMN email;
刪除表
DROP TABLE [IF EXISTS] studentinfo;
常見函數:
一、單行函數
1、字符函數
concat拼接
substr截取子串
upper轉換成大寫
lower轉換成小寫
trim去前後指定的空格和字符
ltrim去左邊空格
rtrim去右邊空格
replace替換
lpad左填充
rpad右填充
instr返回子串第一次出現的索引
length 獲取字節個數
2、數學函數
round 四捨五入
rand 隨機數
floor向下取整
ceil向上取整
mod取餘
truncate截斷
3、日期函數
now當前系統日期+時間
curdate當前系統日期
curtime當前系統時間
str_to_date 將字符轉換成日期
date_format將日期轉換成字符
4、流程控制函數
if 處理雙分支
case語句 處理多分支
情況1:處理等值判斷
情況2:處理條件判斷
5、其他函數
version版本
database當前庫
user當前連接用戶
二、分組函數
sum 求和
max 最大值
min 最小值
avg 平均值
count 計數
特點:
1、以上五個分組函數都忽略null值,除了count()
2、sum和avg一般用於處理數值型
max、min、count可以處理任何數據類型
3、都可以搭配distinct使用,用於統計去重後的結果
4、count的參數可以支持:
字段、、常量值,一般放1
建議使用 count(*)
第五問:詳細的說說增刪改查吧
開始了~~
1.基礎的查詢語句:
select * from 標的名稱
2.條件查詢:
select
要查詢的字段|表達式|常量值|函數
from
表
where
條件
說到條件查詢就說說條件表達式:
示例:salary>10000
條件運算符:
< >= <= = != <>
邏輯運算符:
and(&&):兩個條件如果同時成立,結果爲true,否則爲false
or(||):兩個條件只要有一個成立,結果爲true,否則爲false
not(!):如果條件成立,則not後爲false,否則爲true
3.模糊查詢
示例:last_name like ‘a%’
4.排序查詢:
語法:
select
要查詢的東西
from
表
where
條件
order by 排序的字段|表達式|函數|別名 【asc|desc】
5.分組查詢:
語法:
select 查詢的字段,分組函數
from 表
group by 分組的字段
特點:
1、可以按單個字段分組
2、和分組函數一同查詢的字段最好是分組後的字段
3、分組篩選
針對的表 位置 關鍵字
分組前篩選: 原始表 group by的前面 where
分組後篩選: 分組後的結果集 group by的後面 having
4、可以按多個字段分組,字段之間用逗號隔開
5、可以支持排序
6、having後可以支持別名
6.多表連接查詢:
笛卡爾乘積:如果連接條件省略或無效則會出現
解決辦法:添加上連接條件
一、等值連接——非等值連接
1.等值連接的結果 = 多個表的交集
2.n表連接,至少需要n-1個連接條件
3.多個表不分主次,沒有順序要求
4.一般爲表起別名,提高閱讀性和性能
二、通過join關鍵字實現連接
含義:1999年推出的sql語法
支持:
等值連接、非等值連接 (內連接)
外連接
交叉連接
語法:
select 字段,...
from 表1
【inner|left outer|right outer|cross】join 表2 on 連接條件
【inner|left outer|right outer|cross】join 表3 on 連接條件
【where 篩選條件】
【group by 分組字段】
【having 分組後的篩選條件】
【order by 排序的字段或表達式】
好處:語句上,連接條件和篩選條件實現了分離,簡潔明瞭!
7.自連接
自連接其實就是邏輯上的兩張表,但是實際上只有一張,也可以通過join或者where條件兩種方法進行
join:
SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m ON e.`manager_id`=m.`employee_id`;
where:
SELECT e.last_name,m.last_name
FROM employees e,employees m
WHERE e.`manager_id`=m.`employee_id`;
8.子查詢
含義:
一條查詢語句中又嵌套了另一條完整的select語句,其中被嵌套的select語句,稱爲子查詢或內查詢
在外面的查詢語句,稱爲主查詢或外查詢
特點:
1、子查詢都放在小括號內
2、子查詢可以放在from後面、select後面、where後面、having後面,但一般放在條件的右側
3、子查詢優先於主查詢執行,主查詢使用了子查詢的執行結果
4、子查詢根據查詢結果的行數不同分爲以下兩類:
A. 單行子查詢
結果集只有一行
一般搭配單行操作符使用:> < = <> >= <=
非法使用子查詢的情況:
a、子查詢的結果爲一組值
b、子查詢的結果爲空
B.多行子查詢
結果集有多行
一般搭配多行操作符使用:any、all、in、not in
in: 屬於子查詢結果中的任意一個就行
any和all往往可以用其他查詢代替
9.分頁查詢
應用場景:
實際的web項目中需要根據用戶的需求提交對應的分頁查詢的sql語句
語法:
select 字段|表達式,...
from 表
【where 條件】
【group by 分組字段】
【having 條件】
【order by 排序的字段】
limit 【起始的條目索引,】條目數;
特點:
1.起始條目索引從0開始
2.limit子句放在查詢語句的最後
3.公式:select * from 表 limit (page-1)*sizePerPage,sizePerPage
假如:
每頁顯示條目數sizePerPage
要顯示的頁數 page
10.聯合查詢
引入:
union 聯合、合併
語法:
select 字段|常量|表達式|函數 【from 表】 【where 條件】 union 【all】
select 字段|常量|表達式|函數 【from 表】 【where 條件】 union 【all】
select 字段|常量|表達式|函數 【from 表】 【where 條件】 union 【all】
.....
select 字段|常量|表達式|函數 【from 表】 【where 條件】
特點:
1、多條查詢語句的查詢的列數必須是一致的
2、多條查詢語句的查詢的列的類型幾乎相同
3、union代表去重,union all代表不去重
11.插入數據
語法:
insert into 表名(字段名,...)
values(值1,...);
特點:
1、字段類型和值類型一致或兼容,而且一一對應
2、可以爲空的字段,可以不用插入值,或用null填充
3、不可以爲空的字段,必須插入值
4、字段個數和值的個數必須一致
5、字段可以省略,但默認所有字段,並且順序和表中的存儲順序一致
修改數據
修改單表語法:
update 表名 set 字段=新值,字段=新值
【where 條件】
修改多表語法:
update 表1 別名1,表2 別名2
set 字段=新值,字段=新值
where 連接條件
and 篩選條件
13刪除數據
方式1:delete語句
單表的刪除:
delete from 表名 【where 篩選條件】
多表的刪除:
delete 別名1,別名2
from 表1 別名1,表2 別名2
where 連接條件
and 篩選條件;
方式2:truncate語句
truncate table 表名
兩種方式的區別【面試題】
1.truncate不能加where條件,而delete可以加where條件
2.truncate的效率高一丟丟
3.truncate 刪除帶自增長的列的表後,如果再插入數據,數據從1開始
delete 刪除帶自增長列的表後,如果再插入數據,數據從上一次的斷點處開始
4.truncate刪除不能回滾,delete刪除可以回滾
第六問:說說視圖和索引
1.視圖的含義:理解成一張虛擬的表
視圖和表的區別:
使用方式 佔用物理空間
視圖 完全相同 不佔用,僅僅保存的是sql邏輯
表 完全相同 佔用
視圖的好處:
1、sql語句提高重用性,效率高
2、和表實現了分離,提高了安全性
2.視圖的創建
語法:
CREATE VIEW 視圖名
AS
查詢語句;
3.視圖的增刪改查
1、查看視圖的數據
SELECT * FROM my_v4;
SELECT * FROM my_v1 WHERE last_name='Partners';
2、插入視圖的數據
INSERT INTO my_v4(last_name,department_id) VALUES('虛竹',90);
3、修改視圖的數據
UPDATE my_v4 SET last_name ='夢姑' WHERE last_name='虛竹';
4、刪除視圖的數據
DELETE FROM my_v4;
4.某些視圖不能更新
包含以下關鍵字的sql語句:分組函數、distinct、group by、having、union或者union all
常量視圖
Select中包含子查詢
join
from一個不能更新的視圖
where子句的子查詢引用了from子句中的表
5.視圖邏輯的更新
方式一:
CREATE OR REPLACE VIEW test_v7
AS
SELECT last_name FROM employees
WHERE employee_id>100;
方式二:
ALTER VIEW test_v7
AS
SELECT employee_id FROM employees;
SELECT * FROM test_v7;
6.視圖的刪除
DROP VIEW test_v1,test_v2,test_v3;
7.視圖結構的查看
DESC test_v7;
SHOW CREATE VIEW test_v7;
索引 - index
根據表中的一列或者多列字段按照一定順序建立的列值與記錄行之間的對應關係表。
數據表的訪問方式:
1.順序訪問,對一張表從頭到尾逐個掃描,數據量大的時候,遍歷全部內容時,花費時間較多。
2.索引訪問,通過遍歷索引來直接訪問所在表中記錄行。
索引的分類:
1. B-樹索引
2. 哈希索引
索引的類型和存儲引擎有關,每種引擎支持的索引類型不完全一樣。
1. 普通索引,通常使用關鍵字(index、key)
2. 唯一性索引,unique
3. 主鍵索引,primary key
創建表
CREATE TABLE t_student (
stu_id INT NOT NULL,
stu_name CHAR(10) NOT NULL,
stu_class INT NOT NULL,
stu_sex CHAR(2) NOT NULL,
stu_age INT NOT NULL,
PRIMARY KEY (stu_id)
);
查看索引
SHOW INDEX FROM t_student;
創建普通單列索引
CREATE INDEX index_id ON t_student(stu_id);
修改表的方式添加普通單列索引
ALTER TABLE t_student ADD INDEX index_class(stu_class);
刪除索引
DROP INDEX index_id ON t_student;
DROP INDEX index_class ON t_student;
創建多列組合索引
CREATE INDEX index_id_name ON t_student(stu_id, stu_name(3));
修改表的方式添加多列組合索引
ALTER TABLE t_student ADD INDEX index_test(stu_id, stu_name, stu_class);
使用 explain 關鍵字 查看SQL語句是否使用了索引
EXPLAIN SELECT * FROM t_student WHERE stu_age = 12;
EXPLAIN SELECT * FROM t_student WHERE stu_id = 2;
EXPLAIN SELECT * FROM t_student WHERE stu_id = 2 AND stu_name = 'asd';
EXPLAIN SELECT * FROM t_student WHERE stu_id = 2 AND stu_name = 'asd' AND stu_class = 1;
多列組合索引的特點,是從定義索引時的列組合順序的最左邊開始匹配,注意觀察上下的語句中的匹配條件
EXPLAIN SELECT * FROM t_student WHERE stu_name = 'asd';
EXPLAIN SELECT * FROM t_student WHERE stu_class = 2;
EXPLAIN SELECT * FROM t_student WHERE stu_name = 'asd' AND stu_class = 1;
創建表時創建索引
CREATE TABLE t_student_01(
stu_id INT NOT NULL,
stu_name CHAR(10) NOT NULL,
stu_class INT NOT NULL,
stu_sex CHAR(2) NOT NULL,
stu_age INT NOT NULL,
PRIMARY KEY (stu_id),
INDEX index_name(stu_name(5))
);
查看索引
SHOW INDEX FROM t_student_01;
創建唯一性索引
CREATE UNIQUE INDEX indexname ON t_student_01(stu_name(3));
刪除索引
DROP INDEX indexname ON t_student_01;
修改表的方式添加唯一性索引
ALTER TABLE t_student_01 ADD UNIQUE indexname(stu_name(4));
創建表的方式創建唯一性索引
CREATE TABLE test_table_01 (
id INT NOT NULL,
NAME VARCHAR(20) NOT NULL,
UNIQUE index_name (NAME(10))
);
SHOW INDEX FROM test_table_01;
全文索引
創建表的時創建
CREATE TABLE article (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(100),
content TEXT,
FULLTEXT(title, content)
);
查看全文索引
SHOW INDEX FROM article;
準備數據
INSERT INTO article VALUES(NULL,'qwerdf這些操作是啥?','qwer是常規技能按鍵,CD較短,可以短時間內使用多次;df是特殊技能按鍵,CD較長,短時間內使用次數非常少,需要謹慎使用!');
測試是否使用了索引
EXPLAIN SELECT * FROM article WHERE title LIKE 'qwer';
EXPLAIN SELECT * FROM article WHERE title LIKE 'qwer' OR content LIKE 'qwer';
依然複合多列組合索引的使用規則(最左)
EXPLAIN SELECT * FROM article WHERE content LIKE 'qwer';
創建全文索引
CREATE FULLTEXT INDEX index_test_01 ON article(title);
修改表的方式添加全文索引
ALTER TABLE article ADD FULLTEXT INDEX index_test_02(title, content);
刪除全文索引
DROP INDEX index_test_01 ON article;
DROP INDEX index_test_02 ON article;
需要注意的事項:
1. 唯一性索引的值是唯一的,這樣可以更快的確定查找的數據行。
2. 索引不是越多越好,索引需要佔內存空間,更新表數據時候需要一同更新索引會消耗時間和資源。
3. 經常作爲查詢條件的列,是最適合建立索引的列。需要分組、排序、排重的列,也可以建立索引,提高速度。
4. 儘量使用數據量較少的列建立索引,儘量少用全文索引。
5. 刪除不再使用或者極少使用的索引。
第7問:談談觸發器
觸發器
自動執行的行爲,當某個行爲作爲觸發條件設定在觸發器中時,一旦在後續出現這樣的行爲,觸發器則自動啓動,開始執行觸發器設計中需要“連帶自動執行的內容”
三種行爲 insert、update、delete
兩種時間節點:before、 after
排列組合,最多 6個 觸發器(一張表裏面),即使創建了一樣的觸發器(行爲+時間),依然沒有辦法執行
準備表
CREATE TABLE t_order (
id INT PRIMARY KEY,
content VARCHAR(20) NOT NULL
);
CREATE TABLE t_order_time (
id INT PRIMARY KEY,
creation_time TIMESTAMP NOT NULL
);
插入行爲的觸發器
CREATE TRIGGER tri_insert
-- 注意兩個一樣行爲和時間的觸發器,可以創建,但是不能執行
-- create trigger tri_insert_01
AFTER INSERT
ON t_order
FOR EACH ROW
INSERT INTO t_order_time VALUES( NEW.id, NOW() );
INSERT INTO t_order VALUES(1,'外賣訂單01');
INSERT INTO t_order VALUES(2,'快遞訂單01');
INSERT INTO t_order VALUES(3,'xx訂單01');
SHOW TRIGGERS;
DROP TRIGGER tri_insert_01;
更新行爲的觸發器
DELIMITER //
CREATE TRIGGER tri_update
BEFORE UPDATE
ON t_order
FOR EACH ROW
BEGIN
UPDATE t_order_time SET creation_time = NOW() WHERE OLD.id = id;
END
//
DELIMITER ;
SHOW TRIGGERS;
UPDATE t_order SET content = 'XX訂單_01(up_01)' WHERE id = 3;
刪除行爲的觸發器
DELIMITER //
CREATE TRIGGER tri_delete
AFTER DELETE
ON t_order
FOR EACH ROW
BEGIN
DELETE FROM t_order_time WHERE OLD.id = id;
END
//
DELIMITER ;
DELETE FROM t_order WHERE id = 3;
觸發器裏面的“連帶執行的內容”儘量寫的邏輯簡單一點,不要太過於複雜。
第八問:談談對於存儲過程的理解,並且舉例
存儲過程:
1.含義:一組經過預先編譯的sql語句的集合
好處:
1、提高了sql語句的重用性,減少了開發程序員的壓力
2、提高了效率
3、減少了傳輸次數
2.分類:
1、無返回無參
2、僅僅帶in類型,無返回有參
3、僅僅帶out類型,有返回無參
4、既帶in又帶out,有返回有參
5、帶inout,有返回有參
注意:in、out、inout都可以在一個存儲過程中帶多個
3.創建存儲過程
語法:
create procedure 存儲過程名(in|out|inout 參數名 參數類型,...)
begin
存儲過程體
end
類似於方法:
修飾符 返回類型 方法名(參數類型 參數名,...){
方法體;
}
注意
1、需要設置新的結束標記
delimiter 新的結束標記
示例:
delimiter $
CREATE PROCEDURE 存儲過程名(IN|OUT|INOUT 參數名 參數類型,...)
BEGIN
sql語句1;
sql語句2;
END $
2、存儲過程體中可以有多條sql語句,如果僅僅一條sql語句,則可以省略begin end
3、參數前面的符號的意思
in:該參數只能作爲輸入 (該參數不能做返回值)
out:該參數只能作爲輸出(該參數只能做返回值)
inout:既能做輸入又能做輸出
4.調用存儲過程
call 存儲過程名(實參列表)
5.函數
A.創建函數
學過的函數:LENGTH、SUBSTR、CONCAT等
語法:
CREATE FUNCTION 函數名(參數名 參數類型,...) RETURNS 返回類型
BEGIN
函數體
END
B.調用函數
SELECT 函數名(實參列表)
函數和存儲過程的區別
關鍵字 調用語法 返回值 應用場景
函數 FUNCTION SELECT 函數() 只能是一個 一般用於查詢結果爲一個值並返回時,當有返回值而且僅僅一個
存儲過程 PROCEDURE CALL 存儲過程() 可以有0個或多個 一般用於更新
我自己的操作:
創建存儲過程
DELIMITER //---自定義結束符號
CREATE PROCEDURE procedure_01( IN str CHAR(20) )
BEGIN
IF str IS NULL OR str = '' THEN
SELECT * FROM t_user;
ELSE
SELECT * FROM t_user WHERE user_name LIKE str;
END IF;
END
//
DELIMITER ;
調用存儲過程
CALL procedure_01('%s%');
創建存儲過程
DELIMITER //
CREATE PROCEDURE procedure_02( IN str CHAR(20), OUT print CHAR(20) )
BEGIN
SELECT user_password INTO print FROM t_user WHERE user_name = str;
-- 此處必須值有一行數據被查出
END
//
DELIMITER ;
調用存儲過程
-- set @p = '';
CALL procedure_02('zxcv',@p);
SELECT @p;
創建存儲過程
DELIMITER //
CREATE PROCEDURE procedure_03( INOUT num INT )
BEGIN
SET num = num*10;
END
//
DELIMITER ;
調用存儲過程
SET @n = 3;
CALL procedure_03(@n);
SELECT @n;
DELIMITER //
CREATE PROCEDURE p_test_01()
BEGIN
-- 聲明定義一個整型變量,是存儲過程內部的局部變量
DECLARE num INT;
-- 給這個變量賦值
SET num = 101;
-- “打印”變量裏面的存放的數值
SELECT num;
END
//
DELIMITER ;
CALL p_test_01();
DELIMITER //
CREATE PROCEDURE p_test_02( IN num INT )
BEGIN
IF num = 1 THEN
SELECT * FROM t_user WHERE num = user_id;
ELSEIF num = 2 THEN
SELECT * FROM t_user WHERE num = user_id;
ELSEIF num = 5 THEN
SELECT * FROM t_user WHERE num = user_id;
ELSEIF num = 7 THEN
SELECT * FROM t_user WHERE num = user_id;
ELSE
SELECT * FROM t_user;
END IF;
END
//
DELIMITER ;
CALL p_test_02(7);
DELIMITER //
CREATE PROCEDURE p_test_03( IN num INT, OUT res INT )
BEGIN
SET res = 0;
WHILE num > 0 DO
SET res = num + res;
SET num = num - 1;
END WHILE;
END
//
DELIMITER ;
CALL p_test_03(10, @m);
SELECT @m;
DELIMITER //
CREATE PROCEDURE p_test_04( IN num INT, OUT res INT )
BEGIN
SET res = 0;
REPEAT
SET res = num + res;
SET num = num - 1;
UNTIL num <= 0
END REPEAT;
END
//
DELIMITER ;
CALL p_test_04(10, @m);
SELECT @m;
-- drop procedure [if exists] 存儲過程名
DROP PROCEDURE IF EXISTS p_test_04;
存儲過程的修改,只能修改器特性,不能修改begin-end之間的執行內容。
如果需要存儲過程的執行內容,需要刪除原來的,新建一個即可。
第九問:你自己說說什麼是遊標
說到遊標就想起了那啥遊標卡尺,其實半毛線關係都沒有,哈哈哈
話說遊標是啥?
嗯,是系統爲用戶開設的一個數據緩衝區,存放sql語句的執行結果,每個遊標區都有一個名字。用戶可以通過遊標逐一獲取記錄並賦值給主變量,交由主語言進一步處理
遊標的示例馬上補齊,客觀稍等!!
創建一張測試表,用於演示sqlserver遊標的使用
create table tblCursor(
Id uniqueidentifier,
EmpCode varchar(50),
EmpName varchar(50),
EmpAddress varchar(200)
);
往測試表中插入幾行測試數據
insert into tblCursor(Id, EmpCode, EmpName, EmpAddress) values(NEWID(), 'Emp001', '張三', '北京');
insert into tblCursor(Id, EmpCode, EmpName, EmpAddress) values(NEWID(), 'Emp002', '李四', '上海');
insert into tblCursor(Id, EmpCode, EmpName, EmpAddress) values(NEWID(), 'Emp003', '王五', '深圳');
insert into tblCursor(Id, EmpCode, EmpName, EmpAddress) values(NEWID(), 'Emp004', '趙六', '廣州');
查詢測試表中的數據
select * from tblCursor;
定義遊標,格式如下,截圖中有顏色的字都是sqlserver的關鍵字
declare curEmployee cursor for
select empcode, empname, empaddress from tblCursor
定義遊標之後,需要打開遊標,才能開始操作,打開遊標使用下面的語法
-- curEmployee 就是上一步定義的遊標名稱
open curEmployee
當 全局變量@@FETCH_STATUS = -1,表示當前沒有遊標在處理數據
select @@FETCH_STATUS
使用遊標,循環輸出第一步創建表的數據完整代碼如下:
-- 定義臨時標量,用於接收遊標的數據內容
declare @EmpCode varchar(50), @EmpName varchar(50), @EmpAddress varchar(200);
-- 定義遊標
declare curEmployee cursor for
select empcode, empname, empaddress from tblCursor
-- 打開遊標
open curEmployee
-- 請注意:遊標返回的字段個數、類型都需要與into後面的變量一致
fetch curEmployee into @EmpCode, @EmpName, @EmpAddress
-- 當遊標循環結束之後 @@FETCH_STATUS = -1,當還有下一行數據的時候,@@FETCH_STATUS = 0
while @@FETCH_STATUS = 0
begin
select @EmpCode, @EmpName, @EmpAddress
fetch curEmployee into @EmpCode, @EmpName, @EmpAddress
end
-- 關閉遊標
close curEmployee
-- 刪除遊標
deallocate curEmployee
第十問:來我們說道說道事務處理
含義
通過一組邏輯操作單元(一組DML——sql語句),將數據從一種狀態切換到另外一種狀態
特點
(ACID)
原子性:要麼都執行,要麼都回滾
一致性:保證數據的狀態操作前和操作後保持一致
隔離性:多個事務同時操作相同數據庫的同一個數據時,一個事務的執行不受另外一個事務的干擾
持久性:一個事務一旦提交,則數據將持久化到本地,除非其他事務對其進行修改
相關步驟:
1、開啓事務
2、編寫事務的一組邏輯操作單元(多條sql語句)
3、提交事務或回滾事務
事務的分類:
隱式事務,沒有明顯的開啓和結束事務的標誌
比如
insert、update、delete語句本身就是一個事務
顯式事務,具有明顯的開啓和結束事務的標誌
1、開啓事務
取消自動提交事務的功能
2、編寫事務的一組邏輯操作單元(多條sql語句)
insert
update
delete
3、提交事務或回滾事務
使用到的關鍵字
set autocommit=0;
start transaction;
commit;
rollback;
savepoint 斷點
commit to 斷點
rollback to 斷點
事務的隔離級別:
事務併發問題如何發生?
當多個事務同時操作同一個數據庫的相同數據時
事務的併發問題有哪些?
髒讀:一個事務讀取到了另外一個事務未提交的數據
不可重複讀:同一個事務中,多次讀取到的數據不一致
幻讀:一個事務讀取數據時,另外一個事務進行更新,導致第一個事務讀取到了沒有更新的數據
如何避免事務的併發問題?
通過設置事務的隔離級別
1、READ UNCOMMITTED
2、READ COMMITTED 可以避免髒讀
3、REPEATABLE READ 可以避免髒讀、不可重複讀和一部分幻讀
4、SERIALIZABLE可以避免髒讀、不可重複讀和幻讀
設置隔離級別:
set session|global transaction isolation level 隔離級別名;
查看隔離級別:
select @@tx_isolation;