Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 41 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
41
Dung lượng
327,29 KB
Nội dung
You can encrypt triggers or stored procedures to prevent anyone from looking into your source code. Just add the modifier WITH ENCRYPTION right before the AS keyword. Recursive triggers A trigger can call itself recursively (if the database option that allows it is set to true). For example, if a FOR UPDATE trigger contains an UPDATE statement for the base table, this trigger will be called again as this UPDATE executes, and again, and yet again. The maximum number of recursive calls is 32, which is also the maximum nesting depth. While a valid programming tool, recursive triggers can be tricky to write and you should exercise caution in using them. Besides implementing business logic, triggers are mainly used to enforce referential integrity (see Session 5). Though the best way to maintain referential integrity is normally to use the FOREIGN KEY constraint, triggers and stored procedures become a viable alternative in some situations. Check out Books Online or some advanced books on SQL Server 2000 for some examples of such situations. Nested triggers Triggers can be nested. They follow the same rules defined for stored procedures and cannot exceed 32 levels. One example of nested triggers can be a table whose FOR UPDATE makes an INSERT into the same table, thus invoking a FOR INSERT trigger, which in turn invokes a FOR DELETE trigger. It is possible that one trigger will invoke another that in turn invokes the first one, causing a so-called indefi- nite loop. Because of the maximum depth of nesting levels, this loop will stop after 32 cycles. The SQL Server 2000 default setting allows nested triggers. You can dis- able this option on the Server-level right-click menu by selecting Properties fol- lowed by an option on the Server Settings menu, or by executing the following system stored procedure: exec sp_configure ‘nested triggers’, 0 Note Note Saturday Afternoon142 204840-9 ch12.F 8/28/01 12:53 PM Page 142 Disabling nested triggers will automatically disable recursive triggers, regardless of the setting you may have in your database. Recursive triggers are a special kind of nested triggers. Managing Triggers The easiest way to manage triggers is through a visual interface (see Figure 12-1). You can view, modify, or delete a trigger. Behind the scenes, SQL Server will assem- ble and execute a batch of T-SQL statements; you can, of course, also create and execute these statements yourself. Triggers are powerful, built-in tools for implementing business rules in the SQL Server database as well as for enforcing referential integrity. I strongly recommend reading Session 16, “Understanding Transactions and Locks,” before attempting any real-life implementations. Creating triggers To create a trigger, simply run the code shown in Figure 12-2 from a Query Analyzer window. Dropping (deleting) triggers To drop/delete a trigger, use the following syntax: DROP TRIGGER <trigger name> You can drop more than one trigger at the same time by specifying a list of trig- gers. Dropping a trigger does not affect its base table. You can remove a trigger by dropping it or by dropping the table that it is associated with. When a table is dropped, all associated triggers are also dropped. Tip Note Session 12—Trigger Happy 143 Part III—Saturday Afternoon Session 12 204840-9 ch12.F 8/28/01 12:53 PM Page 143 Modifying triggers The easiest way to modify a trigger is to drop it and then create another one under the same name. If, for whatever reason, you need to preserve the trigger’s internal ID (a unique number under which the trigger is listed among system objects), you can use the ALTER TRIGGER statement. The T-SQL code following the AS keyword will replace the original code : ALTER TRIGGER tr_TwentyPercentRule ON employees AFTER UPDATE AS PRINT ‘NO MORE RULES’ You can quickly view the information about triggers defined on a table by using the system stored procedure sp_helptrigger. The syntax is as follows: exec sp_helptrigger <table name> REVIEW ¼ Many different types of triggers exist; each has a different use. ¼ You manage triggers as you would any other SQL Server database objects: either with T-SQL commands or through the Enterprise Console manager. QUIZ YOURSELF 1. What is a SQL Server trigger? 2. How is a trigger different from a stored procedure? 3. What are the SQL Server trigger types? 4. In response to what events would a trigger be fired? Tip Saturday Afternoon144 204840-9 ch12.F 8/28/01 12:53 PM Page 144 Session Checklist ✔ Using different types of cursors ✔ Understanding the scope of cursors ✔ Setting cursor concurrency options ✔ Choosing the right cursor T his session introduces Transact-SQL cursors, a very powerful programming tool for data manipulation. You will learn about different types of cursors, their advantages and disadvantages, programming considerations affecting cursors, and how to choose the right cursor for any given job. Understanding Cursors In the SQL Server environment sets are the most efficient means of accessing or modifying data, and you should use them whenever possible. For everything else there is a cursor. Cursor is an extension provided by SQL Server to enable you to SESSION Introducing Cursors 13 214840-9 ch13.F 8/28/01 12:53 PM Page 145 work with result sets returned by SELECT statements — one row at the time. From examples in previous sessions you should have a general idea of what will be returned by the following statement on the Pubs database: SELECT * FROM authors WHERE state = ‘CA’ This statement returns a result set of 15 rows. This is the result set you are working with and there is no way to access a single row within this result set without losing the rest of the rows. That is, unless you are using a cursor. If you want to update each record in a table differently, you either have to run a differ- ent query for each row, or use a cursor. You can request a cursor in SQL Server in two ways: inside the server itself by using Transact-SQL statements, or via a client application by using one of the sup- ported interfaces, such as Microsoft Active Data Objects, ODBC (Open Database Connectivity), OLE DB (the latest database interface from Microsoft), or DB-Library (a low-level programming interface to SQL Server). In this session I will concen- trate mainly on server-side cursors created with Transact-SQL. The basic syntax for declaring a simple cursor is similar to a standard T-SQL batch statement: DECLARE cur_California CURSOR FOR SELECT * FROM authors WHERE state = ‘CA’ Since the primary reason for opening a cursor is to scroll it, all cursors are scrol- lable (that is, you can navigate from record to record sequentially). In the interest of preserving system resources the default scrolling is forward-only; if you need to scroll backward, you open a specific type of cursor. (I’ll go into more detail about cursor types later in this session.) Once a cursor is declared you need to OPEN it so it can be populated with records: OPEN cur_California Once the cursor is open you can access the data by scrolling the cursor. In order to retrieve a row from a cursor you have to FETCH it as shown here: FETCH NEXT FROM cur_California FETCH instructs SQL Server to retrieve a single row from the result set contained in the cursor. Once you’ve examined the content of this row it is time to move on as follows: WHILE @@FETCH_STATUS = 0 BEGIN Saturday Afternoon146 214840-9 ch13.F 8/28/01 12:53 PM Page 146 The following code is executed as long as the previous FETCH succeeds: FETCH NEXT FROM cur_California END You have to organize a loop to scroll the cursor and you also need to know when to stop. The system function @@FETCH_STATUS will let you know when you reach the end of the cursor: 0 means that a row was successfully FETCHed, and anything else means that the FETCH NEXT statement failed. Once you are through with the cursor you need to explicitly close and destroy it: CLOSE cur_California DEALLOCATED cur_California Closing and de-allocating cursors is very important. An open cur- sor takes up a lot of memory that will not be freed until the cur- sor is closed and de-allocated; nor will you be able to open another cursor with the same name. If you run all the T-SQL statements introduced earlier in this session as a batch from the Query Analyzer window, in your Results pane you will see 15 separate rows as opposed to a single result set of 15 rows. In the preceding sample you FETCHed the whole row. It is possible to FETCH only the fields (columns) you are interested in; you can also declare a cursor on a join. You can use any valid T-SQL SELECT statement to produce a cursor. Here is an example of creating and scrolling a cursor containing records of the last names and first names of the authors living in California, ordered alphabeti- cally by last name: USE Pubs DECLARE @FirstNameVARCHAR(20) DECLARE @LastName VARCHAR(20) DECLARE cur_California CURSOR FOR SELECT au_lname,au_fname FROM authors WHERE state = ‘CA’ ORDER BY au_lname OPEN cur_California FETCH NEXT FROM cur_California INTO @FirstName, @LastName WHILE @@FETCH_STATUS = 0 BEGIN PRINT @LastName+ “,” + @FirstName Note Session 13—Introducing Cursors 147 Part III—Saturday Afternoon Session 13 214840-9 ch13.F 8/28/01 12:53 PM Page 147 The following code is executed as long as the previous FETCH succeeds: FETCH NEXT FROM cur_California INTO @FirstName, @LastName END CLOSE cur_California DEALLOCATE cur_California The result of this batch executed from the Query Analyzer will be a comma- delimited list of all authors’ first and last names. Using Different Types of Cursors According to your particular needs you may choose one of the four following types of cursors: ¼ Scrollable cursors ¼ Static cursors ¼ Dynamic cursors ¼ Keyset cursors ¼ Forward-only cursors You specify the type of cursor you want through a specific modifier in the dec- laration statement, as shown here: DECLARE cur_California CURSOR STATIC FOR SELECT au_fname, au_lname FROM authors WHERE state = ‘CA’ I discuss each type of cursor in the following sections. Scrollable cursors So far you have only scrolled the cursor forward. Forward-only is the default for any cursor type that opens for which no options are specified. To get a scrollable cursor that scrolls both ways, you should ask for one: DECLARE cur_California CURSOR SCROLL FOR SELECT au_fname, au_lname FROM authors WHERE state = ‘CA’ Saturday Afternoon148 214840-9 ch13.F 8/28/01 12:53 PM Page 148 Now you can move backward and forward. You can navigate a cursor using the FETCH command. ¼ FETCH PRIOR — Moves to the previous record in the result set. ¼ FETCH FIRST — Moves to the first record in the result set. ¼ FETCH LAST — Moves to the last record in the result set. ¼ FETCH ABSOLUTE number — Retrieves a specific position within the result set (FETCH ABSOLUTE 4, for example, retrieves the fourth record from the beginning.) The number you specify must be a positive integer. ¼ FETCH RELATIVE number — Works like FETCH ABSOLUTE, with the exception that the count starts from the current row: If you are on the fourth record in your result set FETCH RELATIVE 3 will take you to the seventh row from the beginning. The number you specify must be a positive integer. You should always check @@FETCH_STATUS to verify that the record was retrieved. At the beginning of the result set FETCH PRIOR does not yield any results and @@FETCH_STATUS is -1; when you are trying to fetch a row that was deleted after the cursor was opened, @@FETCH_STATUS is -2. The value of @@FETCH_STATUS is global to all cursors created on a particular connection, meaning that all cursors you happen to create and that have not yet been destroyed will affect its value. Static cursors Static cursors represent snapshots of the data: Once created, a static cursor does not reflect any subsequent changes to the underlying data. Static cursors in SQL Server are always read-only. They are the least resource-intensive scrollable type of cursor. Dynamic cursors Dynamic cursors, as their name implies, never lose a contact with the data from which they were created. Every modification (INSERT, UPDATE, or DELETE) is visi- ble through this cursor — that is, if it has been made through the cursor itself or committed to the database by other clients (to see uncommitted modifications made by others to the same set of data requires more advanced techniques). The dynamic cursor is always scrollable. Tip Session 13—Introducing Cursors 149 Part III—Saturday Afternoon Session 13 214840-9 ch13.F 8/28/01 12:53 PM Page 149 Keyset cursors KEYSET cursors behave almost exactly like DYNAMIC cursors, with the exception that the KEYSET cursors are — well — keyset-based. A keyset is a unique set of columns that the cursor’s SELECT statement contains, and only these values are guaranteed to be there while you are scrolling the cursor. When you OPEN the cur- sor the list of all key values is created in TempDB, a workbench for all databases in the SQL Server system. The keyset membership is fixed — after the cursor is OPENed, only the data present at that moment will be available for viewing. Forward-only cursors The forward-only cursor does not support scrolling, which means that you can only use FETCH NEXT — there’s no going back. The cursor is not built upon executing the OPEN statement; the FETCH NEXT command fetches the row directly from the database. Understanding the Scope of the Cursors By default, the cursor is global for the connection it was created with. This means that unless you close and de-allocate the cursor, you can use it throughout every T-SQL batch you execute on the connection. While this is certainly a convenient feature, you must be careful not to keep the cursor open longer than necessary. This is because SQL Server will generate an error if a T-SQL block or batch tries to open the same cursor before you close it. If you forget to de-allocate the cursor it will be hanging around until the connection to the SQL Server is closed. If you want to create a local version of a cursor you must explicitly state this at the database-settings level by setting CURSOR_DEFAULT to LOCAL (it is set to GLOBAL by default), or specifying it in the declaration of the cursor, as in the fol- lowing example: DECLARE cur_California CURSOR LOCAL FOR SELECT * FROM authors WHERE state = ‘CA’ Local cursors are visible only within the batch with which they were created and last only as long as it takes that batch to execute; they are implicitly de-allocated afterwards. Saturday Afternoon150 214840-9 ch13.F 8/28/01 12:53 PM Page 150 If you need to perform another cursor operation while scrolling a cursor, feel free. Unlike nested stored procedures or triggers, cur- sors are not limited to any nesting depth. Just keep in mind that the @@FETCH_STATUS function is global for the whole connection and that both cursors will affect it. Setting Cursor Concurrency Options Concurrency can become an issue in a fast-paced environment wherein many users are working on the same data set. How can users be sure that their changes are not being accidentally overridden by other users? By preventing anyone from modifying the record until you’re done — in other words, by placing a lock on it —you can pro- tect your changes. If you think that there’s a good chance that somebody else will try to modify the data while you are working with them, you may try other options. SQL Server 2000 supports four concurrency options: ¼ READ_ONLY — Use this option when you need only to see the data, not to modify it; this option uses the least system resources. ¼ OPTIMISTIC WITH VALUES — Use this option when you do want to update your data but estimate that the chances that a second user might try to update the same record at the same time are very slim: Any other user will get an error notification upon trying to update values that you’ve just changed. ¼ OPTIMISTIC WITH ROW VERSIONING — Use this option when you are still optimistic and prepared to take your chances, but want to make sure that only the whole row can be updated, not just some fields within it. ¼ SCROLL_LOCK — Use this option when you trust no one: Nobody can mod- ify a thing in the result set affected by your cursor until you are through with it. Unless you are using a cursor within a transaction (see Session 16), the cursor does not lock the records it was created against. This means that while you are scrolling your cursor somebody else can modify the underlying data. Depending on the type of cursor you are using you might not be aware of the changes until you close the cursor and reopen it. DYNAMIC cursors let you see the changes as they come — but you must take precautions in order to manipulate them correctly. By placing a lock on the underlying records you effectively deny anyone access to the Tip Session 13—Introducing Cursors 151 Part III—Saturday Afternoon Session 13 214840-9 ch13.F 8/28/01 12:53 PM Page 151 [...]... query SQL Server will have no problems creating such a table, but any insert statement relying on DEFAULT will fail and return the error message “column does not allow nulls.” 234840-9 ch 15. F 8/28/01 12 :53 PM Page 1 75 Session 15 Rules, Defaults, and Constraints 1 75 Understanding NULL Values When data are inserted into the table and neither a value nor a DEFAULT constraint is specified for a field, SQL Server. .. directly issue Transact -SQL commands T -SQL gives you several ways to specify PRIMARY KEY constraints; here is an example of the most basic method: 234840-9 ch 15. F 8/28/01 12 :53 PM Page 170 170 Saturday Afternoon can specify CASCADE to propagate the deletions to all the rows referenced by this key This feature is new to this version of SQL server (though it is similar to the cascading in Microsoft Access)... cursors different from T -SQL batch statements? 3 What is the purpose of the @@FETCH_STATUS system function? 4 What is the default scope of a cursor? How can you change it? 5 Why should you care about concurrency issues? Part III—Saturday Afternoon Session 13 2 What are the four basic types of cursors? 214840-9 ch13.F 8/28/01 12 :53 PM Page 154 224840-9 ch14.F 8/28/01 12 :53 PM Page 155 SESSION 14 Understanding... specified) all existing data are checked against the constraint SQL Server will raise an error if the constraint is violated Sometimes you need to disable a constraint temporarily: the following T -SQL statement will do that ALTER TABLE SampleTable NOCHECK CONSTRAINT sample_key_check As with most SQL Server objects you can choose to use T -SQL or the visual interface of the Enterprise Manager to create... clustered or non-clustered) for the following items: Part III—Saturday Afternoon Session 14 SQL Server 2000 enables you to define an index on computed columns This is rather an advanced feature: Refer to Books Online for a discussion of the computed-columns indexes 224840-9 ch14.F 8/28/01 12 :53 PM Page 158 158 Saturday Afternoon ¼ Large tables containing more than one hundred rows ¼ Frequently searched-for... can create an index either with the Create Index Wizard or with raw Transact -SQL; both methods produce identical results ¼ Once you have created an index, you can manage it through the Index Manager or by using system stored procedures 224840-9 ch14.F 8/28/01 12 :53 PM Page 166 234840-9 ch 15. F 8/28/01 12 :53 PM Page 167 SESSION 15 Rules, Defaults, and Constraints Session Checklist ✔ Enforcing data integrity... particular table, as shown here: USE Pubs EXEC sp_helpindex Titles 224840-9 ch14.F 8/28/01 12 :53 PM Page 1 65 Session 14—Understanding Indexes 1 65 Finally, you can use the system stored procedure sp_rename to rename the index with the following syntax: sp_rename ‘titles.sample_index’, ‘titles.new_index’,’INDEX’ SQL Server will display the following message: “Caution: Changing any part of an object name could... ch16.F 8/28/01 12 :54 PM Page 177 SESSION 16 Understanding Transactions and Locks Session Checklist ✔ Understanding transactions ✔ Setting isolation levels ✔ Learning about SQL Server locks ✔ Exploring lock types ✔ Dealing with deadlocks T ransactions are used in applications where maintaining data consistency is of importance This session is all about transactions and the mechanisms that SQL Server uses... integrity, which refers to the quality of the data If a table contains invalid data it is said to have lost its integrity 234840-9 ch 15. F 8/28/01 12 :53 PM Page 168 168 Saturday Afternoon Types of integrity These are the four different types of integrity you can enforce in SQL Server: ¼ Entity integrity — Refers to a row in the table Every row represents an entity whose integrity is maintained by means of... constraints In Session 5 you learned about the PRIMARY KEY and FOREIGN KEY constraints You can define a primary key on a column or a group of columns; a table can have only one primary key and by definition the key must be unique This requirement precludes the use of NULL as a value in any column that contains the primary key 234840-9 ch 15. F 8/28/01 12 :53 PM Page 169 Session 15 Rules, Defaults, and . cycles. The SQL Server 2000 default setting allows nested triggers. You can dis- able this option on the Server- level right-click menu by selecting Properties fol- lowed by an option on the Server. triggers as you would any other SQL Server database objects: either with T -SQL commands or through the Enterprise Console manager. QUIZ YOURSELF 1. What is a SQL Server trigger? 2. How is a trigger. request a cursor in SQL Server in two ways: inside the server itself by using Transact -SQL statements, or via a client application by using one of the sup- ported interfaces, such as Microsoft Active