一种无奈所以另类的开发方式----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~!~!~!

  

posted @ 2014-06-13 14:27  up-Henson  阅读(2930)  评论(22编辑  收藏  举报