SQL總結——存儲過程

SQL總結(五)存儲過程

概念

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

建立存儲過程語法

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

存儲過程與SQL語句對比

優點:算法

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

劣勢:安全

一、存儲過程須要專門的數據庫開發人員進行維護,但實際狀況是,每每由程序開發員人員兼職網絡

二、設計邏輯變動,修改存儲過程沒有SQL靈活函數

爲何在實際應用中,存儲過程用到相對較少呢?

在一般的項目研發中,用存儲過程卻相對較少,這是爲何呢?
分析緣由以下:
1)沒有特定的數據庫開發人員,普通程序員兼職進行數據庫操做
2)程序員每每只需操做程序,便可完成數據訪問,無需再在數據庫上進行開發
3)項目需求變更比較頻繁,修改SQL語句比較方便,特別是涉及邏輯變動 性能

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

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

一、在一些高效率或者規範性要求比較高的項目,建議採用存儲過程
二、對於通常項目建議採用參數化命令方式,是存儲過程與SQL語句一種折中的方式
三、對於一些算法要求比較高,涉及多條數據邏輯,建議採用存儲過程加密

 

存儲過程的具體應用

 1、基礎查詢spa

一、建立不帶參數的存儲過程

例子:查詢學生總數

--查詢存儲過程
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

二、帶參數的存儲過程

--查詢存儲過程,根據城市查詢總數
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;
複製代碼
2、使用存儲過程進行增刪改

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
 

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

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
 

4、其餘功能:

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
效果,沒法查看腳本或者導出建立腳本
相關文章
相關標籤/搜索