Sql 中存儲過程詳細案例





轉自:http://www.cnblogs.com/yank/p/4235609.html

概念

存儲過程(Stored Procedure):已預編譯為一個可執行過程的一個或多個SQL語句。 

創建存儲過程語法

復制代碼
CREATE proc | procedure procedure_name [{@參數數據類型} [=默認值] [output], {@參數數據類型} [=默認值] [output], .... ] as SQL_statements
go
復制代碼

存儲過程與SQL語句對比

優勢:

1、提高性能
SQL語句在創建過程時進行分析和編譯。 存儲過程是預編譯的,在首次運行一個存儲過程時,查詢優化器對其進行分析、優化,並給出最終被存在系統表中的存儲計划,這樣,在執行過程時便可節省此開銷。
2、降低網絡開銷
存儲過程調用時只需用提供存儲過程名和必要的參數信息,從而可降低網絡的流量。
3、便於進行代碼移植
數據庫專業人員可以隨時對存儲過程進行修改,但對應用程序源代碼卻毫無影響,從而極大的提高了程序的可移植性。
4、更強的安全性
1)系統管理員可以對執行的某一個存儲過程進行權限限制,避免非授權用戶對數據的訪問
2)在通過網絡調用過程時,只有對執行過程的調用是可見的。 因此,惡意用戶無法看到表和數據庫對象名稱、嵌入自己的 Transact-SQL 語句或搜索關鍵數據。
3)使用過程參數有助於避免 SQL 注入攻擊。 因為參數輸入被視作文字值而非可執行代碼,所以,攻擊者將命令插入過程內的 Transact-SQL 語句並損害安全性將更為困難。
4)可以對過程進行加密,這有助於對源代碼進行模糊處理。 

劣勢:

1、存儲過程需要專門的數據庫開發人員進行維護,但實際情況是,往往由程序開發員人員兼職

2、設計邏輯變更,修改存儲過程沒有SQL靈活

為什么在實際應用中,存儲過程用到相對較少呢?

在通常的項目研發中,用存儲過程卻相對較少,這是為什么呢?
分析原因如下:
1)沒有特定的數據庫開發人員,普通程序員兼職進行數據庫操作
2)程序員往往只需操作程序,即可完成數據訪問,無需再在數據庫上進行開發
3)項目需求變動比較頻繁,修改SQL語句比較方便,特別是涉及邏輯變更 

存儲過程與SQL語句如何抉擇?

基於實際應用的經驗,給予如下建議:

1、在一些高效率或者規范性要求比較高的項目,建議采用存儲過程
2、對於一般項目建議采用參數化命令方式,是存儲過程與SQL語句一種折中的方式
3、對於一些算法要求比較高,涉及多條數據邏輯,建議采用存儲過程

 

存儲過程的具體應用

 一、基礎查詢

1、創建不帶參數的存儲過程

例子:查詢學生總數

復制代碼
--查詢存儲過程 IF OBJECT_ID (N'PROC_SELECT_STUDENTS_COUNT', N'P') IS NOT NULL DROP procedure PROC_SELECT_STUDENTS_COUNT; GO CREATE procedure PROC_SELECT_STUDENTS_COUNT AS SELECT COUNT(ID) FROM Students GO
復制代碼

執行:

EXEC PROC_SELECT_STUDENTS_COUNT

 

2、帶參數的存儲過程

復制代碼
--查詢存儲過程,根據城市查詢總數 IF OBJECT_ID (N'PROC_SELECT_STUDENTS_BY_CITY_COUNT', N'P') IS NOT NULL DROP procedure PROC_SELECT_STUDENTS_BY_CITY_COUNT; GO CREATE procedure PROC_SELECT_STUDENTS_BY_CITY_COUNT(@city nvarchar(50)) AS SELECT COUNT(ID) FROM Students WHERE City=@city GO
復制代碼

執行語句:

EXEC PROC_SELECT_STUDENTS_BY_CITY_COUNT N'Beijing'

3、帶有通配符

通配符,在參數值賦值時,加上相應的通配符

復制代碼
--3、查詢姓氏為李的學生信息,含通配符 IF OBJECT_ID (N'PROC_SELECT_STUDENTS_BY_SURNNAME', N'P') IS NOT NULL DROP procedure PROC_SELECT_STUDENTS_BY_SURNNAME; GO CREATE procedure PROC_SELECT_STUDENTS_BY_SURNNAME @surnName nvarchar(20)='李%' --默認值 AS SELECT ID,Name,Age FROM Students WHERE Name like @surnName GO
復制代碼

執行:

EXEC PROC_SELECT_STUDENTS_BY_SURNNAME EXEC PROC_SELECT_STUDENTS_BY_SURNNAME N'李%' EXEC PROC_SELECT_STUDENTS_BY_SURNNAME N'%李%'

 

4、帶有輸出參數

復制代碼
--根據姓名查詢的學生信息,返回學生的城市及年齡 IF OBJECT_ID (N'PROC_SELECT_STUDENTS_BY_NAME', N'P') IS NOT NULL DROP procedure PROC_SELECT_STUDENTS_BY_NAME; GO CREATE procedure PROC_SELECT_STUDENTS_BY_NAME @name nvarchar(50), --輸入參數 @city nvarchar(20) out, --輸出參數 @age int output --輸入輸出參數 AS SELECT @city=City,@age=Age FROM Students WHERE Name=@name AND Age=@age GO
復制代碼

執行:

復制代碼
--執行 declare @name nvarchar(50), @city nvarchar(20), @age int; set @name = N'李明'; set @age = 20; exec PROC_SELECT_STUDENTS_BY_NAME @name,@city out, @age output; select @city, @age;
復制代碼

二、使用存儲過程進行增刪改

1、新增

新增學生信息 

復制代碼
--1、存儲過程:新增學生信息 IF OBJECT_ID (N'PROC_INSERT_STUDENT', N'P') IS NOT NULL DROP procedure PROC_INSERT_STUDENT; GO CREATE procedure PROC_INSERT_STUDENT @id int, @name nvarchar(20), @age int, @city nvarchar(20) AS INSERT INTO Students(ID,Name,Age,City) VALUES(@id,@name,@age,@city) GO
復制代碼

 執行:

EXEC PROC_INSERT_STUDENT 1001,N'張三',19,'ShangHai'

2、修改

根據學生ID,更新學生信息 

復制代碼
IF OBJECT_ID (N'PROC_UPDATE_STUDENT', N'P') IS NOT NULL DROP procedure PROC_UPDATE_STUDENT; GO CREATE procedure PROC_UPDATE_STUDENT @id int, @name nvarchar(20), @age int, @city nvarchar(20) AS UPDATE Students SET Name=@name,Age=@age,City=@city WHERE ID=@id GO
復制代碼

執行:

EXEC PROC_UPDATE_STUDENT 1001,N'張思',20,'ShangHai'

 

3、刪除

根據ID,刪除某學生記錄

復制代碼
--3、存儲過程:刪除學生信息 IF OBJECT_ID (N'PROC_DELETE_STUDENT_BY_ID', N'P') IS NOT NULL DROP procedure PROC_DELETE_STUDENT_BY_ID; GO CREATE procedure PROC_DELETE_STUDENT_BY_ID @id int AS DELETE FROM Students WHERE ID=@id GO
復制代碼

執行:

EXEC PROC_DELETE_STUDENT_BY_ID 1001

 

 三、存儲過程實現分頁查詢

1、使用row_number函數分頁

復制代碼
--分頁查詢 IF OBJECT_ID (N'PROC_SELECT_BY_PAGE', N'P') IS NOT NULL DROP procedure PROC_SELECT_BY_PAGE; GO CREATE procedure PROC_SELECT_BY_PAGE @startIndex int, @endIndex int AS SELECT * FROM (SELECT ID,Name,Age,City,ROW_NUMBER() OVER(ORDER BY ID DESC) AS RowNumber FROM Students) AS Temp WHERE Temp.RowNumber BETWEEN @startIndex AND @endIndex GO
復制代碼

執行:

EXEC PROC_SELECT_BY_PAGE 1,10

2、使用傳統的top分頁

復制代碼
--使用TOP分頁 IF OBJECT_ID (N'PROC_SELECT_BY_PAGE_WITH_TOP', N'P') IS NOT NULL DROP procedure PROC_SELECT_BY_PAGE_WITH_TOP; GO CREATE procedure PROC_SELECT_BY_PAGE_WITH_TOP @pageIndex int, @pageSize int AS SELECT TOP(@pageSize) * FROM Students WHERE ID >=(SELECT MAX(ID) FROM (SELECT TOP(@pageSize*(@pageIndex-1) + 1) ID FROM Students ORDER BY ID) AS Temp) GO
復制代碼

執行:

EXEC PROC_SELECT_BY_PAGE_WITH_TOP 1,2

 

四、其他功能:

1、存儲過程,每次執行都進行重新編譯

復制代碼
--1、存儲過程,重復編譯 IF OBJECT_ID (N'PROC_SELECT_STUDENTS_WITH_RECOMPILE', N'P') IS NOT NULL DROP procedure PROC_SELECT_STUDENTS_WITH_RECOMPILE; GO CREATE procedure PROC_SELECT_STUDENTS_WITH_RECOMPILE with recompile --重復編譯 AS SELECT * FROM Students GO
復制代碼

 

2、對存儲過程進行加密

加密后,不能查看和修改源腳本

復制代碼
--2、查詢存儲過程,進行加密 IF OBJECT_ID (N'PROC_SELECT_STUDENTS_WITH_ENCRYPTION', N'P') IS NOT NULL DROP procedure PROC_SELECT_STUDENTS_WITH_ENCRYPTION; GO CREATE procedure PROC_SELECT_STUDENTS_WITH_ENCRYPTION with encryption --加密 AS SELECT * FROM Students GO
復制代碼

執行:

EXEC PROC_SELECT_STUDENTS_WITH_ENCRYPTION

效果,無法查看腳本或者導出創建腳本

 

作者介紹:半路學IT,做開發3年,先就職在一家共享單車公司,做后台開發!

 我開了一個公眾號,歡迎各位有志同道合朋友,關注!不定期分享干活,和我得故事!

分類: 數據庫技術


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM