zoukankan      html  css  js  c++  java
  • 存储过程,触发器,函数

    学SQL已经几年了,平时的工作,一般都可以应付。
    真正对SQL发生质的理解的阶段,还是做报表的那份工作。经常需要用SQL去取数据,
    分析数据,分组数据,按部门,按组别,按员工统计数据,有时候SQL里不好做,还要到界面上再去组合DataTable,DataRow,
    最终把数据呈现出来。
    今天有空写个总结,关于存储过程,触发器,函数的。没有去网上拷贝,一边对照SQL帮助文档,一边根据自己的理解来写。
    一边看例子,一边学习,这样印象深刻。
    先说存储过程
    CREATE PROCEDURE au_info_all
    AS
    SELECT au_lname, au_fname, title, pub_name
       FROM authors a INNER JOIN titleauthor ta
          ON a.au_id = ta.au_id INNER JOIN titles t
          ON t.title_id = ta.title_id INNER JOIN publishers p
          ON t.pub_id = p.pub_id
    GO

    执行存储过程

    EXECUTE/EXEC au_info_all
     
    经常的需求是,要带参数,比如分页存储过程,需要把当前页码传进去
    CREATE PROCEDURE au_info
       @lastname varchar(40), 
       @firstname varchar(20) 
    AS 
    SELECT au_lname, au_fname, title, pub_name
       FROM authors a INNER JOIN titleauthor ta
          ON a.au_id = ta.au_id INNER JOIN titles t
          ON t.title_id = ta.title_id INNER JOIN publishers p
          ON t.pub_id = p.pub_id
       WHERE  au_fname = @firstname
          AND au_lname = @lastname
    GO
    执行 EXECUTE au_info 'Dull', 'Ann'
     
    存储过程也可以像C++中的方法一样,有默认值,如果不给它的参数传值,它就使用默认值
    CREATE PROCEDURE au_info2
       @lastname varchar(30) = 'D%',
       @firstname varchar(18) = '%'
    AS 
    SELECT au_lname, au_fname, title, pub_name
    FROM authors a INNER JOIN titleauthor ta
       ON a.au_id = ta.au_id INNER JOIN titles t
       ON t.title_id = ta.title_id INNER JOIN publishers p
       ON t.pub_id = p.pub_id
    WHERE au_fname LIKE @firstname
       AND au_lname LIKE @lastname
    GO
    可以这样调用,使用默认的参数
    EXECUTE au_info2  
    也可以这样,传入参数
    EXECUTE au_info2 'Hunter', 'Sheryl'
    也可以只传入一个参数,其余的参数用默认值,如果不指出参数名,则要按照顺序从左边开始。
    EXECUTE au_info2 'Wh%' 或EXECUTE au_info2 @firstname = 'A%'
     
    我第一次工作面试的时候,面试官问我存储过程的参数的作用,举例说明
    在存储过程中,默认的参数类型是输入,如果要表示参数是输出,需要用OUTPUT关键字指出。
    比如,用存储过程验证用户登陆,传出输出参数(也可以用存储过程的返回值),表示是否允许登陆
    CREATE PROCEDURE titles_sum 
    @TITLE varchar(40) = '%', 
    @SUM money OUTPUT
    AS
    SELECT 'Title Name' = title
    FROM titles 
    WHERE title LIKE @TITLE 
    SELECT @SUM = SUM(price)
    FROM titles
    WHERE title LIKE @TITLE
     
    如何调试存储过程

    1.打开Query Analyzer(查询分析器)

    2.打开PUBS数据库->展开Stored Procedures(存储过程)->在存储过程上点右键->选择DEBUG.输入参数就可以调试了.按F11 下一步. 

    理解这些内容,应该可以应对一般的编程任务。在网上找了个小工具,可以直接操作存储过程
    clip_image002
     
    还有代码生成器,直接支持批量生成存储过程
    clip_image004
    当然,都是简单的存储过程,不包含业务逻辑的,只是数据库的增删改。如果要包含业务逻辑和关系,还得手工写。
     
    触发器
    从开始学触发器,就被很多专家建议,触发器影响性能,少用或不用,所以至今还不会用这个东东。
    昨天突然联想到,这个东东可以用做数据库备份。
    在一个采购业务系统中,老板经常会拒绝采购一些物料,大多的数的物料会被批准采购。如果每次老板拒绝采购申请,
    用触发器记住主键,存到另一个表中一。如果有一天不小心数据被破坏了(我指的破坏是指误操作,把批准和拒绝都弄混淆了。
    我发现有开发人员直接用SQL 查询分析器连到服务器中的数据库中,直接执行脚本。我有个习惯,把经常用到的查询记在一个文件中,
    他就直接打开我写的那个查询文件,有时候一不小心,执行了一大段脚本,后悔已经来不及了)
    如下图,把每笔老板拒绝的物料采购都记在日志中,批准的不记入。批准的远远大于拒绝的,如果有一天数据被破坏了,
    我可以根据这个表,轻松的恢复哪些数据是被老板拒绝的。
    clip_image006
    SQL Server 2000版本支持DML的触发器,在SQL Server 2005上还支持DDL的触发器
    这个例子是从《SQL Server 2005开发者指南》中找到的,这本书我已经看过很多遍。
    clip_image008
     
    这个东东有什么作用呢?
    连表都删除了,还记日志有什么作用。
    我接触到一个软件开发平台,用户可以定义SQL Server的表,然后用窗体设计器拖拉几下,把数据表的字段绑定到界面控件中,
    有时候用户发现表设计的不合理,会频繁的删除数据表,在运行界面时,自然会引发异常。 在窗体运行时的基础框架中,把用户删除的表,记到一个日志表中,在窗体运行之前,
    检测当前运行的窗体对应的表是否在日志表中有,如果有,表示这个表已经被用户删除过,要用断言中止程序,
    如果没有,校验通过(当然还有更多的校验)。
     
    函数
    有时候为了减少左右连接的SQL语句,用函数可以达到这个效果。
    一般很少去写通用性功能的函数,SQL表身的已经够用,比如字符串查找。常常是定义业务型的函数,
    比如查找当前采购业务的采购申请人。
    只返回一个值的函数(SQL的叫法是标量函数)
    CREATE FUNCTION ISOweek  (@DATE datetime)
    RETURNS int
    AS
    BEGIN
       DECLARE @ISOweek int
       SET @ISOweek= DATEPART(wk,@DATE)+1
          -DATEPART(wk,CAST(DATEPART(yy,@DATE) as CHAR(4))+'0104')
       IF (@ISOweek=0) 
          SET @ISOweek=dbo.ISOweek(CAST(DATEPART(yy,@DATE)-1 
             AS CHAR(4))+'12'+ CAST(24+DATEPART(DAY,@DATE) AS CHAR(2)))+1
       IF ((DATEPART(mm,@DATE)=12) AND 
          ((DATEPART(dd,@DATE)-DATEPART(dw,@DATE))>= 28))
          SET @ISOweek=1
       RETURN(@ISOweek)
    END
    调用方法
    SET DATEFIRST 1
    SELECT dbo.ISOweek('12/26/1999') AS 'ISO Week'
     
    返回一个查询表的函数(SQL的叫法是内嵌表值函数)
    CREATE FUNCTION SalesByStore (@storeid varchar(30))
    RETURNS TABLE
    AS
    RETURN (SELECT title, qty
          FROM sales s, titles t
          WHERE s.stor_id = @storeid and
          t.title_id = s.title_id)
    调用
    SELECT dbo.SalesByStore ('Warehouse011') 
     
    如果是SQL Server 2005,可以用任何.NET语言(C#,VB)写这些东东,直接以程序集的程序部署到SQL Server服务器中

    T-SQL善于集合运算,C#长于字符串和数学运算。 如果是与金融相关的软件,需要大量计算,
    把代码从T-SQL转为C#,代码可读性会大大增强,性能方面也不差。
    《SQL Server 2005 开发者指南》如是说,我没有做过金融软件,不能深刻理解这句话。
     
  • 相关阅读:
    微信 JS SDK 的 chooseImage 接口在部分安卓机上容易造成页面刷新
    规约模式Specification Pattern
    ASP.NET Core 1.0基础之日志
    C# 7 新特性-2
    C# 7 新特性-1
    ASP.NET Core 1.0基础之诊断
    ASP.NET Core 1.0基础之依赖注入
    ASP.NET Core 1.0 基础之配置
    ASP.NET Core 1.0基础之静态文件处理
    FreeSql生产环境自动升级数据库解决方案
  • 原文地址:https://www.cnblogs.com/haiyabtx/p/2270936.html
Copyright © 2011-2022 走看看