日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

数据库工程开发秘籍之TSQL 存储过程user stored procedure的概念与案例实战

發布時間:2024/9/27 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库工程开发秘籍之TSQL 存储过程user stored procedure的概念与案例实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

TSQL存儲過程概念與案例實戰

存儲過程

存儲過程由一個或多個 T-SQL 語句或對.NET公共語言運行時 (CLR) 方法的引用所構成的一組程序塊。這里的T-SQL語句包括執行DDL、DML語句、應用臨時表、動態SQL、定義異常處理等。但是相比于函數,它不能嵌套在查詢里,但它可以調用其它的存儲過程,即存儲過程可以相互調用。

存儲過程和常見的程序語言類似,可以指定輸入和輸出參數。SQL Server通過緩存存儲過程的執行計劃進而達到節約時間、降低CPU、內存的目的。

存儲過程相對于在應用端實現業務邏輯有以下好處:

1 通過封裝實現重用性和邏輯復雜性的隱藏。僅需要通過存儲過程的修改(alter procedure)就能應用新的邏輯。

2 減少網絡的傳輸,這是因為存儲過程即存儲在數據庫里,而如果是應用程序方式訪問數據庫識別有網絡傳輸的成本。

3 存儲過程可以提供對數據庫進行安全的訪問,即賦予了執行存儲過程的用戶不能直接訪問底層的數據庫對象,這種隔離對數據庫提供了保障。

補注:盡管存儲過程有這些優點,但實際應用程序封裝在Service(服務層),其對應的是某些單獨的SQL邏輯,而如果都放在存儲過程則會出現靈活性差、代碼難維護的情況。

普通存儲過程

假設我們有一張tb_user表,有兩個字段id,name,如果我想通過傳參數的形式給這張表插入數據,那么我們可以通過存儲過程來實現。這里id需要沿著tb_user的最大的值往下自增,自增間隔是1。

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[usp_useradd_MS] (@username VARCHAR(100)) AS DECLARE @max_id int=0 DECLARE @has int=0 BEGIN SELECT @max_id=max(id) FROM tb_user ; SELECT @has=1 FROM tb_user WHERE name = @username;IF @has =0BEGININSERT INTO tb_user VALUES(@max_id+1,@username);END;END; GO--調用,可選用下列任一方式執行 exec usp_useradd_MS 'Mike' exec usp_useradd_MS @username='John' --驗證結果 SELECT * FROM tb_user;

存儲過程與動態SQL

所謂動態SQL即SQL的內容是靈活的,是通過字符串拼接出來的,可以理解是不固定的。比如有一個需求,我們想通過查詢指定表的字段名并以列的形式展示出來,這里就可以通過存儲過程結合動態SQL來實現。因為每次傳過來的參數即表名是不固定的,所以需要一個字符串變量拿到參數里的值再拼接成最終的sql(相對于翻譯一下),再去數據庫里執行。

CREATE PROCEDURE [dbo].[usp_getColumnsBycolumn]( @tabname VARCHAR(100)) AS DECLARE @sql VARCHAR(8000) DECLARE @STRING VARCHAR(500) BEGIN SELECT @sql= ISNULL(@sql+',','')+'['+CAST(COLID AS VARCHAR(12))+']' FROM SYSCOLUMNS WHERE ID = OBJECT_ID(@tabname) GROUP BY COLID SET @STRING='SELECT * FROM (SELECT NAME,COLID FROM SYSCOLUMNS WHERE ID=OBJECT_ID('''+@tabname+'''))A pivot (MAX(NAME) for COLID in('+@sql+'))t' EXEC(@STRING) END GO --調用及結果 exec usp_getColumnsBycolumn 'tb_user'

存儲過程內調用存儲過程

存儲過程里是可以調用其它存儲過程的,有時一些復雜的邏輯需要多個存儲過程結合一起才能實現最終效果。

CREATE PROCEDURE [dbo].[usp_getColumnsByonecolumn]( @tabname VARCHAR(100)) AS DECLARE @tab Table (colid varchar(100),colname varchar(20)) BEGIN INSERT INTO @tab exec usp_getColumnsBycolumn @tabname SELECT colid FROM @tab END --調用 exec usp_getColumnsByonecolumn 'tb_user' -- 結果

注意:我們不可以把存儲過程包裹在子查詢里,即如下方式查詢存儲過程的結果是不支持的。

SELECT?*?FROM(exec?usp_getColumnsBycolumn?'tb_user')A

系統函數查看存儲過程的定義

可以通過內置的系統函數sp_helptext查看存儲過程的文本定義。

sp_helptext @objname = N'usp_getColumnsByonecolumn' #結果,存儲過程的文本定義見下: CREATE PROCEDURE [dbo].[usp_getColumnsByonecolumn]( @tabname VARCHAR(100)) AS DECLARE @tab Table(colid varchar(100), colname varchar(20)) BEGIN INSERT INTO @tab exec usp_getColumnsBycolumn @tabname SELECT colid FROM @tab END

存儲過程的安全性

存儲過程跟表、視圖一樣首先用戶和角色,賦予EXECUTE權限后才能執行。特別的,如果過程里用到非dbo的schema(架構)那么在賦予存儲過程權限后也要將該架構下表的訪問權限賦予用戶,否則存儲可以執行但是會報底層表訪問權限的錯誤。

CREATE LOGIN db_loginuser WITH PASSWORD = 'D#2$3)5b'; GO CREATE USER db_user FOR LOGIN db_loginuser; GO EXECUTE AS LOGIN = 'db_loginuser'; SELECT SUSER_NAME() AS [login], USER_NAME() AS [user];

exec usp_useradd_MS 'Alice'

?

REVERT; SELECT SUSER_NAME() AS [login], USER_NAME() AS [user];

GRANT EXEC ON dbo.usp_useradd_MS TO db_user; EXECUTE AS LOGIN = 'db_loginuser'; SELECT SUSER_NAME() AS [login], USER_NAME() AS [user]; exec usp_useradd_MS 'Alice'

?

REVERT; SELECT * FROM tb_user

:針對sa、dbo無法執行,即無法通過下列的語句切換到sa用戶

EXECUTE?AS?LOGIN?=?'sa';

EXECUTE?AS?LOGIN?=?'dbo';

可通過REVERT;語句切換到上一次的用戶執行環境。

存儲過程與事務

事務是一個工作整體,它包含一個或多個操作數據(可能還包括數據結構)的活動。比如我們建表的DDL語句就是一個事務,要么建表成功要么失敗,不存在中間狀態。事務具有ACID性,其中A(atomicity)即原子性、C(consistency)即一致性、I(isolation)隔離性、D(durability)持久性。

SQL Server事務分為隱性事務和顯性事務的,如果是隱性的可通過SET IMPLICIT_TRANSACTIONS ON;開關打開該選項,在該模式下只需要在要操作的事務的尾部編寫commit或者rollback即可提交或者回滾事務,而不用在事務開頭寫begin tran。相對的顯式事務需要在事務前后定義諸如BEGIN TRAN … COMMIT TRAN(ROLLBACK TRAN)

隱式事務的例子:

SET IMPLICIT_TRANSACTIONS ON select @@TRANCOUNT INSERT INTO tb_user VALUES(110,'Philips') select @@TRANCOUNT -- 注:以上代碼需要一起執行。 -- 查看插入的數據 SELECT * FROM tb_user A WHERE A.name = 'Philips' --這里如果回滾則數據不存在。 ROLLBACK

以回滾為例演示在存儲過程里如何使用事務。如果傳入的參數(用戶名)是'Lily'則回滾,其它則插入并提交事務。

CREATE PROCEDURE [dbo].[usp_useradd_MS_trans](@username VARCHAR(100)) AS BEGIN print @username; if @username='Lily' BEGIN BEGIN TRAN exec usp_useradd_MS @username ROLLBACK TRAN END ELSE BEGIN exec usp_useradd_MS @username END END GO -- 執行與結果 EXEC usp_useradd_MS_trans 'Lily' EXEC usp_useradd_MS_trans 'Tim'

SELECT?*?FROM?tb_user?A?WHERE?A.name?=?'Lily'

SELECT?*?FROM?tb_user?A?WHERE?A.name?=?'Tim'

總結

以上是生活随笔為你收集整理的数据库工程开发秘籍之TSQL 存储过程user stored procedure的概念与案例实战的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。