一种无奈所以另类的开发方式----SQL很强大!
好久没写点什么了。。。
多年前。。。。。。
前些时间,与一多年前在北京共事过的略带亲戚关系的同事闲聊了会。
在北京那时,他们的主要是用Delphi语言,数据库是MSSqlServer。
他没有大学学历,甚至好像高中学历都没有,成长过程比较励志,工厂流水线、理发师、卖东西神马的都干过!!!
他是公司的主程,负责某行业管理软件、呼叫中心等系统,最让我佩服的,是他对MSSqlServer的熟悉程度,对我而言,膜拜之也并不过分。
===============================================================================
现状
听他说,他们现在做B/S时,已经在用.Net了,多年前,也听他们提过,说想转到C#。
不过,当聊到开发方式时,我却震惊了:因为对C#还不是很熟悉,所以,所有的CURD、所有的业务逻辑,通通用存储过程来实现。C#没有业务逻辑,各种数据操作都调用存储过程来实现。
顺便贴了一个存储过程给我,只是一个删数据的存储过程。
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的他来说,这样的开发方式耗时最短,性能最高。
简单谈下自己对这个的看法吧:
优点:
1、对他来说,这可能是最合适最快速的开发方式。
2、在符合某些前提(如访问量不大)的情况,确实性能最高。
3、一次操作只连接一次数据库。
4、直接操作数据,没有转换为对象的操作,没有生成SQL语句的操作。
5、更改方便,只需改存储过程,无需编译发布。
6、大大减轻Web服务器的压力(将就着算优点吧)。
缺点就太明显了:
1、只适合小项目。
2、可读性、可维护性、可扩展性。
。。。。。。
好吧,这两点,足够了。。。
Over~!~!~!