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

Hướng dẫn học Microsoft SQL Server 2008 part 70 potx

10 297 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,04 MB

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

Nội dung

The first script creates a sample valid inventory item for test purposes: USE OBXKites; DECLARE @ProdID UniqueIdentifier, @LocationID UniqueIdentifier; SELECT @ProdID = ProductID FROM db

Trang 1

TheOBXKitesdatabase includes a simplified inventory system To demonstrate transaction-aggregation

handling, the following triggers implement the required rules The first script creates a sample valid

inventory item for test purposes:

USE OBXKites;

DECLARE

@ProdID UniqueIdentifier,

@LocationID UniqueIdentifier;

SELECT @ProdID = ProductID

FROM dbo.Product

WHERE Code = 1001;

SELECT @LocationID= LocationID

FROM dbo.Location

WHERE LocationCode = ‘CH’;

INSERT dbo.Inventory (ProductID, InventoryCode, LocationID) VALUES (@ProdID,’A1’, @LocationID);

SELECT P.Code, I.InventoryCode, I.QuantityOnHand

FROM dbo.Inventory AS I INNER JOIN dbo.Product AS P

ON I.ProductID = P.ProductID;

Result:

Code InventoryCode QuantityOnHand - -

The inventory-transaction trigger

The inventory-transaction trigger performs the aggregate function of maintaining the current

quantity-on-hand value in theInventorytable With each row inserted into theInventoryTransaction

table, the trigger updates theInventorytable TheJOINbetween theInsertedimage table and the

Inventorytable enables the trigger to handle multiple-row inserts:

CREATE TRIGGER InvTrans_Aggregate

ON dbo.InventoryTransaction AFTER Insert

AS

UPDATE dbo.Inventory

SET QuantityOnHand += i.Value FROM dbo.Inventory AS Inv INNER JOIN Inserted AS i

ON Inv.InventoryID = i.InventoryID;

Return;

Trang 2

The next batch tests theInvTrans_Aggregatetrigger by inserting a transaction and observing the

InventoryTransactionandInventorytables:

INSERT InventoryTransaction (InventoryID, Value)

SELECT InventoryID, 5

FROM dbo.Inventory

WHERE InventoryCode = ‘A1’;

INSERT InventoryTransaction (InventoryID, Value)

SELECT InventoryID, -3

FROM dbo.Inventory

WHERE InventoryCode = ‘A1’;

INSERT InventoryTransaction (InventoryID, Value)

SELECT InventoryID, 7

FROM dbo.Inventory

WHERE InventoryCode = ‘A1’;

The following query views the data within theInventoryTransactiontable:

SELECT i.InventoryCode, it.Value

FROM dbo.InventoryTransaction AS it

INNER JOIN dbo.Inventory AS i

ON i.InventoryID

= it.InventoryID;

Result:

InventoryCode Value

-

TheInvTrans_Aggregatetrigger should have maintained a correct quantity-on-hand value through

the inserts to the InventoryTransactiontable Indeed, the next query proves the trigger functioned

correctly:

SELECT p.Code, i.InventoryCode, i.QuantityOnHand

FROM dbo.Inventory AS i

INNER JOIN dbo.Product AS p

ON i.ProductID = p.ProductID;

Result:

Code InventoryCode QuantityOnHand

- -

Trang 3

The inventory trigger

The quantity values in theInventorytable should never be directly manipulated Every quantity

adjustment must go through theInventoryTransactiontable However, some users will want

to make manual adjustments to theInventorytable The gentlest solution to the problem is to use

server-side code to perform the correct operations regardless of the user’s method:

1 An inventoryinstead oftrigger must redirect direct updates intended for theInventory

table, converting them into inserts in theInventoryTransactiontable, while permitting theInvTrans_Aggregatetrigger to update theInventorytable

2 The inserts into theInventoryTransactiontable then update theInventorytable, leaving the correct audit trail of inventory transactions

As a best practice, the trigger must accept multiple-row updates The goal is to undo the original

DMLUPDATEcommand while keeping enough of the data to write the change as anINSERTto the

InventoryTransactiontable:

CREATE TRIGGER Inventory_Aggregate

ON Inventory INSTEAD OF UPDATE AS

Redirect direct updates

If Update(QuantityOnHand)

BEGIN;

UPDATE dbo.Inventory SET QuantityOnHand = d.QuantityOnHand

FROM Deleted AS d INNER JOIN dbo.Inventory AS i

ON i.InventoryID = d.InventoryID;

INSERT dbo.InventoryTransaction (Value, InventoryID)

SELECT

i.QuantityOnHand - Inv.QuantityOnHand,

Inv.InventoryID FROM dbo.Inventory AS Inv INNER JOIN Inserted AS i

ON Inv.InventoryID = i.InventoryID;

END;

To demonstrate the trigger, the followingUPDATEattempts to change the quantity on hand from

9to10 The newInventory_Aggregatetrigger traps theUPDATEand resets the quantity on

hand back to9, but it also writes a transaction of +1to theInventoryTransactiontable (If

theInventoryTransactiontable had transaction type and comment columns, then the

trans-action would be recorded as a manual adjustment by user X.) TheInventoryTransaction

table’sInvTrans_Aggregatetrigger sees theINSERTand properly adjusts the Inventory

.QuantityOnHandto10:

Trigger Test

Trang 4

UPDATE dbo.Inventory

SET QuantityOnHand = 10

WHERE InventoryCode = ‘A1’;

Having performed the manual adjustment, the following query examines theInventoryTransaction

table:

SELECT i.InventoryCode, it.Value

FROM dbo.InventoryTransaction AS it

INNER JOIN dbo.Inventory AS i

ON i.InventoryID

= it.InventoryID;

Sure enough, the manual adjustment of 1 has been written to theInventoryTransactiontable:

InventoryCode Value

-

As the adjustment was being inserted into theInventoryTransactiontable, theInvTrans_

Aggregatetrigger posted the transaction to theInventorytable The following query double-checks

theQuantityOnHandfor inventory item‘A1’:

SELECT p.Code, i.InventoryCode, i.QuantityOnHand

FROM dbo.Inventory AS i

INNER JOIN dbo.Product AS p

ON i.ProductID = p.ProductID;

Result:

Code InventoryCode QuantityOnHand

- -

Summary

Triggers are a key feature of client/server databases It is the trigger that enables the developer to create

complex custom business rules that are strongly enforced at the Database Engine level SQL Server has

two types of triggers:INSTEAD OFtriggers andAFTERtriggers

Key takeaways about triggers:

■ INSTEAD OFtriggers cancel the firing DML statement and do something else instead of the

original DML statement

Trang 5

■ Triggers extend the lock duration, so try to place the code in the abstraction layer before it goes into the trigger

■ Triggers fire once per DML statement, not once per row, so be certain the trigger is set-based and can handle multiple rows well

■ Use the inserted and deleted virtual tables to access the data being modified by the DML statement

■ Logic in triggers can quickly become a rat’s nest of code — ad hoc SQL firing a trigger, which calls a stored procedure, which updates two tables, which fires two triggers, one of which updates another table, and so on This type of system is very expensive to maintain or refactor

The previous five chapters presented T-SQL programming and described how to package the code

within stored procedures, user-defined functions, and triggers The next chapter, ‘‘Creating DDL

Triggers,’’ continues the discussion about triggers

Trang 6

DDL Triggers

IN THIS CHAPTER

Creating DDL database triggers Preventing server or database changes

DDL trigger scope Reading event data with XML Security triggers

Sometimes the difference between an endless search to identify the problem

and readily solving the problem is as simple as knowing what changed

DDL triggers are perfect for auditing server-level and database changes

Why devote a whole chapter to DDL triggers when the material only takes a few

pages? Because I’m convinced every database, development, test, or production,

should have a schema audit DDL trigger

A trigger is code that executes as the result of some action DML triggers fire as

the result of DML code — anINSERT,UPDATE,DELETE, orMERGEstatement

DDL triggers fire as the result of some server-level or database schema–level

event — typically data definition language (DDL) code — aCREATE,ALTER, or

DROPstatement DML triggers respond to data changes, and DDL triggers respond

to schema changes

Just like DML triggers, DDL triggers can execute T-SQL code and can rollback

the event DML triggers can see into the data transaction using the inserted and

deleted tables Because DDL triggers can respond to so many types of events and

commands, the command that fired the trigger and other appropriate

informa-tion about the event is passed to the trigger in XML using theEventData()

function

Trang 7

What’s New with DDL Triggers

Introduced in SQL Server 2005, DDL triggers were extended to include logon triggers with SQL Server 2005

SP2 For SQL Server 2008, DDL triggers are a bit more fleshed out and slightly easier to code:

■ More trappable events — especially system stored procedures that work like DDL

code

■ EventData() XML schema is more readily available

Policy-Based Management, new in SQL Server 2008, leverages DDL triggers to enforce policies, so you can

be assured that DDL triggers reflect a technology that’s here to stay

Many of the reasons for using a DDL trigger can now be accomplished with more consistency across

multiple servers using Policy-Based Management (PBM) For more about PBM see Chapter 40,

‘‘Policy-Based Management.’’

Chapter 54, ‘‘Schema Audit Triggers,’’ is a sister chapter to this one that shows how to implement DDL

triggers to record every schema change to a database

Managing DDL Triggers

DDL triggers are easy to manage because they are managed using normal DDL The most significant

factor when developing a DDL trigger is the scope of the trigger — deciding which server- or

database-level events will fire a trigger

Creating and altering DDL triggers

DDL triggers are created or altered using syntax similar to working with DML triggers The location

of the trigger, specified by theONclause, is eitherALL SERVERorDATABASE— literally, the term is

DATABASE, not the name of the database The following code creates a database-level DDL trigger:

CREATE TRIGGER SchemaAudit

ON DATABASE

FOR DDL_Database_Level AS

code

Server-level events are a superset of database-level events They include all database level events The

next example shows a server-level DDL trigger:

CREATE TRIGGER SchemaAudit

ON ALL SERVER

Trang 8

FOR DDL_Server_Level

WITH Options

AS

code

Using Management Studio, database triggers are listed under the database’s Programmability node in

Object Explorer Server triggers are listed under Server Objects in Object Explorer Database triggers can

be scripted using Object Explorer, but not modified as easily as other programmability objects such as

stored procedures The context menu for DDL triggers does not offer the➪ modify, or ➪ script to alter

options that a stored procedure’s context menu includes

To list the database DDL triggers using code, query thesys.triggersandsys.eventscatalog

views Server triggers are found atsys.server_triggersandsys.server_trigger_events

Trigger scope

There are dozens of events that can potentially fire a DDL trigger — one for every DDL type of action

that can be executed on the server or database These events are categorized into a hierarchy using event

groups Creating a DDL trigger for an event group will cause the DDL trigger to fire for every event in

that group

DDL triggers can be fired by individual events, such ascreate_table,create_login, or

alter_view This can be the perfect scope for trapping the specific event There are 136 server/

database-level events, and 33 server-only level events The full list of DDL events is listed in Books

Online — search for ‘‘DDL Events.’’

With so many events, it’s sometimes (often) useful to develop a DDL trigger that spans multiple events

Fortunately, Microsoft has combined multiple similar events into a well-designed logical hierarchy of

event groups The ‘‘DDL Event Groups’’ page in Books Online clearly shows the whole hierarchy

The top, or root, of the hierarchy is theddl_eventsgroup, which includes every possible event The

next level has two groups:ddl_server_level_eventsandddl_database_level_events Each

of these groups includes several subgroups and events Chances are good that when you need to write a

DDL trigger, there’s a group that matches exactly with the types of events you want to handle

The following code creates three DDL triggers to demonstrate DDL trigger scope The first DDL trigger

handles all server-level events:

CREATE TRIGGER DDL_Server_Level_Sample

ON ALL SERVER

FOR DDL_SERVER_LEVEL_EVENTS

AS

Set NoCount ON

Print ‘DDL_Server_Level_Sample DDL Trigger’

The second DDL trigger fires for all database-level events:

USE tempdb

CREATE TRIGGER DDL_Database_Sample

Trang 9

ON DATABASE FOR DDL_DATABASE_LEVEL_EVENTS AS

Set NoCount ON Print ‘DDL_Database_Sample DDL Trigger’

The third DDL trigger traps onlycreate tablecommands:

CREATE TRIGGER DDL_Create_Table_Sample

ON DATABASE FOR Create_Table AS

Set NoCount ON Print ‘DDL_Create_Table_Sample DDL Trigger’

With these three DDL triggers installed, the next few DDL commands demonstrate DDL trigger scope

Creating a new database is a server-level event:

Create database Testdb

Result:

DDL_Server_Level_Sample DDL Trigger

Creating a new table will fire thecreate tableDDL trigger as well as the general database DDL

events trigger:

create table Test (col1 INT)

Result:

DDL_Database_Sample DDL Trigger DDL_Create_Table_Sample DDL Trigger

Dropping the table fires the general database DDL event trigger, but not the specificcreate table

event trigger:

drop table Test

Result:

DDL_Database_Sample DDL Trigger

DDL triggers and security

The DDL trigger creation options,ENCRYPTIONandEXECUTE AS, both ensure the security of

system-level auditing triggers The following DDL trigger will be encrypted when stored:

Trang 10

CREATE TRIGGER DDL_DDL_Level_Sample

ON ALL SERVER

WITH ENCRYPTION

FOR DDL_EVENTS

AS

code

As with stored procedures, triggers can be executed under a different security context Instead of the

user who issued the DDL command that caused the DDL trigger to fire, the trigger can execute as one

the following security contexts:

■ Caller: Executes as the person executing the DDL command that fires the DDL trigger

■ Self: Executes as the person who created the DDL trigger

■ ‘login_name’: Executes as a specific login

Enabling and disabling DDL triggers

DDL triggers can be turned on and off This is good because DBAs need an easy way to

disable DDL triggers that roll back any schema changes The following code disables and then

enables theDDL_Create_Table_Sampletrigger:

DISABLE TRIGGER DDL_Create_Table_Sample

ON DATABASE;

ENABLE TRIGGER DDL_Create_Table_Sample

ON DATABASE;

Removing DDL triggers

Typically, removing an object in SQL Server requires nothing more than aDROPcommand Because

DDL triggers can exist on either the database or server level, slightly more code is required Also,

because of their dual lives (residing in either the database or server), DDL triggers aren’t listed in

sys.objects, nor can their presence be detected usingobject_id() DDL triggers are listed in

sys.server_triggersandsys.triggersDMVs :

IF EXISTS (SELECT *

FROM sys.server_triggers WHERE Name = ‘DDL_Server_Level_Sample’) DROP TRIGGER DDL_Server_Level_Sample ON ALL SERVER

IF EXISTS (SELECT *

FROM sys.triggers WHERE Name = ‘DDL_Database_Sample’) DROP TRIGGER DDL_Database_Sample ON DATABASE

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

TỪ KHÓA LIÊN QUAN