1. Trang chủ
  2. » Công Nghệ Thông Tin

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

10 212 0
Tài liệu đã được kiểm tra trùng lặp

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 1,17 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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

Trang 1

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, theOUTER APPLYcommand, 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 be 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 funcfunc-tion referencesTableA, then columns may be added toTableA,

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 afterRETURNSand beforeASduring 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,ALTERthe 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 withinSELECTstatements

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 aSELECTstatement This enables you to build

complex logic into a query and solve problems that would otherwise be very difficult to solve without

a cursor

Trang 2

TheAPPLYcommand 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@Pricewithin theCREATE FUNCTION

header

2 Within the body of the function, twoINSERTstatements populate the@Pricetable variable

3 When the function completes execution, the@Pricetable variable is passed back as the

output of the function

TheftPriceAvgfunction returns every price in thePricetable 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

Trang 3

Part IV Developing with SQL Server

GROUP BY Code;

RETURN;

END;

Calling the function

To execute the function, refer to it within theFROMportion of aSELECTstatement The following code

retrieves the result from theftPriceAvgfunction:

SELECT *

FROM dbo.ftPriceAvg();

Result:

- -

-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 theSELECTstatement

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 singleSELECTstatement

■ Multi-statement table-valued user-defined functions use code to populate a table variable, which is then returned

■ TheAPPLYfunction 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

Trang 4

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

Triggers are special stored procedures attached to table events They can’t

be directly executed; they fire only in response to anINSERT,UPDATE,

orDELETEevent 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

Trang 5

Part IV Developing with SQL Server

Best Practice

Triggers 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

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 INSERTcheck

2 Nullability constraint

Trang 6

3 Data-type check

4. INSTEAD OFtrigger execution If anINSTEAD OFtrigger exists, then execution of the DML

stops here.INSTEAD OFtriggers are not recursive Therefore, if theINSERTtrigger executes

another DML command, then theINSTEAD OFtrigger 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. AFTERtrigger 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:

■ AnAFTERtrigger 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

■ AnINSTEAD OFtrigger can circumvent foreign-key problems, but not nullability, data-type, or

identity-column problems

■ AnAFTERtrigger can assume that the data has passed all the other built-in data-integrity

checks

■ TheAFTERtrigger 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 hadAFTERtriggers only Because no distinction betweenAFTER

andINSTEAD OFwas necessary, the old syntax created the triggerFOR INSERT,UPDATE, orDELETE

To ensure that the oldFORtriggers will still work,AFTERtriggers can be created by using the keyword

FORin place ofAFTER

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

Trang 7

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 severalAFTERtriggers for each of the three table events.AFTERtriggers may be

applied to tables only, not to views

The traditional trigger is anAFTERtrigger that fires after the modification implied by the statement is

complete, but before the statement ends and before the transaction is committed.AFTERtriggers 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

Trang 8

Best Practice

When 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 followingAFTERtrigger 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 theAFTERtrigger 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)

TheINSERTworked and the trigger printed its own version of the ‘‘hello world’’ message

Instead of triggers

INSTEAD OFtriggers 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 anINSTEAD OFtrigger signals the submitted

transaction to be ignored by SQL Server

As a substitution procedure, each table is limited to only oneINSTEAD OFtrigger per table event In

addition,INSTEAD OFtriggers may be applied to views as well as tables

Don’t confuseINSTEAD OFtriggers withBEFOREtriggers or before update events They’re not the

Trang 9

Part IV Developing with SQL Server

INSTEAD OFtriggers 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, theINSTEAD OFtrigger updates the underlying tables instead

■ When the DML statement attempts to directly update an inventory table, anINSTEAD OF trigger updates the inventory transaction table instead

■ When the DML statement attempts to delete a row, anINSTEAD OFtrigger moves the row to

an archive table instead

The following code creates a testINSTEAD OFtrigger and then attempts toINSERTa row:

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 theINSTEAD OFtrigger’s ‘‘hello world’’ declaration and a report that one row was

affected However, selectingpersonID 51will prove that no rows were in fact inserted:

SELECT LastName FROM dbo.Person WHERE PersonID = 51;

Result:

LastName -(0 row(s) affected) TheINSERTstatement worked as if one row were affected, although the effect of theINSERTstatement

was blocked by theINSTEAD OFtrigger ThePRINTcommand was executed instead of the rows being

inserted In addition, theAFTERtrigger is still in effect, but itsPRINTmessage 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:

Trang 10

■ CREATE,ALTER, orDROPdatabase

■ RECONFIGURE

■ RESTOREdatabase 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 theALTER TABLEDDL command with theENABLE TRIGGERor

DISABLE TRIGGERoption:

ALTER TABLE schema.TableName ENABLE or DISABLE TRIGGER

schema.TriggerName;

For example, the following code disables theINSTEAD OFtrigger (TriggerOneon thePerson

table):

ALTER TABLE dbo.Person

DISABLE TRIGGER TriggerOne;

To view the enabled status of a trigger, use theOBJECTPROPERTY()function, passing to it the object

ID of the trigger and theExecIsTriggerDisabledoption:

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 thesys.triggerscatalog 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)

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

TỪ KHÓA LIÊN QUAN