得福代孕网怎么样

得福代孕网怎么样█微/信 同号█:138★0226★9370█ ████ 得福代孕█代孕包成功█ ★█代孕包男孩█ ★█

一、游标
*什么是游标

游标实际上是一种能从包括多条数据记录的结果集(结果集是select查询之后返回的所有行数据的集合)中每次提取一条记录的机制充当指针的作用,遍历结果中的所有行,但他一次只指向一行。游标的结果集是由SELECT语句产生,如果处理过程需要重复使用一个记录集,那么创建一次游标而重复使用若干次,比重复查询数据库要快的多。
也可以说,SQL的游标是一种临时的数据库对象,可以用来存放在数据库表中的数据行副本,也可以指向存储在数据库中的数据行的指针。游标提供了在逐行的基础上操作表中数据的方法。
一般复杂的存储过程,都会有游标的出现,他的用处主要有: 
1.定位到结果集中的某一行。 
2.对当前位置的数据进行读写。 
3.可以对结果集中的数据单独操作,而不是整行执行相同的操作。 
4.是面向集合的数据库管理系统和面向行的程序设计之间的桥梁。
*不足: 
数据量小时才使用游标,因为: 
1.游标使用时会对行加锁,系统上跑的不只我们一个业务,这就会影响其他业务的正常进行; 
2.数据量大时其效率也较低效; 
3.游标其实是相当于把磁盘数据整体放入了内存中,如果游标数据量大则会造成内存不足, 
书写格式:

DECLARE mycursor Cursor   --定义游标
FOR SELECT EmployeeID FROM ...  --查询语句

OPEN mycursor     --打开游标
DECLARE @id int   --根据查询语句相应地定义变量
FETCH NEXT FROM mycursor INTO @id  --逐行提取游标集中的行
WHILE @@FETCH_STATUS=0 --通过检查全局变量@@FETCH_STATUS来判断是否已读完游标集中所有行
BEGIN
  *此处书写要执行的Sql语句* 
  FETCH NEXT FROM mycursor INTO @id  --移动游标
END
CLOSE mycursor  --关闭游标
DEALLOCATE mycursor --释放游标

实例:根据产品名称(名称一样视为同一产品)统计该产品的销售数量,如果在统计表(ProductStatistics)中能找到这个产品名称的数据,则插入这个产品的统计结果,如果不能找到这个产品名称的数据,则修改统计结果。


注意:

@@FETCH_STATUS的值有: 
0:FETCH 语句成功,表示已经从游标集中获取了元组值 
1:FETCH 语句失败或此行不在结果集中 
2:被提取的行不存在
游标不使用了,必须关闭,关闭后再使用要重新打开
关闭游标,并没有释放游标所占用的内存和外存空间,必须释放游标
游标可以放在触发器和存储过程中
扩充(以上是标准游标):
语法:


参数说明: 
(1)Local与Global: 
1.Local表示游标的作用于仅仅限于其所在的存储过程、触发器以及批处理中、执行完毕以后游标自动释放。 
2.Global表示的是该游标作用域是整个会话层。由连接执行的任何存储过程、批处理等都可以引用该游标名称,仅在断开连接时隐性释放。

(2)Forward_only与Scroll:前者表示为只进游标,后者表示为可以随意定位。默认为前者。

(3)Static、Keyset与Dynamic、 FAST_FORWARD: 这四个关键字是游标所在数据集所反应的表内数据和游标读取出的数据的关系 
1. STATIC意味着,当游标被建立时,将会创建FOR后面的SELECT语句所包含数据集的副本存入tempdb数据库中,任何对于底层表内数据的更改不会影响到游标的内容. 
2. DYNAMIC是和STATIC完全相反的选项,当底层数据库更改时,游标的内容也随之得到反映,在下一次fetch中,数据内容会随之改变 
3. KEYSET可以理解为介于STATIC和DYNAMIC的折中方案。将游标所在结果集的唯一能确定每一行的主键存入tempdb,当结果集中任何行改变或者删除时,@@FETCH_STATUS会为-2,KEYSET无法探测新加入的数据 
4. FAST_FORWARD可以理解成FORWARD_ONLY的优化版本.FORWARD_ONLY执行的是静态计划,而FAST_FORWARD是根据情况进行选择采用动态计划还是静态计划,大多数情况下FAST_FORWARD要比FORWARD_ONLY性能略好.

(4) READ_ONLY SCROLL_LOCKS OPTIMISTIC 三选一 : 
1. READ_ONLY意味着声明的游标只能读取数据,游标不能做任何更新操作 
2. SCROLL_LOCKS是另一种极端,将读入游标的所有数据进行锁定,防止其他程序进行更改,以确保更新的绝对成功 
3. OPTIMISTIC是相对比较好的一个选择,OPTIMISTIC不锁定任何数据,当需要在游标中更新数据时,如果底层表数据更新,则游标内数据更新不成功,如果,底层表数据未更新,则游标内表数据可以更新

二、存储过程
什么是存储过程 
存储过程是一组命名了的SQL语句集合,是为了完成特定功能汇集而成的。该集合编译后存放在数据库中,可根据实际情况重新编译,可直接运行,也可远程运行且存储过程直接在服务器端运行。

优点: 
1. 将业务操作封装 
(a) 可为复杂的业务操作编写存储过程,放在数据库中; 
(b)用户可调用存储过程执行,而业务操作对用户是不可见的; 
(c)若存储过程仅修改了执行体,没有修改接口(即调用参数),则用户程序不需要修改,达到业务封装的效果。

2. 便于事务管理 
(a)事务控制可以用在存储过程中; 
(b)用户可依据业务的性质定义事务,并对事务进行相应级别的操作

3. 实现一定程度的安全性保护 
(a)存储过程存放在数据库中,且在服务器端运行; 
(b)对于不允许用户直接操作的表或视图,可通过调用存储过程来间接地访问这些表或视图,达到一定程度的安全性; 
(c)这种安全性缘于用户对存储过程只有执行权限,没有查看权限; 
(d)拥有存储过程的执行权限,自动获取了存储过程中对相应表或视图的操作权限; 
(e)这些操作权限仅能通过执行存储过程来实现,一旦脱离存储过程,也就失去了相应操作权限。

4. 特别适合统计和查询操作 
(a)一般统计和查询,尤其是期末统计,往往涉及数据量大、表多,若在客户端实现,数据流量和网络通信量较大; 
(b)很多情况下,管理信息系统的设计者,将复杂的查询和统计用存储过程来实现,免去客户端的大量编程

5. 减少网络通信量 
(a)存储过程仅在服务器端执行,客户端只接收结果; 
(b)由于存储过程与数据一般在一个服务器中,可减少大量的网络通信量

缺点: 
1.如果更改范围大到需要对输入存储过程的参数进行更改,或者要更改由其返回的数据,则仍需要更新程序集中的代码以添加参数、更新 GetValue() 调用,等等,这时候估计比较繁琐了。 
2.可移植性差,由于存储过程将应用程序绑定到 SQL Server,因此使用存储过程封装业务逻辑将限制应用程序的可移植性。如果应用程序的可移植性在您的环境中非常重要,则将业务逻辑封装在不特定于 RDBMS 的中间层中可能是一个更佳的选择。

书写格式:


实例:1. 创建一个存储过程, 实现判断某员工(输入姓名)的总订单数,超过100输出优,在[35,100]中为良,[25,34]为及格,其他为差。 
–输出员工姓名及结果


实例2:(和游标一起使用) 
输入某学院名称,统计该学院每个班级同学的选课信息,返回班级编号、班级名称、课程名称、课程选课人数、课程平均分。

CREATE PROCEDURE proInstitute( @institute varchar(30) )
AS
BEGIN
       DECLARE @className varchar(30), @courseName varchar(30)
       DECLARE @classNo char(6), @count tinyint, @avg numeric(5, 1)
       /*定义一个临时表,存放每个班级的班级编号、班级名称、课程
          名称、课程选课人数、课程平均分*/
      CREATE TABLE #myTemp ( 
           classNo           char(6),
           className      varchar(30),
           courseName   varchar(30),
           classCount      tinyint,
           classAvg          numeric(5, 1) 
        )
          --定义游标curClass,依据输入参数@institute,查找班级编号和班级名称
       DECLARE curClass CURSOR FOR
             SELECT classNo, className
             FROM Class 
             WHERE institute=@institute
       OPEN curClass
       FETCH curClass INTO @classNo, @className
       WHILE (@@FETCH_STATUS=0)
       BEGIN
           --定义游标curCourse,查找@classNo班选课的课程名称、选课人数、平均分
           DECLARE curCourse CURSOR FOR 
                 SELECT courseName, count(*), avg(score)
                 FROM Student a, Score b, Course c
                 WHERE a.studentNo=b.studentNo AND b.courseNo=c.courseNo 
                       AND classNo=@classNo
                 GROUP BY courseName
                  OPEN curCourse
        FETCH curCourse INTO @courseName, @count, @avg
        WHILE (@@FETCH_STATUS=0)
        BEGIN
                /* 将班级编号、班级名称、课程名称、课程选课人数、课程平均分
                    插入到临时表#myTemp中 */
                INSERT INTO #myTemp VALUES( @classNo, @className, @courseName, 
                                @count, @avg )
                -- 获取下一游标值,取该班下一门课程的课程名、选课人数和平均分
                FETCH curCourse INTO @courseName, @count, @avg
        END
        CLOSE curCourse
        DEALLOCATE curCourse
        --获取游标curClass的下一个值,即取下一个班级
        FETCH curClass INTO @classNo, @className
    END
    CLOSE curClass
    DEALLOCATE curClass
    --显示临时表的内容,同时将临时表的内容返回给调用者
    SELECT * FROM #myTemp
END
注意:

1.OUTPUT:说明该参数是输出参数,被调用者获取使用。缺省时表示是输入参数。 
2.使用存储过程时,必须执行命令EXECUTE/EXEC,且EXECUTE参数必须与对应的PROCEDURE的参数相匹配。 
3.删除存储过程 
语法: 
DROP PROCEDURE <procedureName> 
4.如果存储过程的输出参数取集合值,则该输出参数不在存储过程的参数中定义,而是在存储过程中定义一个临时表来存储该集合值。

(a)临时表的表名前加一个#符号,如#myTemp

(b)在存储过程尾部,使用语句:

 SELECT * FROM #myTemp
1
(c) 将结果集合返回给调用者。 
(d)存储过程结束后,临时表自动被删除。 
5.用户定义的存储过程只能在当前数据库中创建 
6.修改存储过程只需将CREATE改ALTER

三、触发器
什么是触发器 
1.触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程。触发器主要是通过事件进行触发被自动调用执行的。而存储过程可以通过存储过程的名称被调用。 
2.触发器对表进行插入、更新、删除的时候会自动执行的特殊存储过程,对于每条SQL语句,触发器仅执行一次。触发器一般用在check约束更加复杂的约束上面。触发器和普通的存储过程的区别是:触发器是当对某一个表进行操作。诸如:update、insert、delete这些操作的时候,系统会自动调用执行该表上对应的触发器。

触发器的分类 
1、 after触发器(之后触发) 
after触发器要求只有执行某一操作insert、update、delete之后触发器才被触发,且只能定义在表上。

(a)创建触发器的语法:

CREATE TRIGGER <triggerName>
      ON <tableName>
      FOR { INSERT | UPDATE | DELETE }
      AS <SQL-Statement>
(b)实例: 创建一个Order Details表的修改触发器,当字段Quantity修改时重新修改统计表(ProductStatistics)中的销售数量


CREATE TRIGGER update_mount
ON [Order Details]
FOR UPDATE
AS
BEGIN
  IF UPDATE(Quantity)
  BEGIN 
     DECLARE @Oldquantity int
     DECLARE @Newquantity int
     DECLARE @ProductID int
     SELECT @Newquantity=Quantity FROM inserted
     SELECT @Oldquantity=Quantity FROM deleted
     SELECT @ProductID=ProductID FROM deleted
     UPDATE ProductStatistics 
     SET Salesvolumes=Salesvolumes-@Oldquantity+@Newquantity 
     WHERE ProductName IN (Select ProductName from Products WHERE ProductID=@ProductID)
  END
END
--******************触发**********************

UPDATE [Order Details]
SET Quantity=10
WHERE OrderID=10248 AND  ProductID=11

2、 instead of 触发器 (之前触发) 
instead of触发器表示并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身。既可以在表上定义instead of触发器,也可以在视图上定义。

(a)创建触发器的语法:

CREATE TRIGGER <triggerName>
      ON <tableName>
      instead of { INSERT | UPDATE | DELETE }
      AS <SQL-Statement>
(b)实例: 创建一个员工表(Employees)的删除触发器,判断是否存在有当前这条员工数据的主码为外码的信息,存在则提示错误不能删除(加rollback回滚),不存在正常删除


CREATE TRIGGER employee_delete
ON Employees
INSTEAD OF DELETE
AS 
BEGIN 
  DECLARE @EmployeeID int
  SELECT @EmployeeID=EmployeeID FROM deleted 
  IF EXISTS(SELECT * FROM Orders WHERE EmployeeID=@EmployeeID)
  BEGIN
      PRINT('删除失败')
      ROLLBACK
  END
  ELSE 
  BEGIN
      DELETE FROM Employees
      WHERE  EmployeeID=@EmployeeID
      PRINT('删除成功')
  END
END
GO

--******************触发**********************
DELETE FROM Employees
WHERE EmployeeID=4
注意: 
1.触发器本身就是一个事务,所以在触发器里面可以对修改数据进行一些特殊的检查。如果不满足可以利用事务回滚,撤销操作。

2.表后面加with encrypion表示加密触发器

3.触发器有两个特殊的表:插入表(instered表)和删除表(deleted表)。这两张是逻辑表也是虚表。有系统在内存中创建者两张表,不会存储在数据库中。而且两张表的都是只读的,只能读取数据而不能修改数据。这两张表的结果总是与被改触发器应用的表的结构相同。当触发器完成工作后,这两张表就会被删除。Inserted表的数据是插入或是修改后的数据,而deleted表的数据是更新前的或是删除的数据。

4.触发器仅在当前数据库中生成 
(a)触发器有三种类型,即插入、删除和更新; 
(b)插入、删除和更新可作为一种类型的触发器; 
(c)查询操作不会产生触发动作,没有查询触发器类型。

5.规定一次仅能修改一个记录,即如果插入的记录数大于1条, 则回滚

     IF ( SELECT count(*) FROM inserted )>1
              ROLLBACK
6.触发器不需要时可以删除,删除语法:

    DROP TRIGGER <triggerName>
7.原则上并不限制一张表上定义的触发器的数量,一张表可以有多个触发器,且同一类型触发器也可以有多个,但是,由于触发器是自动执行的,为一张表建立了多个触发器,必然加大系统的开销。且如果触发器设计得不好,会带来不可预知的后果。 
8.触发器常常用于维护复杂的完整性约束,不用于业务处理。凡是可以用一般约束限制的,就不要使用触发器,如限制性别仅取男和女,可以使用检查约束CHECK实现,用户的业务处理常常使用存储过程实现。
--------------------- 
作者:xueym 
原文:https://blog.csdn.net/qq_41571267/article/details/79776043

猜你喜欢

转载自www.cnblogs.com/baiducom/p/10619815.html