亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

帶你深入了解"T-SQL"的十一種設計模式

2024-07-21 02:43:46
字體:
來源:轉載
供稿:網友
一、ITERATOR(迭代)

這種模式提供一種在相似對象列表中遍歷對象的標準化方法。在SQL Server數據庫中的同義詞是游標。

DECLARE tables CURSOR

FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

FOR READ ONLY

DECLARE @table varchar(40)

OPEN tables

FETCH tables INTO @table

WHILE (@@FETCH_STATUS = 0)

BEGIN

EXEC sp_help @table

FETCH tables INTO @table

END

CLOSE tables

DEALLOCATE tables

注:游標的清理代碼:在CLOSE后緊跟DEALLOCATE,實際上可以只運行DEALLOCATE,并且游標也能自動關閉。但這不是最自然,也不是最常見的方法。大家可以理解為:CLOSE抵消OPEN,DEALLOCATE與DECLARE則相反,這樣可以使代碼保持對稱并且合乎邏輯。

二、INTERSECTOR(交集)

這種模式是表示集合交集的一種模板。

1、推薦方法:

SELECT c.companyname,o.orderid

FROM customer c INNER JOIN orders o ON c.customerid = o.customerid

2、舊式語法(不推薦使用)

SELECT c.companyname,o.orderid

FROM customer c ,orders o

WHERE c.customerid = o.customerid

注:實現集合交集還有許多變種方法。但是慣例方法就是方法1,方法2在實現左(右)聯接時,條件的表示及結果都可能出現問題,SQL SERVER的后續版本將會取消此種聯接方式。

三、QUALIFIER(限定)

限定數據等價于篩選查詢所返回的行數。

1、常用法:WHERE子句限定

SELECT city,count(*) AS NumberCity

FROM customers

WHERE city like 'A%'

GROUP BY city

2、不自然的篩選:HAVING子句限定

SELECT city,count(*) AS NumberCity

FROM customers

GROUP BY city

HAVING city like 'A%'

注:HAVING子句的目的是在結果集被檢索出來后再篩選查詢。實際上,SQL SERVER內在地轉換HAVING子句為WHERE子句(兩種方法查詢的執行計劃是相同的),如果SQL SERVER不執行此優化,則針對包含大量數據行的表,因需要在篩選前從表中檢索所有行,則性能方面可能會遭受重大損失。

四、EXECTOR(運行)

提供創建并執行動態T-SQL字符串的模板

--中斷除當前連接之外的所有用戶連接

DECLARE @s int,@sql nvarchar(128)

DECLARE spids CURSOR FOR

SELECT spid

FROM master..sysPRocesses

WHERE spid <> @@SPID AND net_address<>''

FOR READ ONLY

OPEN spids

FETCH spids INTO @s

WHILE (@@FETCH_STATUS = 0)

BEGIN

SET @sql = 'KILL ' + CAST(@s AS varchar)

EXEC sp_executesql @sql

FETCH spids INTO @s

END

CLOSE spids

DEALLOCATE spids

注:上述語句中的sp_executesql可以用exec()替換,但推薦使用sp_executesql,因為與exec()相比,sp_executesql支持參數化查詢,并可從動態T-SQl調用返回一個結果代碼。如果動態代碼產生一個嚴重級達到或超過11的錯誤,sp_executesql將在它的結果代碼中返回錯誤碼。

五、Conveyor(傳送)

提供一種通過存儲過程鏈傳送信息的機制。與GoF的責任鏈模式(Chain of Responsibility)相類似。

1、傳送返回碼

CREATE PROC procC

AS

IF OBJECT_ID('no_exist') IS NOT NULL

SELECT * FROM no_exist

ELSE

RETURN (-1)

GO

CREATE PROC procB

AS

DECLARE @res int

EXEC @res = procC

RETURN (@res)

GO

CREATE PROC procA

AS

DECLARE @res int

EXEC @res = procB

SELECT @res

GO

EXEC procA

注:上述代碼使用了存儲過程的結果代碼從過程向過程傳遞原始返回碼的方法,即A調用B,B又調用C,C運行時如出現了錯誤,則將錯誤代碼-1傳送給A。

2、通過輸出參數傳送消息

CREATE PROC procC

@msg varchar(128) OUT

AS

IF OBJECT_ID('no_exist') IS NOT NULL

SELECT * FROM no_exist

ELSE

SET @msg = 'Table dosen''t exist!'

GO

CREATE PROC procB

@msg varchar(128) OUT

AS

EXEC procC @msg OUT

GO

CREATE PROC procA

AS

DECLARE @msg varchar(128)

EXEC procB @msg OUT

SELECT @msg

GO

EXEC procA

注:可以使用任何數據類型(包括游標)來返回任何想要的信息

3、傳送真實錯誤代碼

CREATE PROC procC

AS

DECLARE @err int

IF @@TRANCOUNT = 0 --此全局變量返回當前連接的活動事務數

ROLLBACK TRAN --有意設置的出錯語句,因未使用BEGIN TRANSACTION語句

SET @err = @@ERROR

RETURN (@err)

GO

CREATE PROC procB

AS

DECLARE @res int

EXEC @res = procC

RETURN (@res)

GO

CREATE PROC procA

AS

DECLARE @res int

EXEC @res = procB

SELECT @res

GO

EXEC procA

六、Restorer(恢復)

此模式提供一種在出錯時清理資源的機制。為避免孤立一個事務,當事務活動時,適當地處理出錯條件極其重要。

1、出錯時回滾事務

IF OBJECT_ID('procR') IS NOT NULL

DROP PROC procR

GO

CREATE PROC procR

AS

DECLARE @err int

BEGIN TRAN

UPDATE customers SET city = 'Dallas'

SELECT 1/0 --設置一個錯誤

SET @err = @@ERROR

IF @err <> 0

BEGIN

ROLLBACK TRAN

RETURN (@err)

END

COMMIT TRAN

GO

DECLARE @res int

EXEC @res = procR

SELECT @res

注:此模式的關鍵部分是將錯誤碼@@error緩存至變量@err中,如果不緩存@@error,下一執行成功的語句將重置@@error,緩存它后,如出現錯誤,將檢查@errr的值并回滾該活動事務。

2、出錯時清除臨時表

CREATE PROC procR

AS

DECLARE @err int

CREATE TABLE ##myglobal(c1 int)

INSERT ##myglobal DEFAULT VALUES

SELECT 1/0 --設置一個錯誤

SET @err = @@ERROR

IF @err <> 0

BEGIN

DROP TABLE ##myglobal

RETURN (@err)

END

DROP TABLE ##myglobal

GO

DECLARE @res int

EXEC @res = procR

SELECT @res

3、主動執行恢復模式

CREATE PROC procR

AS

IF @@TRANCOUNT <> 0 --啟動新事務前先回滾舊事務

ROLLBACK TRAN

DECLARE @err int

BEGIN TRAN

UPDATE customers SET city = 'Dallas'

SELECT 1/0 --設置一個錯誤

SET @err = @@ERROR

IF @err <> 0

BEGIN

ROLLBACK TRAN

RETURN (@err)

END

COMMIT TRAN

GO

DECLARE @res int

EXEC @res = procR

SELECT @res

注:通過@@TRANCOUNT<>0可知有活動事務,執行ROLLBACK回滾當前活動連接的所有事務。當SQL Server使用連接池時(對WEB服務器而言相當常見),

在實際應用中編寫此種邏輯就非常重要。由于一個虛連接可以留下一個打開的事務,該事務會影響使用同一物理連接的后續用戶,因此,通過主動地

執行Restorer模式,讓代碼知道如何保護自己免受“無賴”事務和其他意外殘余的影響。

重要提示

T-SQL的錯誤處理結構也并非無懈可擊,它經常不是按預期的方式或它應該的方法運行。例如,存在許多嚴重的足以中斷當前命令批處理的錯誤,當這些錯誤出現時,它讓那些可能緊跟在其后的錯誤處理代碼根本沒有機會去執行。因此,當出現問題時,即使使用@@ERROR執行代碼檢查并調用ROLLBACK,還會有錯誤禁止ROLLBACK執行。這可能是導致孤立事務存在的根本原因,而且也是在開始一個事務前應檢查孤立事務的原因?!?

七、PROTOTYPE(原型)

此模式的目標:使用一種原型實例指定要創建對象的類型,并且通過復制原型創建新的對象。

1、最常見的實現方式是SELECT...INTO結構

SELECT *

INTO newCustomers

FROM Customers

SELECT *

INTO newCustomers

FROM Customers

WHERE country='UK'

注:通過指定一個列列表、WHERE子句、GROUP BY或HAVING子句,可在傳送過程中修改原型。

2、復制表結構(T-SQL慣例中也曾提過)

SELECT *

INTO newCustomers

FROM Customers

WHERE 1 = 2

SELECT TOP 0 *

INTO newCustomers

FROM Customers

注:通過錯誤的WHERE條件或不存在的行實現了復制表結構的功能

3、復制表時指定新數據

SELECT IDENTITY(int,1,1) AS CustNo,*

INTO newCustomers

FROM Customers

注:還可指定新列、通過聯接選取來自其他表或視圖的列、約束或函數等許多的可能性。

八、Singleton(單例)

此模式目標:確保在任何給定時間只存在一個類實例并且提供訪問該實例的路徑。

嚴格說,在關系數據庫中,對于面向對象類的等價物是表。類的一個實例就是表中的一行。因此,Singleton模式的最顯而意見的實現就是確保表中只包含一行。

CREATE TABLE LastCustNo

(LastCustNo int)

GO

INSERT LastCustNo VALUES(1)

GO

CREATE TRIGGER LastCustNoInsert ON LastCustNo

FOR INSERT

AS

IF (SELECT COUNT(*) FROM LastCustNo) > 1

BEGIN

RAISERROR('You May Not insert more than one row into this table!',16,10)

ROLLBACK TRAN

END

GO

INSERT LastCustNo VALUES(2) --由于觸發器的原因,插入失敗

GO

SELECT * FROM LastCustNo

注:由于觸發器的原因,在任何時刻只允許在表中插入一行,如果表中已包含至少一行,在試圖插入新的一行時將導致錯誤并回滾事務。

(1)IF (SELECT COUNT(*) FROM LastCustNo)必須用 > 1 ,而不能用=1,因為除Instead Of觸發器外,T-SQL觸發器只在操作已完成,但還沒提交給數據庫前運行,這表明從觸發器角度看,在事務回滾前,LastCustNo表看起來總是包含兩行。

(2)禁止使用IF EXISTS(SELECT COUNT(*) FROM LastCustNo)測試表中的行,因對于觸發器來說,新插入的行直到事務被回滾才出現在表中,因此,即使在插入前表為空,也將禁止向表中插入行。

實際應用:禁止一個應用的多個實例連接至服務器

方法1:應用程序鎖

--鎖定應用程序資源

DECLARE @res int

BEGIN TRAN

EXEC @res = sp_getapplock @Resource = 'Check Writer',@LockMode = 'Exclusive'

--返回到應用程序

--當檢測到應用程序時執行以下代碼(釋放鎖資源)

EXEC @res = sp_releaseapplock @Resource = 'Check Writer'

ROLLBACK TRAN

注:可在啟動應用程序時啟用一個鎖,在關閉時釋放該鎖。通過以獨占方式啟用鎖,可在釋放該鎖前禁止運行應用程序的另一個實例。

但這種方法讓一個事務長期保持為打開狀態。一般來說,不應該長時間或當一個用戶被提示輸入時讓一個事務保持打開狀態。

方法2:使用SET CONTEXT_INFO(推薦方法)

IF EXISTS (SELECT * FROM master..sysprocesses WHERE context_info = 0x123456)

RAISERROR('You Can run only one copy of this application at a time',20,1) WITH LOG

ELSE

SET CONTEXT_INFO 0x123456

注:使用SET CINTEXT_INFO命令在啟動時間向sysprocesses插入一個用戶自定義值,每次啟動程序時檢查該值,如果存在,則包含特定的記號連接已存在,因此產生一個錯誤并中止自己的連接。如不存在,則將該值保存在sysprocesses中,并繼續加載應用。

九、FACADE(外觀)

此模式目標:它給位于子系統的一個接口集合提供統一的接口。

在T-SQL中與此模式類似的是包含INSTEAD OF觸發器的視圖(INSTEAD OF觸發器接受對視圖的更新,并將它們分配給適當的底層表)。

CREATE TABLE AussieArtists

(ArtistID int identity,

LastName varchar(30),

FirstName varchar(30))

GO

INSERT AussieArtists VALUES('Gibb','Barry')

INSERT AussieArtists VALUES('Crowe','Russell')

INSERT AussieArtists VALUES('Hogan','Paul')

GO

CREATE VIEW VAussieArtists

AS

SELECT FirstName + '' + LastName AS Name FROM AussieArtists

GO

CREATE TRIGGER VAussieArtists_Insert ON VAussieArtists INSTEAD OF INSERT

AS

INSERT AussieArtists(FirstName,LastName)

SELECT LEFT(Name,ISNULL(NULLIF(CHARINDEX(' ',NAME),0),255)-1),

SUBSTRING(Name,NULLIF(CHARINDEX(' ',Name),0)+1,255)

FROM inserted

GO

INSERT VAussieArtists(Name) VALUES('Gerg Ham')

GO

SELECT * FROM AussieArtists

GO

DROP TABLE AussieArtists

DROP VIEW VAussieArtists

GO

注:因想在加入到基表前處理數據,所以使用INSTEAD OF觸發器分析輸入并執行插入數據,即對視圖的簡單插入被轉換為對基表稍微復雜一些的插入。

十、Chain Of Responsibility(職責鏈)

此模式目標:為避免通過多個對象提供機會處理請求,合并請求的發送者與接收者。為實現該模式,必須串聯接收對象并沿此鏈傳送請求,直到某個對象處理它。

前面的Conveyor模式已接到責任鏈模式,這里再作深入討論。在T-SQL中最接近此模式所描述行為的是嵌套觸發器(觸發器的執行導致其他觸發器激活并實現串聯行為的操作)。

CREATE TABLE employee (id int identity ,name varchar(10))

GO

CREATE TABLE laborage (id int ,salary int)

GO

CREATE TABLE laborage2(id int,number int)

GO

INSERT employee (name) values('zs')

INSERT laborage values(101,101)

INSERT laborage2 values(101,102)

GO

CREATE TRIGGER up_employee ON Employee

FOR UPDATE

AS

UPDATE laborage Set Salary = Salary + 100 WHERE id =101

GO

CREATE TRIGGER up_laborage ON laborage

FOR UPDATE

AS

UPDATE laborage2 SET number = number + 200 WHERE id = 101

GO

UPDATE Employee SET Name = 'Zxm' WHERE id = 1

GO

注:SP_CONFIGURE 'NESTED TRIGGER',0 可以禁止觸發器嵌套,同時觸發器最多嵌套32次。從功能角度考慮,在觸發器未設定激活順序情況下,插入請求從一個觸發器傳送給另一個。在任何情況下,如果其中的任一觸發器拒絕插入并回滾事務,則整個操作都將被取消。

十一、COMMAND(命令)

這種模式目標:將請求一個對象來封裝,允許你參數化包含不同請求、隊列或日志請求的客戶端,并支持可撤消操作。在T-SQL中與此模式對應的是事務。

CREATE PROC prClearLS

@intLsID int

AS

BEGIN TRAN

UPDATE Inventory SET Lease = 0 WHERE LsID = @intLsID

IF @@ERROR <> 0

GOTO PROBLEM

UPDATE LeaseSchedule

SET PeriodTotalAmount = 0

WHERE ScheduleID = @intLsID

IF @@ERROR <> 0

GOTO PROBLEM

COMMIT TRAN

RETURN 0

PROBLEM:

PRINT 'Unable to eliminate lease amounts from the database.'

ROLLBACK TRAN

RETURN 1


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久偷看各类女兵18女厕嘘嘘| 日韩精品免费看| 亚洲精品小视频| 欧美一级在线播放| 成人欧美在线观看| 久久精品视频在线观看| 亚洲视频在线看| 欧美日韩国产中文精品字幕自在自线| 免费不卡在线观看av| 久久这里有精品| 国内免费精品永久在线视频| 91天堂在线视频| 俺去亚洲欧洲欧美日韩| 欧美亚洲日本网站| 国产丝袜一区二区三区| 在线色欧美三级视频| 91亚洲一区精品| 亚洲伊人久久综合| 伊人精品在线观看| 在线播放日韩欧美| 精品国产一区二区在线| 欧美日韩午夜剧场| 亚洲电影免费观看高清| 亚洲综合精品伊人久久| 日韩av在线直播| 亚洲国产成人精品女人久久久| 日韩成人网免费视频| 欧美人交a欧美精品| 成人欧美一区二区三区在线| 日本中文字幕久久看| 91精品视频在线播放| 亚洲国产精品视频在线观看| 92版电视剧仙鹤神针在线观看| 国产视频丨精品|在线观看| 91久久精品美女| 91久久精品国产91久久性色| 91在线无精精品一区二区| 国产视频丨精品|在线观看| 91九色国产在线| 麻豆乱码国产一区二区三区| 成人写真视频福利网| 国产成人精品a视频一区www| 久久久国产成人精品| 91av在线不卡| 精品日韩美女的视频高清| 欧美日韩亚洲一区二区| 成人免费观看49www在线观看| 亚洲欧洲在线免费| 免费99精品国产自在在线| 欧美电影在线免费观看网站| 久久免费精品日本久久中文字幕| 国产亚洲精品久久久优势| 亚洲男人av电影| 欧美一区二区.| 国产精品夜色7777狼人| 亚洲午夜色婷婷在线| 久久久精品国产一区二区| 久久精品久久久久久| 欧美精品在线播放| 欧美人交a欧美精品| 俺也去精品视频在线观看| 成人精品久久一区二区三区| 亚洲自拍中文字幕| 久久国产精品久久久久| 国产精品丝袜久久久久久不卡| 亚洲人成电影在线播放| 亚洲情综合五月天| 欧美最猛性xxxxx(亚洲精品)| 亚洲精品999| 日韩在线观看免费全集电视剧网站| 亚洲欧美在线免费| 亚洲成人精品在线| www.日韩欧美| 亚洲欧洲第一视频| 国产午夜精品一区二区三区| 亚洲深夜福利网站| 日韩av在线影院| 97视频免费在线观看| 国产精品99久久久久久www| 久久精品99无色码中文字幕| 这里只有精品在线播放| 亚洲国产欧美自拍| 亚洲欧美在线第一页| 亚洲天堂av在线免费观看| 国产精品色婷婷视频| 福利视频导航一区| 久久久久久久电影一区| 色播久久人人爽人人爽人人片视av| 欧美日韩性生活视频| 色偷偷亚洲男人天堂| www高清在线视频日韩欧美| 国产精品第一第二| 欧美裸身视频免费观看| 97香蕉超级碰碰久久免费的优势| 成人国内精品久久久久一区| 日韩在线中文字| 97国产精品人人爽人人做| 色综合亚洲精品激情狠狠| 亚洲第一区在线| 久久久亚洲网站| 日韩有码片在线观看| 欧美激情国产高清| 一区二区三区无码高清视频| 日韩av最新在线观看| 亚洲欧美一区二区三区情侣bbw| 亚洲第一精品自拍| 伊人一区二区三区久久精品| 国产日韩欧美日韩大片| 97在线视频免费| 亚洲欧美中文日韩v在线观看| 国内精品免费午夜毛片| 91成品人片a无限观看| 秋霞成人午夜鲁丝一区二区三区| 国产亚洲美女精品久久久| 久久视频在线播放| 亚洲性日韩精品一区二区| 久久成年人免费电影| 欧洲亚洲免费在线| 亚洲午夜精品久久久久久久久久久久| 亚洲美女免费精品视频在线观看| 尤物yw午夜国产精品视频| 色综合久久88| 亚洲一区国产精品| 久久久久久久久电影| 91精品国产自产在线老师啪| 色综合久久精品亚洲国产| 欧美国产日韩精品| 亚洲国模精品私拍| 性欧美激情精品| 亚洲无亚洲人成网站77777| 在线观看91久久久久久| 久久久久久久一| 日韩视频亚洲视频| 国产精品久久久久久久久| 国模视频一区二区三区| 亚洲级视频在线观看免费1级| 自拍偷拍亚洲欧美| 国产精品99免视看9| 亚洲电影免费观看高清完整版在线| 国产精品入口日韩视频大尺度| 国产精品国产三级国产专播精品人| 欧美激情欧美激情| 亚洲一区二区三区乱码aⅴ蜜桃女| 欧美日本高清一区| 欧美日韩国产丝袜另类| 久久综合久久美利坚合众国| 欧美性猛交丰臀xxxxx网站| 欧美高清一级大片| 国产精品久久久久久亚洲调教| 日韩中文字幕av| 精品国产乱码久久久久久虫虫漫画| 久久男人av资源网站| 国产精品都在这里| 亚洲人成电影网站色| 亚洲综合色av| www国产精品com| 精品中文字幕在线| 日本欧美精品在线| 日韩亚洲欧美成人| 91成人免费观看网站| 亚洲欧美日韩国产中文| 亚洲欧美激情另类校园| 亚洲欧美另类人妖| 国产ts人妖一区二区三区|