什么是存儲過程
SQL 存儲過程(Stored Procedure)是一個在數據庫中預編譯并存儲的一組 SQL 語句。它們可以包含查詢、插入、更新、刪除等數據庫操作,甚至包括控制流語句(如條件判斷、循環等)。存儲過程可以通過調用來執行,而不需要每次都重新編寫和執行 SQL 語句。
分類
-
系統存儲過程
是再master數據庫中,其他數據庫可以直接使用系統存儲過程
再新的數據庫中會自動創建
調用時,不需要加數據庫名稱 -
自定義存儲過程
開發者自己創建的
可以傳參 也可以有返回值
怎么標明存儲過程是否執行成功
print 日志 查看日志即可
存儲過程內部可以寫什么?
一個或者多個操作
存儲過程與表之間的關系是什么?
存儲過程依賴表的存在,如果存儲中依賴的表刪除了,那么存儲過程也就失效了
關系:操作與被操作的關系
執行:exec/execute 存儲過程名參數列表(多個參數,用逗號分割)
存儲過程的優缺點是什么?
優點:提高了程序的可復用性,減少腳本冗余
提高了管理數據庫的效率
提高了執行sql的熟讀
減輕了服務器的負擔
缺點:需要專門維護,占用數據庫空間,
存儲過程的優點:
性能提升:
存儲過程是在數據庫中編譯并優化過的,因此執行時可以比單獨的 SQL 查詢更高效。因為在執行時,SQL
語句已經預編譯,避免了重復解析和優化的開銷。
重用性:
存儲過程是可重用的,可以通過調用存儲過程多次執行相同的操作,而無需重復編寫相同的 SQL 語句。
封裝性:
存儲過程將數據庫邏輯封裝起來,使得應用程序與數據庫操作解耦,減少了應用程序和數據庫之間的依賴。
安全性:
通過限制應用程序對數據庫表的直接訪問,存儲過程可以提供更好的安全性。用戶只需要權限調用存儲過程,而無需直接訪問底層數據表。
事務管理:
存儲過程支持事務管理,可以確保一組操作要么全部成功,要么全部失敗(原子性)。這使得數據的一致性得到了保障。
定義存儲過程 名稱:建議以為 Proc開頭
create proc Proc_gen_orderNo
as
begin -- {
-- 這里編寫執行邏輯
print '開始執行...'
select * from BookInfos
select * from BookShellInfos
print '存儲過程執行完畢'
end --}
---- bug: 如果 存儲過程已經存在,執行新建報錯觸發存儲過程
exec Proc_gen_orderNo
練習:
完成自動生成訂單編號的邏輯:
訂單編號:2025062600001 202506260002 202506260003
前8位:插入數據的日期
后5位:訂單編號的流水號碼
思考問題:
如果獲取當前時間編號?
select convert(varchar(255),getDate(),112) -- 20250626
如何查詢最后一條記錄的編號?
方式一:
declare @lastNo varchar(255)
select @lastNo=orderNo from orderTable
問題:數據只有幾百條,沒有影響,
假如每天都產生上萬個訂單,如果查全部,查詢的時間,一天比一天慢
優化:查詢今天的數據,倒序排序,在查第一條,== 今天最后一個點單
方式二:
select top 1 @lastNo=orderNo from orderTable where substring(orderNo,1,8) = @ starTimespan
order by orderId desc;
如何生成新的編號
新編號
set @No = @starTimespan + '00001'
編號已經存在,怎么驗證編號已經存在,如何再已存在編號基礎上進行生成
create proc Proc_gen_orderNo
as
begin-- 1:聲明完成整個過程需要的變量declare @No varchar(255) -- 執行后,生成的編號declare @starTimespan varchar(255) -- 當前時間,時間編號declare @lastNo varchar(255) -- 最后一條記錄的訂單編號-- 2:給變量初始化賦值set @starTimespan = convert(varchar(255),getDate(),112) -- 時間編號-- 找到最后一條記錄的編號select top 1 @lastNo=orderNo from orderTablewhere substring(orderNo,1,8) = @starTimespan order by orderId desc -- 3:生成新的編號-- 3.1 如果最后一條記錄不存在if @lastNo is nullbeginset @No = @starTimespan + '00001'insert into orderTable(orderNo) values(@No)print '第一個訂單已產生' endelse begin -- 存在最后一條記錄print '今天已經有了訂單'declare @lastNo_ int -- 當前生成記錄的尾號declare @tmpNo varchar(255) -- 編號尾號字符串類型declare @tmpLen int; -- 字符尾號的長度declare @n int -- 循環次數set @n = 0; --設置循環次初始值print substring(@lastNo,9,5)-- 求當前訂單,流水的序號set @lastNo_ = convert(int, substring(@lastNo,9,5)) +1 print @lastNo_-- 將流水序號,轉化為字符串類型set @tmpNo = convert(varchar(10),@lastNo_)-- 當前字符流水的長度。set @tmpLen = len(@tmpNo)print @tmpLen-- 求流水號前面拼接幾個0,流水號總長度為5.while(@n<5-@tmpLen)beginSET @tmpNo = '0' + @tmpNoset @n +=1end-- 生成新的編號set @No = @starTimespan + @tmpNoprint @No-- 插入數據insert into orderTable(orderNo) values(@No)endend
-- 1:執行新建 存儲過程
-- 2:觸發存儲過程。exec Proc_gen_orderNo