Hướng dẫn học Microsoft SQL Server 2008 part 68 docx

10 211 0
Hướng dẫn học Microsoft SQL Server 2008 part 68 docx

Đang tải... (xem toàn văn)

Thông tin tài liệu

Nielsen c25.tex V4 - 07/23/2009 4:55pm Page 632 Part IV Developing with SQL Server Anderson 01-016 2001-11-16 00:00:00.000 Outer Banks Lighthouses Andrews 01-015 2001-11-05 00:00:00.000 Amazon Trek Andrews 01-012 2001-09-14 00:00:00.000 Gauley River Rafting Andrews 01-014 2001-10-03 00:00:00.000 Outer Banks Lighthouses Bettys 01-013 2001-09-15 00:00:00.000 Gauley River Rafting Bettys 01-015 2001-11-05 00:00:00.000 Amazon Trek The second form, the OUTER APPLY command, operates much like a left outer join. With this usage, rows from the main query are included in the result set regardless of whether the virtual table returned by the user-defined function is empty. Creating functions with schema binding All three types of user-defined functions may be created with the significant added benefit of schema binding. Views may b e schema bound; in this way, UDFs are like views — both can be schema bound. This is one reason why you might choose a UDF over a stored procedure, as stored procedures cannot be schema bound. Schema binding prevents the altering or dropping of any object on which the func- tion depends. If a schema-bound function references TableA, then columns may be added to TableA, but no existing columns can be altered or dropped, and neither can the table itself. To create a function with schema binding, add the option after RETURNS and before AS during function creation, as shown here: CREATE FUNCTION FunctionName (Input Parameters) RETURNS DataType WITH SCHEMA BINDING AS BEGIN; Code; RETURNS Expression; END; Schema binding not only alerts the developer that the change will may affect an object, it prevents the change. To remove schema binding so that changes can be made, ALTER the function so that schema binding is no longer included. Multi-Statement Table-Valued Functions The multi-statement table-valued user-defined function combines the scalar function’s ability to contain complex code with the inline table-valued function’s ability to return a result set. This type of function creates a table variable and then populates it within code. The table is then passed back from the func- tion so that it may be used within SELECT statements. The primary benefit of the multi-statement table-valued user-defined function is that complex result sets may be generated within code and then easily used with a SELECT statement. This enables you to build complex logic into a query and solve problems that would otherwise be very difficult to solve without acursor. 632 www.getcoolebook.com Nielsen c25.tex V4 - 07/23/2009 4:55pm Page 633 Building User-Defined Functions 25 The APPLY command may be used with multi-statement table-valued user-defined functions in the same way that it’s used with inline user-defined functions. Creating a multi-statement table-valued function The syntax to create the multi-statement table-valued function is very similar to that of the scalar user- defined function: CREATE FUNCTION FunctionName (InputParamenters) RETURNS @TableName TABLE (Columns) AS BEGIN; Code to populate table variable RETURN; END; The following process builds a multi-statement table-valued user-defined function that returns a basic result set: 1. The function first creates a table variable called @Price within the CREATE FUNCTION header. 2. Within the body of the function, two INSERT statements populate the @Price table variable. 3. When the function completes execution, the @Price table variable is passed back as the output of the function. The ftPriceAvg function returns every price in the Price table and the average price for each product: USE OBXKite; go CREATE FUNCTION ftPriceAvg() RETURNS @Price TABLE (Code CHAR(10), EffectiveDate DATETIME, Price MONEY) AS BEGIN; INSERT @Price (Code, EffectiveDate, Price) SELECT Code, EffectiveDate, Price FROM Product JOIN Price ON Price.ProductID = Product.ProductID; INSERT @Price (Code, EffectiveDate, Price) SELECT Code, Null, Avg(Price) FROM Product JOIN Price ON Price.ProductID = Product.ProductID 633 www.getcoolebook.com Nielsen c25.tex V4 - 07/23/2009 4:55pm Page 634 Part IV Developing with SQL Server GROUP BY Code; RETURN; END; Calling the function To execute the function, refer to it within the FROM portion of a SELECT statement. The following code retrieves the result from the ftPriceAvg function: SELECT * FROM dbo.ftPriceAvg(); Result: Code EffectiveDate Price 1001 2001-05-01 00:00:00.000 14.9500 1001 2002-06-01 00:00:00.000 15.9500 1001 2002-07-20 00:00:00.000 17.9500 Multi-statement table-valued user-defined functions use tempdb to pass the table variable to the calling query. For many applications this is not a concern, but for high-transaction applications I recommend focusing on the performance of the UDF and, if possible, incorporating the code directly into the calling stored procedure. Summary User-defined functions expand the capabilities of SQL Server objects and open a world of flexibility within expressions and the SELECT statement. The big ideas from this chapter: ■ Scalar user-defined functions return a single value and must be deterministic. ■ Inline table-valued user-defined functions are very similar to views, and return the results of a single SELECT statement. ■ Multi-statement table-valued user-defined functions use code to populate a table variable, which is then returned. ■ The APPLY function can be used to pass data to an inline table-valued UDF or a multi- statement table-valued UDF from the outer query, similar to how a correlated subquery can receive data from the outer query. T-SQL code can be packaged in stored procedures, user-defined functions, and triggers. The next chapter delves into triggers, specialized T-SQL procedures that fire in response to table-level events. 634 www.getcoolebook.com Nielsen c26.tex V4 - 07/23/2009 4:56pm Page 635 Creating DML Triggers IN THIS CHAPTER Creating instead of and after triggers Using the transaction’s data within the trigger Integrating multiple triggers Building a delete trigger to enforce a single-row delete T riggers are special stored procedures attached to table events. They can’t be directly executed; they fire only in response to an INSERT, UPDATE, or DELETE event on a table. In the same way that attaching code to a form or control event in Visual Basic or Access causes that code to execute on the form or control event, triggers fire on table events. Users can’t bypass a trig- ger; and unless the trigger sends a message to the client, the end-user is unaware of the trigger. Developing triggers involves several SQL Server topics. Understanding transaction flow and locking, T-SQL, and stored procedures is a prerequisite for developing smooth triggers. Triggers contain a few unique elements and require careful plan- ning, but they provide rock-solid execution of complex business rules and data validation. Trigger Basics SQL Server triggers fire once per data-modification operation, not once per affected row. This is different from Oracle, which can fire a trigger once per operation, or once per row. While this may seem at first glance to be a limitation, being forced to develop set-based triggers actually helps ensure clean logic and fast performance. Triggers may be created for the three table events that correspond to the three data-modification commands: INSERT, UPDATE,andDELETE. 635 www.getcoolebook.com Nielsen c26.tex V4 - 07/23/2009 4:56pm Page 636 Part IV Developing with SQL Server Best Practice T riggers extend the duration of a transaction, which can lead to locking and blocking problems for high-transaction systems. For data integrity, sometimes a trigger is the best solution, but be aware of the potential performance impact. If the processing can be performed in the abstraction layer with 100 percent certainty, then I’d rather see the code there than in a trigger. If the abstraction layer isn’t enforced 100 percent of the time, then the code must exist in a trigger. SQL Server has two kinds of transaction triggers: instead of triggers and after triggers. They differ in their purpose, timing, and effect, as detailed in Table 26-1. Database triggers fire on data definition language (DDL) commands — CREATE, ALTER, DROP — and are useful for auditing server or database schema changes. For more details, see Chapter 27, ‘‘Creating DDL Triggers.’’ TABLE 26-1 Trigger Type Comparison Instead of Trigger After Trigger DML statement Simulated but not executed Executed, but can be rolled back in the trigger Timing Before PK and FK constraints After the transaction is complete, but before it is committed Number possible per table event One Multiple May be applied to views? Yes No Nested? Depends on server option Depends on server option Recursive? No Depends on database option Transaction flow Developing triggers requires understanding the overall flow of the transaction; otherwise, conflicts between constraints and triggers can cause designing and debugging nightmares. Every transaction moves through the various checks and code in the following order: 1. IDENTITY INSERT check 2. Nullability constraint 636 www.getcoolebook.com Nielsen c26.tex V4 - 07/23/2009 4:56pm Page 637 Creating DML Triggers 26 3. Data-type check 4. INSTEAD OF trigger execution. If an INSTEAD OF trigger exists, then execution of the DML stops here. INSTEAD OF triggers are not recursive. Therefore, if the INSERT trigger executes another DML command, then the INSTEAD OF trigger will be ignored the second time around (recursive triggers are covered later in this chapter). 5. Primary-key constraint 6. Check constraints 7. Foreign-key constraint 8. DML execution and update to the transaction log 9. AFTER trigger execution 10. Commit transaction (for more details on commits, see Chapter 66, ‘‘Managing Transactions, Locking, and Blocking’’) Based on SQL Server’s transaction flow, note a few key points about developing triggers: ■ An AFTER trigger occurs after all constraints. Because of this, it can’t correct data, so the data must pass any constraint checks, including foreign-key constraint checks. ■ An INSTEAD OF trigger can circumvent foreign-key problems, but not nullability, data-type, or identity-column problems. ■ An AFTER trigger can assume that the data has passed all the other built-in data-integrity checks. ■ The AFTER trigger occurs before the DML transaction is committed, so it can roll back the transaction if the data is unacceptable. Creating triggers Triggers are created and modified with the standard DDL commands, CREATE, ALTER,andDROP,as follows: CREATE TRIGGER Schema.TriggerName ON Schema.TableName AFTER | INSTEAD OF [Insert, Update, (and or) Delete] AS Trigger Code; The trigger can be fired for any combination of insert, update, or delete events. Prior to SQL Server 2000, SQL Server had AFTER triggers only. Because no distinction between AFTER and INSTEAD OF was necessary, the old syntax created the trigger FOR INSERT, UPDATE,orDELETE. To ensure that the old FOR triggers will still work, AFTER triggers can be created by using the keyword FOR in place of AFTER. Although I strongly recommend that triggers be created and altered using scripts and version control, you can view and modify triggers using Management Studio’s Object Explorer, as shown in Figure 26-1. 637 www.getcoolebook.com Nielsen c26.tex V4 - 07/23/2009 4:56pm Page 638 Part IV Developing with SQL Server FIGURE 26-1 Object Explorer will list all triggers for any table and may be used to modify the trigger using the context menu. After triggers A table may have several AFTER triggers for each of the three table events. AFTER triggers may be applied to tables only, not to views. The traditional trigger is an AFTER trigger that fires after the modification implied by the statement is complete, but before the statement ends and before the transaction is committed. AFTER triggers are useful for the following: ■ Complex data validation ■ Enforcing complex business rules ■ Writing data-audit trails ■ Maintaining modified date columns ■ Enforcing custom referential-integrity checks and cascading deletes 638 www.getcoolebook.com Nielsen c26.tex V4 - 07/23/2009 4:56pm Page 639 Creating DML Triggers 26 Best Practice W hen planning triggers, consider the most likely path. If the trigger verifies data that will nearly always be accepted, then an AFTER trigger is the best route. That’s because the work is completed and the trigger is merely a check. For inserts, updates, or deletes that are rarely accepted, use an INSTEAD OF trigger, which doesn’t actually perform the DML statement’s work prior to the trigger’s execution. When you are learning a new programming language, the first program you write is traditionally a ‘‘hello world’’ application that does nothing more than compile the program and prove that it runs by printing ‘‘hello world.’’ The following AFTER trigger simply prints ‘In the After Trigger’when the trigger is executed: USE Family; CREATE TRIGGER dbo.TriggerOne ON dbo.Person AFTER INSERT AS PRINT ‘In the After Trigger’; With the AFTER trigger enforced, the following code inserts a sample row: INSERT dbo.Person(PersonID, LastName, FirstName, Gender) VALUES (50, ‘Ebob’, ‘Bill’,‘M’); Result: In the After Trigger (1 row(s) affected) The INSERT worked and the trigger printed its own version of the ‘‘hello world’’ message. Instead of triggers INSTEAD OF triggers execute ‘‘instead of’’ (as a substitute for) the submitted transaction, so that the sub- mitted transaction does not occur. It’s as if the presence of an INSTEAD OF trigger signals the submitted transaction to be ignored by SQL Server. As a substitution procedure, each table is limited to only one INSTEAD OF trigger per table event. In addition, INSTEAD OF triggers may be applied to views as well as tables. Don’t confuse INSTEAD OF triggers with BEFORE triggers or before update events. They’re not the same. A BEFORE trigger, if such a thing existed in SQL Server, would not interfere with the submitted DML statement execution unless code in the trigger executed a transaction rollback. 639 www.getcoolebook.com Nielsen c26.tex V4 - 07/23/2009 4:56pm Page 640 Part IV Developing with SQL Server INSTEAD OF triggers are useful when it’s known that the DML statement firing the trigger will always be rolled back and some other logic will be executed instead of the DML statement. For example: ■ When the DML statement attempts to update a non-updatable view, the INSTEAD OF trigger updates the underlying tables instead. ■ When the DML statement attempts to directly update an inventory table, an INSTEAD OF trigger updates the inventory transaction table instead. ■ When the DML statement attempts to delete a row, an INSTEAD OF trigger moves the row to an archive table instead. The following code creates a test INSTEAD OF trigger and then attempts to INSERT arow: CREATE TRIGGER dbo.TriggerTwo ON dbo.Person INSTEAD OF INSERT AS PRINT ‘In the Instead of Trigger’; go INSERT dbo.Person(PersonID, LastName, FirstName, Gender) VALUES (51, ‘Ebob’, ‘’,‘M’); Result: In the Instead of Trigger (1 row(s) affected) The result includes the INSTEAD OF trigger’s ‘‘hello world’’ declaration and a report that one row was affected. However, selecting personID 51 will prove that no rows were in fact inserted: SELECT LastName FROM dbo.Person WHERE PersonID = 51; Result: LastName (0 row(s) affected) The INSERT statement worked as if one row were affected, although the effect of the INSERT statement was blocked by the INSTEAD OF trigger. The PRINT command was executed instead of the rows being inserted. In addition, the AFTER trigger is still in effect, but its PRINT message failed to print. Trigger limitations Given their nature (code attached to tables), triggers have a few limitations. The following SQL commands are not permitted within a trigger: 640 www.getcoolebook.com Nielsen c26.tex V4 - 07/23/2009 4:56pm Page 641 Creating DML Triggers 26 ■ CREATE, ALTER,orDROP database ■ RECONFIGURE ■ RESTORE database or log ■ DISK RESIZE ■ DISK INIT Disabling triggers A user’s DML statement can never bypass a trigger, but a system administrator can temporarily disable it, which is better than dropping it and then recreating it if the trigger gets in the way of a data-modification task. Disabling a trigger can only be done for the entire database, not just for the current connection or the current user; this makes disabling a trigger an extremely dangerous instrument. Think twice before making any attempt to bypass an instrument that is used to guard data integrity! To temporarily turn off a trigger, use the ALTER TABLE DDL command with the ENABLE TRIGGER or DISABLE TRIGGER option: ALTER TABLE schema.TableName ENABLE or DISABLE TRIGGER schema.TriggerName; For example, the following code disables the INSTEAD OF trigger (TriggerOne on the Person table): ALTER TABLE dbo.Person DISABLE TRIGGER TriggerOne; To view the enabled status of a trigger, use the OBJECTPROPERTY() function, passing to it the object ID of the trigger and the ExecIsTriggerDisabled option: SELECT OBJECTPROPERTY( OBJECT_ID(’TriggerOne’),’ExecIsTriggerDisabled’); Listing triggers Because triggers tend to hide in the table structure, the following query lists all the triggers in the database based on the sys.triggers catalog view: SELECT Sc.name + ‘.’ + Ob.name as [table], Tr.Name as [trigger], CASE (Tr.is_instead_of_trigger ) WHEN 0 THEN ‘after’ WHEN 1 THEN ‘instead of’ END AS type, CASE (Tr.is_disabled) WHEN 0 THEN ‘enabled’ WHEN 1 THEN ‘disabled’ 641 www.getcoolebook.com . trigger can be fired for any combination of insert, update, or delete events. Prior to SQL Server 2000, SQL Server had AFTER triggers only. Because no distinction between AFTER and INSTEAD OF was. Product.ProductID 633 www.getcoolebook.com Nielsen c25.tex V4 - 07/23/2009 4:55pm Page 634 Part IV Developing with SQL Server GROUP BY Code; RETURN; END; Calling the function To execute the function, refer. is unaware of the trigger. Developing triggers involves several SQL Server topics. Understanding transaction flow and locking, T -SQL, and stored procedures is a prerequisite for developing smooth

Ngày đăng: 04/07/2014, 09:20

Tài liệu cùng người dùng

Tài liệu liên quan