Use of cursors, stored procedures, triggers

1. Cursor

*What is a cursor

  1. The cursor is actually a mechanism that can extract one record at a time from a result set that includes multiple data records (the result set is a collection of all row data returned after a select query), which acts as a pointer and traverses all the rows in the result. , but he only points to one line at a time. The result set of the cursor is generated by the SELECT statement. If the process needs to reuse a recordset, creating a cursor and using it several times is much faster than repeatedly querying the database .
  2. It can also be said that a SQL cursor is a temporary database object, which can be used to store a copy of a data row in a database table, or a pointer to a data row stored in the database. Cursors provide methods for manipulating data in a table on a row-by-row basis.
  3. In general complex stored procedures, there will be cursors, and his main uses are:
    1. Locate a row in the result set.
    2. Read and write data at the current location.
    3. You can operate on the data in the result set individually, instead of performing the same operation on the entire row.
    4. It is a bridge between collection-oriented database management systems and row-oriented programming.

*Insufficient:
The cursor is only used when the amount of data is small, because:
1. When the cursor is used, the row will be locked, and more than one business is running on the system, which will affect the normal operation of other businesses;
2. When the amount of data is large, its efficiency It is also less efficient;
3. The cursor is actually equivalent to putting the entire disk data into the memory. If the amount of cursor data is large, it will cause insufficient memory. The
writing format:

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 --释放游标

Example: According to the product name (the same name is regarded as the same product) to count the sales quantity of this product, if the data of this product name can be found in the statistics table (ProductStatistics), insert the statistical result of this product, if the product name cannot be found data, modify the statistical results.


DECLARE MyCursor CURSOR
FOR SELECT DISTINCT(ProductName) FROM Products 

OPEN MyCursor
DECLARE @name NVARCHAR(30)
FETCH NEXT FROM MyCursor INTO @name
WHILE @@FETCH_STATUS=0 
BEGIN 
    DECLARE @salesvolumes INT
    SELECT @salesvolumes=SUM(Quantity) FROM [Order Details] WHERE ProductID IN 
        (SELECT ProductID FROM Products WHERE ProductName=@name)
    IF((SELECT COUNT(*) FROM ProductStatistics WHERE ProductName=@name)>0)
      BEGIN
        UPDATE ProductStatistics
        SET Salesvolumes=@salesvolumes
        WHERE ProductName=@name
      END
    ELSE
      BEGIN
        IF(@salesvolumes<>0)
        BEGIN
            INSERT INTO ProductStatistics(ProductName,Salesvolumes)
            VALUES(@name,@salesvolumes)
        END
      END

    FETCH NEXT FROM MyCursor INTO @name
END
CLOSE MyCursor
DEALLOCATE  MyCursor

Notice:

  1. The values ​​of @@FETCH_STATUS are:
    0: The FETCH statement succeeded, indicating that the tuple value has been fetched from the cursor set
    1: The FETCH statement failed or the row is not in the result set
    2: The row being fetched does not exist
  2. The cursor is not used, it must be closed, and it must be reopened after closing it.
  3. Closing the cursor does not release the memory and external memory space occupied by the cursor, the cursor must be released
  4. Cursors can be placed in triggers and stored procedures
  5. Expansion (above is a standard cursor):
语法:
DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ] 
     [ FORWARD_ONLY | SCROLL ] 
     [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] 
     [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] 
     FOR select_statement 
     [ FOR UPDATE [ OF column_name [ ,...n ] ] ]

Parameter description:
(1) Local and Global:
1.Local indicates that the role of the cursor is limited to the stored procedure, trigger and batch process where it is located, and the cursor is automatically released after the execution is completed.
2.Global means that the cursor scope is the entire session layer. This cursor name can be referenced by any stored procedures, batches, etc. executed by the connection, only implicitly freed on disconnect.

(2) Forward_only and Scroll: The former is expressed as a forward-only cursor, and the latter is expressed as a free positioning. The default is the former.

(3) Static, Keyset and Dynamic, FAST_FORWARD: These four keywords are the relationship between the data in the table reflected by the dataset where the cursor is located and the data read by the cursor
1. STATIC means that when the cursor is established, it will A copy of the data set contained in the SELECT statement following the creation of FOR is stored in the tempdb database, and any changes to the data in the underlying table will not affect the content of the cursor.
2. DYNAMIC is the exact opposite option to STATIC, when the underlying database changes , the content of the cursor is also reflected, in the next fetch, the data content will change accordingly
3. KEYSET can be understood as a compromise between STATIC and DYNAMIC. Store the primary key of the result set where the cursor is located that can determine each row in tempdb. When any row in the result set is changed or deleted, @@FETCH_STATUS will be -2, and KEYSET cannot detect the newly added data
. 4. FAST_FORWARD can be understood as FORWARD_ONLY The optimized version. FORWARD_ONLY executes a static plan, and FAST_FORWARD chooses a dynamic plan or a static plan according to the situation. In most cases, the performance of FAST_FORWARD is slightly better than FORWARD_ONLY.

(4) READ_ONLY SCROLL_LOCKS OPTIMISTIC Choose one of three:
1. READ_ONLY means that the declared cursor can only read data, and the cursor cannot do any update operations
2. SCROLL_LOCKS is the other extreme, which locks all data read into the cursor to prevent Make changes to other programs to ensure the absolute success of the update
3. OPTIMISTIC is a relatively good choice. OPTIMISTIC does not lock any data. When data needs to be updated in the cursor, if the underlying table data is updated, the data in the cursor will not be updated successfully. , if the underlying table data is not updated, the table data in the cursor can be updated

Second, the stored procedure

What is a stored procedure?
A stored procedure is a named set of SQL statements that are assembled to accomplish specific functions. The collection is compiled and stored in the database, and can be recompiled according to the actual situation. It can be run directly or remotely and the stored procedure can be run directly on the server side.

Advantages:
1. Encapsulate business operations
(a) Write stored procedures for complex business operations and put them in the database;
(b) Users can call stored procedures to execute, but business operations are invisible to users;
(c) If The stored procedure only modifies the executor and does not modify the interface (that is, the calling parameters), so the user program does not need to be modified to achieve the effect of business encapsulation.

2. Facilitate transaction management
(a) Transaction control can be used in stored procedures;
(b) Users can define transactions according to the nature of the business, and perform operations on the transaction at the corresponding level

3. Implement a certain degree of security protection
(a) Stored procedures are stored in the database and run on the server side;
(b) For tables or views that do not allow users to operate directly, these tables can be accessed indirectly by calling stored procedures or view, to achieve a certain level of security;
(c) This security is due to the fact that the user has only the execution authority to the stored procedure, but no viewing authority;
(d) has the execution authority of the stored procedure, and automatically obtains the corresponding table in the stored procedure. Or the operation authority of the view;
(e) These operation authority can only be realized by executing the stored procedure. Once the stored procedure is separated, the corresponding operation authority will be lost.

4. Especially suitable for statistics and query operations
(a) General statistics and queries, especially end-of-period statistics, often involve a large amount of data and a large number of tables. If implemented on the client side, the data traffic and network traffic will be large;
(b) In many cases Under the management information system, the designer of the management information system uses the stored procedure to realize the complex query and statistics, eliminating the need for a lot of programming on the client

5. Reduce network traffic
(a) The stored procedure is only executed on the server side, and the client only receives the results;
(b) Since the stored procedure and data are generally in the same server, a large amount of network traffic can be reduced

Disadvantages:
1. If the changes are large enough to require changes to the parameters of the input stored procedure, or to change the data returned by it, you will still need to update the code in the assembly to add the parameters, update the GetValue() call, etc., This time it is probably more complicated.
2. Poor portability, because the stored procedure binds the application to SQL Server, so using the stored procedure to encapsulate the business logic will limit the portability of the application. If application portability is important in your environment, encapsulating the business logic in a middle tier that is not RDBMS specific may be a better option.

Writing format:

CREATE PROCEDURE  【存储过程名】
 @LastName NVARCHAR (20) 
 @sName varchar(20) OUTPUT
  --参数
 AS
    BEGIN 
      要执行的Sql语句
    END
    EXEC 【存储过程名】 '参数的值',@sName OUTPUT

Example: 1. Create a stored procedure to judge the total number of orders of an employee (input name). If it exceeds 100, the output is excellent. In [35, 100], it is good, [25, 34] is pass, and others are poor.
– Output employee name and result

ALTER PROCEDURE get_result18
 @LastName NVARCHAR (20)
 AS
    BEGIN 
      DECLARE @Ordercount int
      SELECT @Ordercount=COUNT(OrderID)
      FROM Employees LEFT JOIN Orders ON Employees.EmployeeID=Orders.EmployeeID
      WHERE LastName=@LastName
      GROUP BY LastName
      SELECT LastName,(  CASE 
                           WHEN @Ordercount>100 then '优'
                           WHEN @Ordercount>=35  then '良'
                           WHEN @Ordercount>=25  then '及格'
                           ELSE  '差'
                           END ) AS result 
      FROM Employees 
      WHERE LastName=@LastName
    END
    EXEC get_result18 'Peacock'

Example 2: (used with a cursor)
Enter the name of a college, count the course selection information of each class in the college, and return the class number, class name, course name, number of students enrolled in the course, and average course score.

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

Notice:

1.OUTPUT: Indicates that this parameter is an output parameter, which is acquired and used by the callee. By default, it means that it is an input parameter.
2. When using a stored procedure, the command EXECUTE/EXEC must be executed, and the EXECUTE parameter must match the parameter of the corresponding PROCEDURE.
3. Delete the stored procedure
Syntax :
DROP PROCEDURE <procedureName>
4. If the output parameter of the stored procedure takes the set value, the output parameter is not defined in the parameter of the stored procedure, but a temporary table is defined in the stored procedure to store the set value.

(a) Add a # symbol before the table name of the temporary table, such as #myTemp

(b) At the end of the stored procedure, use the statement:

 SELECT * FROM #myTemp

(c) Return the result set to the caller.
(d) After the stored procedure ends, the temporary table is automatically deleted.
5. User-defined stored procedures can only be created in the current database
6. To modify stored procedures, just change CREATE to ALTER

3. Trigger

What is a trigger
1. A trigger is a special type of stored procedure, which is different from the stored procedure we introduced earlier. Triggers are mainly triggered by events and are automatically invoked and executed. The stored procedure can be called by the name of the stored procedure.
2. A trigger is a special stored procedure that is automatically executed when a trigger inserts, updates, and deletes a table. For each SQL statement, the trigger is executed only once. Triggers are generally used on constraints with more complex check constraints. The difference between triggers and ordinary stored procedures is that triggers operate on a table. For operations such as update, insert, and delete, the system will automatically call and execute the corresponding trigger on the table.

Classification
of triggers 1. After triggers (after triggering) After
triggers require that the triggers be triggered only after performing an operation insert, update, or delete, and can only be defined on the table.

(a) Syntax to create trigger:

CREATE TRIGGER <triggerName>
      ON <tableName>
      FOR { INSERT | UPDATE | DELETE }
      AS <SQL-Statement>

(b) Example: Create a modification trigger for the Order Details table, and re-modify the sales quantity in the statistics table (ProductStatistics) when the field Quantity is modified


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 trigger (fired before)
instead of trigger means that it does not execute its defined operations (insert, update, delete) but only executes the trigger itself. Instead of triggers can be defined on a table or on a view.

(a) Syntax to create trigger:

CREATE TRIGGER <triggerName>
      ON <tableName>
      instead of { INSERT | UPDATE | DELETE }
      AS <SQL-Statement>

(b) Example: Create a delete trigger for the employee table (Employees) to determine whether there is information that the primary code of the current employee data is a foreign code. delete normally


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

Note:
1. The trigger itself is a transaction, so some special checks can be performed on the modified data in the trigger. If it is not satisfied, you can use the transaction to roll back and undo the operation.

2. Add with encrypion after the table to indicate an encrypted trigger

3. Triggers have two special tables: insert table (instered table) and delete table (deleted table). These two are logical tables and virtual tables. There are systems that create two tables in memory, not stored in the database. And the two tables are read-only, you can only read the data but not modify the data. The result of these two tables is always the same structure as the table to which the modified trigger is applied. When the trigger completes its work, the two tables are dropped. The data of the Inserted table is the inserted or modified data, and the data of the deleted table is the data before the update or the deleted data.

4. Triggers are only generated in the current database
(a) There are three types of triggers, namely insert, delete and update;
(b) Insert, delete and update can be used as one type of trigger;
(c) Query operations will not Generate trigger action, no query trigger type.

5. It is stipulated that only one record can be modified at a time, that is, if the number of inserted records is greater than 1, it will be rolled back

     IF ( SELECT count(*) FROM inserted )>1
              ROLLBACK

6. Triggers can be deleted when they are not needed, delete syntax:

    DROP TRIGGER <triggerName>

7. In principle, there is no limit to the number of triggers defined on a table. A table can have multiple triggers, and there can also be multiple triggers of the same type. However, since triggers are executed automatically, The establishment of multiple triggers for a table will inevitably increase the overhead of the system. And if the trigger is not designed well, it will bring unpredictable consequences.
8. Triggers are often used to maintain complex integrity constraints and are not used for business processing. For those that can be restricted by general constraints, don't use triggers. For example, if the gender is limited to male and female, it can be implemented by check constraint CHECK, and the user's business processing is often implemented by stored procedures.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325894380&siteId=291194637