很久沒寫點什麼了。。。sql
前些時間,與一多年前在北京共事過的略帶親戚關係的同事閒聊了會。數據庫
在北京那時,他們的主要是用Delphi語言,數據庫是MSSqlServer。服務器
他沒有大學學歷,甚至好像高中學歷都沒有,成長過程比較勵志,工廠流水線、理髮師、賣東西神馬的都幹過!!!性能
他是公司的主程,負責某行業管理軟件、呼叫中心等系統,最讓我佩服的,是他對MSSqlServer的熟悉程度,對我而言,膜拜之也並不過度。日誌
===============================================================================對象
聽他說,他們如今作B/S時,已經在用.Net了,多年前,也聽他們提過,說想轉到C#。blog
不過,當聊到開發方式時,我卻震驚了:由於對C#還不是很熟悉,因此,全部的CURD、全部的業務邏輯,統統用存儲過程來實現。C#沒有業務邏輯,各類數據操做都調用存儲過程來實現。索引
順便貼了一個存儲過程給我,只是一個刪數據的存儲過程。ip
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[up_DeleteTravelLineType]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[up_DeleteTravelLineType] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /* ============================================= -- Author: LSH -- Create date: 2013-12-31 -- Description: 線路類型,(暫時不容許刪除有線路的類型)當存在下屬從表數據時,若是 @DeleteChild = 1 則刪除下屬信息,不然,返回 50005 錯誤碼。 -- 調用示例 DECLARE @ErrCode int, @ReturnMsg nvarchar(256) SET @=0; EXEC @ErrCode = up_DeleteTravelLineType @Code = NULL, @DeleteChild = 0, @Operator = '', @ReturnMsg = @ReturnMsg output, @Language = '簡體中文' IF @ErrCode = 0 SELECT * FROM OperationLog WHERE LogType = 'TravelLineType' AND KeyValue = @ ELSE PRINT CONVERT(varchar(10), @ErrCode)+': '+ CASE @ErrCode WHEN 0 THEN CASE @ReturnMsg WHEN 0 THEN '數據無變化' ELSE @ReturnMsg+' 行數據受影響' END WHEN 50001 THEN @ReturnMsg+' 不能爲空' --@ReturnMsg 輸出對應的參數名稱(不帶 @ 符號)。 WHEN 50002 THEN @ReturnMsg+' 已存在' --@ReturnMsg 輸出不能重複的值。 WHEN 50003 THEN 'Code '+@ReturnMsg+' 不存在' --@ReturnMsg 輸出主鍵對應的參數值。 WHEN 50004 THEN @ReturnMsg+' 指定了無效值' --@ReturnMsg 輸出對應的參數名稱(不帶 @ 符號)。 WHEN 50005 THEN '當前數據下包含至少一個 '+@ReturnMsg --@ReturnMsg 輸出對應的子數據表名。 WHEN 50006 THEN @ReturnMsg+' 引用了不存在的主表數據' --@ReturnMsg 輸出對應的參數名稱(不帶 @ 符號)。 WHEN 50007 THEN ' 數據在上次加載後已被修改,修改時間爲: '+@ReturnMsg -- @ReturnMsg 輸出最後的修改日期。 WHEN 50008 THEN @ReturnMsg+' 須要使用當前數據' --@ReturnMsg 輸出對應的引用數據表名。 WHEN 51000 THEN @ReturnMsg+' 不是有效的操做員' --@ReturnMsg 輸出操做員參數的值。 ELSE @ReturnMsg+' 可嘗試查看 SELECT * FROM ErrorLog 中的信息' END -- ============================================= */ CREATE PROCEDURE [dbo].[up_DeleteTravelLineType] ( @Code [varchar](20), @DeleteChild [bit] = 0, @Operator [nvarchar](32) = NULL, -- 操做員 @ReturnMsg [nvarchar](256) = NULL OUTPUT, @Language [sysname] = NULL -- 語言,如: '簡體中文','us_english' 等,NULL 或 '' 時使用當前語言。 ) AS BEGIN -- 對存儲過程作一些基本設置 SET NOCOUNT ON; -- 不返回計數(表示受 Transact-SQL 語句影響的行數)。 IF @Language <> '' SET LANGUAGE @Language; -- 設置語言 IF @Operator = '' SET @Operator = NULL; -- 暫時不啓用刪除子數據功能,若是啓用該功能,須要處理好子數據又有子數據的狀況!!! SET @DeleteChild = 0; -- 判斷參數合法性,用 FORMATMESSAGE() 設置錯誤信息。 IF @Code IS NULL BEGIN SET @ReturnMsg = 'Code' RETURN 50001 END; DECLARE @ErrCode int SELECT @ErrCode = 0, @ReturnMsg='' IF NOT EXISTS(SELECT * FROM TravelLineType WHERE Code = @Code)-- 判斷數據是否存在 SELECT @ErrCode = 50003, @ReturnMsg = ISNULL(CONVERT(varchar(128),@Code),'null') ELSE IF dbo.uf_ExistsUserCode(@Operator) = 0 -- dbo.uf_ExistsUser(@Operator) = 0 SELECT @ErrCode = 51000, @ReturnMsg = ISNULL(@Operator, 'null') ELSE -- 若是有從表數據時,對從表數據進行檢查,暫時不容許刪除有航線的類型 IF ((@DeleteChild IS NULL) OR (@DeleteChild = 0)) AND (EXISTS(SELECT * FROM TravelLine WHERE TypeCode = @Code)) SELECT @ErrCode = 50005, @ReturnMsg = 'TravelLine' ELSE -- ============================================= */ CREATE PROCEDURE [dbo].[up_DeleteTravelLineType] ( @Code [varchar](20), @DeleteChild [bit] = 0, @Operator [nvarchar](32) = NULL, -- 操做員 @ReturnMsg [nvarchar](256) = NULL OUTPUT, @Language [sysname] = NULL -- 語言,如: '簡體中文','us_english' 等,NULL 或 '' 時使用當前語言。 ) AS BEGIN -- 對存儲過程作一些基本設置 SET NOCOUNT ON; -- 不返回計數(表示受 Transact-SQL 語句影響的行數)。 IF @Language <> '' SET LANGUAGE @Language; -- 設置語言 IF @Operator = '' SET @Operator = NULL; -- 暫時不啓用刪除子數據功能,若是啓用該功能,須要處理好子數據又有子數據的狀況!!! SET @DeleteChild = 0; -- 判斷參數合法性,用 FORMATMESSAGE() 設置錯誤信息。 IF @Code IS NULL BEGIN SET @ReturnMsg = 'Code' RETURN 50001 END; DECLARE @ErrCode int SELECT @ErrCode = 0, @ReturnMsg='' IF NOT EXISTS(SELECT * FROM TravelLineType WHERE Code = @Code)-- 判斷數據是否存在 SELECT @ErrCode = 50003, @ReturnMsg = ISNULL(CONVERT(varchar(128),@Code),'null') ELSE IF dbo.uf_ExistsUserCode(@Operator) = 0 -- dbo.uf_ExistsUser(@Operator) = 0 SELECT @ErrCode = 51000, @ReturnMsg = ISNULL(@Operator, 'null') ELSE -- 若是有從表數據時,對從表數據進行檢查,暫時不容許刪除有航線的類型 IF ((@DeleteChild IS NULL) OR (@DeleteChild = 0)) AND (EXISTS(SELECT * FROM TravelLine WHERE TypeCode = @Code)) SELECT @ErrCode = 50005, @ReturnMsg = 'TravelLine' ELSE DELETE FROM TravelLineType WHERE Code = @Code -- 備份數據 DECLARE @BackupID int; SET @BackupID = 0; EXEC @ErrCode = up_BackupData @DataFlag = 'TravelLineType', @DataKey = @Code, @DataContent = @DataContent, @BackupID = @BackupID OUTPUT IF @ErrCode = 0 BEGIN SET @LogText = @LogText + '數據已備份,備份標識: '+CONVERT(varchar, @BackupID) -- 記錄操做日誌 EXEC @ErrCode = up_LogOperation @LogType = 'TravelLineType', @KeyValue = @Code, @Operate='刪除', @Operator=@Operator, @Detail=@LogText, @Description='', @LogID = @LogID OUTPUT END; IF @ErrCode = 0 BEGIN IF @TranCounter = 0 COMMIT TRANSACTION END ELSE BEGIN IF @TranCounter = 0 ROLLBACK TRANSACTION ELSE ROLLBACK TRANSACTION ProcTRAN END END TRY BEGIN CATCH SELECT @ErrCode = ERROR_NUMBER(), @ReturnMsg = ERROR_MESSAGE() IF (XACT_STATE() = -1) OR (@TranCounter = 0) BEGIN ROLLBACK TRANSACTION; IF @TranCounter > 0 BEGIN TRANSACTION END ELSE ROLLBACK TRANSACTION ProcTRAN -- 記錄錯誤日誌 IF @ErrCode < 50000 EXEC dbo.up_LogError; END CATCH RETURN @ErrCode; -- 設置返回值 END; GO EXEC dp_SetDescription N'刪除線路類型,(暫時不容許刪除有線路的類型)當存在下屬從表數據時,若是 @DeleteChild = 1 則刪除下屬信息,不然,返回 50005 錯誤碼。', 'PROCEDURE', 'up_DeleteTravelLineType' GO EXEC dp_SetDescription N'指定要刪除的數據主鍵。', 'PROCEDURE', 'up_DeleteTravelLineType', 'PARAMETER', '@Code' GO EXEC dp_SetDescription N'暫未啓用!當存在下屬從表數據時,若是 @DeleteChild = 1 則刪除下屬信息,不然,返回 50005 錯誤碼。', 'PROCEDURE', 'up_DeleteTravelLineType', 'PARAMETER', '@DeleteChild' GO
好吧,雖然本身簡歷上也寫着熟悉MSSqlServer(存儲過程、觸發器、視圖、遊標、索引),但看到這存儲過程,真心能感覺到差距。。。開發
雖然佩服他的Sql,但我並不推崇這種開發方式,甚至抵觸。
但他們也是無奈,要實現功能,對C#又不太熟,對精通SQL的他來講,這樣的開發方式耗時最短,性能最高。
簡單談下本身對這個的見解吧:
優勢:
一、對他來講,這多是最合適最快速的開發方式。
二、在符合某些前提(如訪問量不大)的狀況,確實性能最高。
三、一次操做只鏈接一次數據庫。
四、直接操做數據,沒有轉換爲對象的操做,沒有生成SQL語句的操做。
五、更改方便,只需改存儲過程,無需編譯發佈。
六、大大減輕Web服務器的壓力(將就着算優勢吧)。
缺點就太明顯了:
一、只適合小項目。
二、可讀性、可維護性、可擴展性。
。。。。。。
好吧,這兩點,足夠了。。。
Over~!~!~!