zoukankan      html  css  js  c++  java
  • 存储过程优缺点-附加简单例子

    1、什么是存储过程?

           存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。

    2、存储过程的优点:

            A、 存储过程允许标准组件式编程

            存储过程创建后可以在程序中被多次调用执行,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对存储过程进行修改,但对应用程序源代码却毫无影响,从而极大的提高了程序的可移植性。

            B、 存储过程能够实现较快的执行速度

            如果某一操作包含大量的T-SQL语句代码,分别被多次执行,那么存储过程要比批处理的执行速度快得多。因为存储过程是预编译的,在首次运行一个存储过程时,查询优化器对其进行分析、优化,并给出最终被存在系统表中的存储计划。而批处理的T-SQL语句每次运行都需要预编译和优化,所以速度就要慢一些。

            C、 存储过程减轻网络流量

            对于同一个针对数据库对象的操作,如果这一操作所涉及到的T-SQL语句被组织成一存储过程,那么当在客户机上调用该存储过程时,网络中传递的只是该调用语句,否则将会是多条SQL语句。从而减轻了网络流量,降低了网络负载。

            D、 存储过程可被作为一种安全机制来充分利用

            系统管理员可以对执行的某一个存储过程进行权限限制,从而能够实现对某些数据访问的限制,避免非授权用户对数据的访问,保证数据的安全。

       E、可扩展性:应用程序和数据库操作分开,独立进行,而不是相互在一起。方便以后的扩展和DBA维护优化。

      总述:执行快、减少网络传输、可以维护性强、加强安全性、可扩展性强

    3、存储过程的缺点:

       A. SQL本身是一种结构化查询语言,但不是面向对象的的,本质上还是过程化的语言,面对复杂的业务逻辑,过程化的处理会很吃力。同时SQL擅长的是数据查询而非业务逻辑的处理,如果如果把业务逻辑全放在存储过程里面,违背了这一原则。

       B. 如果需要对输入存储过程的参数进行更改,或者要更改由其返回的数据,则您仍需要更新程序集中的代码以添加参数、更新调用,等等,这时候估计会比较繁琐了。

       C. 开发调试复杂,由于IDE的问题,存储过程的开发调试要比一般程序困难。     

       D. 没办法应用缓存。虽然有全局临时表之类的方法可以做缓存,但同样加重了数据库的负担。如果缓存并发严重,经常要加锁,那效率实在堪忧。

       E. 不支持群集,数据库服务器无法水平扩展,或者数据库的切割(水平或垂直切割)。数据库切割之后,存储过程并不清楚数据存储在哪个数据库中。

      总述:编写复杂度高、逻辑性强、更改不便等

    4、优缺点总述:

      1、我们要适当的使用存储过程来提高我们查询的质量,如复杂的连接查询等

      2、避免滥用,因为开发存储过程需要时间,避免复杂的逻辑而去使用存储过程,减少数据库的压力

    5、数据库中的存储过程有二部分:

      1、系统存储过程:系统存储过程是系统创建的存储过程以“sp”下划线开头的存储过程一般存放在master数据库中,其目的是为了帮助我们调用、更新和管理系统相关的信息。

    exec sp_databases; --查看数据库
    exec sp_tables;        --查看表
    exec sp_columns student;--查看列
    exec sp_helpIndex student;--查看索引
    exec sp_helpConstraint student;--约束
    exec sp_stored_procedures;
    exec sp_helptext 'sp_stored_procedures';--查看存储过程创建、定义语句
    exec sp_rename student, stuInfo;--修改表、索引、列的名称
    exec sp_renamedb myTempDB, myDB;--更改数据库名称
    exec sp_defaultdb 'master', 'myDB';--更改登录名的默认数据库
    exec sp_helpdb;--数据库帮助,查询数据库信息
    exec sp_helpdb master;

      2、用户自定义的存储过程:

      基本语法:

    create proc | procedure pro_name
        [{@参数数据类型} [=默认值] [output],
         {@参数数据类型} [=默认值] [output],
         ....
        ]
    as
        SQL_statements

      不带参数的存储过程语法

    if (exists (select * from sys.objects where name = 'proc_name'))
        drop proc proc_name
    go
    create proc proc_name
    as
        select * from student;
    
    --调用、执行存储过程
    exec proc_name;

      掌握了基本语法之后,试着去写几个复杂的存储过程,在实际应用中还是有很多好处的,毕竟对于后端开发工程师来说:这是一个必经之路,当然对于DBA(数据库管理员)来说,这个都是非常EASY的事情

      最后作者在奉献一个我在开发中写的一个存储过程:非常简单希望各位大神不要笑(*^_^*)

      这是一个红酒检验检疫查询

    展示存储过程

    CREATE PROC [dbo].[Proc_Check_Checkout] 
        @pageIndex AS INT,
        @pageSize AS INT,
        @ForecastBegin AS NVARCHAR(MAX),--预检
        @ForecastEnd AS NVARCHAR(MAX),
        @InspectionBegin AS NVARCHAR(MAX),--报检
        @InspectionEnd AS NVARCHAR(MAX), 
        @CheckoutID AS NVARCHAR(MAX),--预检单号
        @InspectionID AS NVARCHAR(MAX),--报检单号
        @recordCount  AS INT OUTPUT
    AS
        SET NOCOUNT ON
        DECLARE @tempPageSize INT;
        SET @tempPageSize = (@pageIndex - 1) * @pageSize;
    
     SELECT 
     --第一二条查询
     t1.ID,t2.CheckoutID,t1.QuarantineID,t1.PurchaseContract,t1.Origin,t1.Consignee,t1.GoodsName,t1.Bottle,t1.Numbers,t1.RiseNumber,t1.Mount,CONVERT(NVARCHAR(16),t1.ForecastDate,20) AS ForecastDate,
     t2.InspectionID,t2.KBottle,t2.KNumbers,t2.KRiseNumber,
     --三四条查询
     t2.Franchisee,t2.Brand,t2.BottleInspection,t2.NewspaperNumber,t2.NumberInspection,t2.CheckMount,CONVERT(NVARCHAR(16),t2.HisDate,20) AS HisDate,t2.InspectionDate
     INTO #TempData1
     FROM dbo.TBPreview_Table AS t1 
    
     LEFT JOIN dbo.TBCheckout AS t2 ON t2.CheckoutID = t1.ID
     ORDER BY t1.Date DESC ;
    
    
     SELECT * INTO #TempData2 FROM #TempData1 WHERE 1 = 2;
    
     --时间检索 
     IF @ForecastBegin IS NOT NULL AND LEN(@ForecastBegin) > 0
     BEGIN
            TRUNCATE TABLE #TempData2;
            INSERT INTO #TempData2 
            SELECT *FROM #TempData1 AS t WHERE t.ForecastDate >= @ForecastBegin;
            TRUNCATE TABLE #TempData1;
            INSERT INTO #TempData1 SELECT * FROM #TempData2;
     END
     
     --
     IF @ForecastEnd IS NOT NULL AND LEN(@ForecastEnd) > 0
     BEGIN
            TRUNCATE TABLE #TempData2;
            INSERT INTO #TempData2 
            SELECT *FROM #TempData1 AS t WHERE t.ForecastDate < DATEADD(DAY,1,@ForecastEnd) ;
            TRUNCATE TABLE #TempData1;
            INSERT INTO #TempData1 SELECT * FROM #TempData2;
     END
     
     --时间检索 报检时间
     IF @InspectionBegin IS NOT NULL AND LEN(@InspectionBegin) > 0
     BEGIN
            TRUNCATE TABLE #TempData2;
            INSERT INTO #TempData2 
            SELECT *FROM #TempData1 AS t WHERE t.InspectionDate >= @InspectionBegin;
            TRUNCATE TABLE #TempData1;
            INSERT INTO #TempData1 SELECT * FROM #TempData2;
     END
     
     --
     IF @InspectionEnd IS NOT NULL AND LEN(@InspectionEnd) > 0
     BEGIN
            TRUNCATE TABLE #TempData2;
            INSERT INTO #TempData2 
            SELECT *FROM #TempData1 AS t WHERE t.InspectionDate < DATEADD(DAY,1,@InspectionEnd) ;
            TRUNCATE TABLE #TempData1;
            INSERT INTO #TempData1 SELECT * FROM #TempData2;
     END
     
     /* 预检单号 */
      IF @CheckoutID IS NOT NULL AND LEN(@CheckoutID) > 0
     BEGIN
            TRUNCATE TABLE #TempData2;
            INSERT INTO #TempData2 
            SELECT *FROM #TempData1 AS t WHERE t.QuarantineID LIKE '%'+@CheckoutID+'%' ;
            TRUNCATE TABLE #TempData1;
            INSERT INTO #TempData1 SELECT * FROM #TempData2;
     END
    
     /* 报检单号*/
       IF @InspectionID IS NOT NULL AND LEN(@InspectionID) > 0
     BEGIN
            TRUNCATE TABLE #TempData2;
            INSERT INTO #TempData2 
            SELECT *FROM #TempData1 AS t WHERE t.InspectionID LIKE '%'+@InspectionID+'%' ;
            TRUNCATE TABLE #TempData1;
            INSERT INTO #TempData1 SELECT * FROM #TempData2;
     END
    
    SELECT @recordCount = COUNT(1) FROM #TempData1;
        DROP TABLE #TempData2;
        SELECT * INTO #TempData3 FROM #TempData1 WHERE 1 = 2;
        INSERT INTO #TempData3
        SELECT TOP (@pageSize) t1.* FROM #TempData1 AS t1 , 
        (SELECT * , ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber FROM #TempData1) AS t2
        WHERE t1.ID = t2.ID AND RowNumber > @tempPageSize 
        ORDER BY t2.RowNumber;
        DROP TABLE #TempData1;
        SELECT * FROM #TempData3;
    GO

    最后作者希望各位指出作者的不足,毕竟在程序这条路才刚刚起步!

     

     

  • 相关阅读:
    vue 中的单元测试
    redux-学习总结
    React-学习总结
    vuecli 中 chainWebpack 的常用操作
    常用 vue-config.js 配置
    JavaScript 中的 MVC、MVP、MVVM
    日常工作中 @vue/cli 需要关注的一些配置
    Electron 构建超时问题
    JSBridge 原理与封装
    Three.js 之相机
  • 原文地址:https://www.cnblogs.com/lau-4/p/10076624.html
Copyright © 2011-2022 走看看