zoukankan      html  css  js  c++  java
  • 一种无奈所以另类的开发方式----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~!~!~!

      

  • 相关阅读:
    strcspn()函数
    makfile通用版本
    C实现简单的xml格式文件
    shell编程题(七)
    C语言实现五子棋
    打字软件(最终版本)
    TypeWriting
    KMP 串的模式匹配 (25分)
    C链表操作
    Ubuntu终端字体
  • 原文地址:https://www.cnblogs.com/uphenson/p/3785763.html
Copyright © 2011-2022 走看看