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

Tài liệu MASTERING SQL SERVER 2000- P7 doc

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

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Advanced Transact-SQL
Trường học University of Information Technology and Communications
Chuyên ngành Database Management
Thể loại Lecture Notes
Năm xuất bản 2000
Thành phố Hanoi
Định dạng
Số trang 50
Dung lượng 1,24 MB

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

Nội dung

Committing a nested transaction does not write the changes from that transactionpermanently to the database; it merely makes them available to the outer transaction.Suppose you have the

Trang 1

Committing a nested transaction does not write the changes from that transactionpermanently to the database; it merely makes them available to the outer transaction.Suppose you have the following SQL batch:

BEGIN TRANSACTIONUPDATE titlesSET price = 20.00WHERE title_id = ‘TC7777’

BEGIN TRANSACTIONUPDATE titlesSET type = ‘potboiler’

WHERE title_id = ‘TC7777’

COMMIT TRANSACTIONROLLBACK TRANSACTION

In this case, the COMMIT TRANSACTION statement tells SQL Server that you’refinished with the second transaction that you started However, the ROLLBACKTRANSACTION then rolls back all the work since the first BEGIN TRANSACTION,including the inner nested transaction

Although transaction names appear to offer increased readability for your code,they interact poorly with nested transactions In fact, you can refer to a transaction

by name only if it’s the outermost transaction in a batch Our recommendation is toavoid naming transactions if you plan to ever nest transactions

if there’s only one transaction open, the changes are written immediately

It’s your responsibility to make sure you’ve made all the changes you want beforeissuing a COMMIT TRANSACTION statement Once a transaction has been commit-ted, it can’t be rolled back

Although you can use a name in the COMMIT TRANSACTION statement, SQLServer makes no attempt to match this to a name in a BEGIN TRANSACTION state-ment The name’s purely for your convenience in making your code more readable

Trang 2

COMMIT, with or without the optional keyword WORK, is exactly synonymous toCOMMIT TRANSACTION with no transaction name This form of the statement isANSI SQL-92 compatible

@savepoint_variable]

ROLLBACK [WORK]

ROLLBACK TRANSACTION throws away all changes since the most recent BEGINTRANSACTION Again, you can supply a transaction name as either a constant or avariable, but SQL Server ignores this name

You can also roll back part of a transaction by supplying a savepoint name We’lltalk about savepoints in the next section If a transaction is a distributed transaction(one that affects databases on multiple servers), you can’t roll back to a savepoint

ROLLBACK, with or without the optional WORK keyword, is the SQL-92 ant form of the statement However, in this form, you can’t roll back only one of a set

compli-of nested transactions ROLLBACK WORK always rolls back to the outermost (first)transaction in a batch

WAR N I N G ROLLBACK WORK rolls back all nested transactions and sets

@@TRANCOUNT to zero

If you call ROLLBACK TRANSACTION as part of a trigger, subsequent SQL ments in the same batch are not executed On the other hand, if you call ROLLBACKTRANSACTION in a stored procedure, subsequent SQL statements in the same batchare executed

Trang 3

Note that when you issue SAVE TRANSACTION, you must name it This name vides a reference point for a subsequent COMMIT TRANSACTION or ROLLBACKTRANSACTION statement.

pro-An example will make the use of SAVE TRANSACTION more clear Consider thefollowing T-SQL batch:

BEGIN TRANSACTIONUPDATE titlesSET price = 20.00WHERE title_id = ‘TC7777’

SAVE TRANSACTION pricesavedUPDATE titles

SET type = ‘potboiler’

@@TRANCOUNT

The @@TRANCOUNT system global variable tells you the number of nested tions that are currently pending If no transactions are pending, this variable will con-tain zero This is useful for determining whether a trigger, for example, is executing inthe middle of a transaction already started by a T-SQL batch

transac-@@ERROR

The @@ERROR system global variable holds the most recent error number from any T-SQL statement Whenever a statement is executed that does not cause an error, thisvariable will contain zero That is, it’s reset to zero every time you successfully execute

a statement So if you want to check at some later point whether a statement hascaused an error, you need to save the value of @@ERROR to a local variable

Trang 4

UPDATE titlesSET price = 20.00WHERE title_id = ‘TC7777’

SET @price_err = @@ERRORSAVE TRANSACTION pricesavedUPDATE titles

SET type = ‘potboiler’

WHERE title_id = ‘TC7777’

SET @type_err = @@ERROR

IF @type_err <> 0 ROLLBACK TRANSACTION pricesaved

IF @price_err = 0 AND @type_err = 0 BEGIN

COMMIT TRANSACTIONPRINT ‘Changes were successful’

ENDELSEROLLBACK TRANSACTION

Here’s a blow-by-blow account of this batch:

1 The DECLARE statement sets up two local variables.

2 The BEGIN TRANSACTION statement starts a transaction.

3 The first UPDATE statement makes a change to the price column.

4 The first SET statement is used to save the value of @@ERROR so that you can

check later whether the first UPDATE statement was successful Note that thisstatement must immediately follow the UPDATE statement

5 The SAVE TRANSACTION statement sets a savepoint.

6 The second UPDATE statement makes a change to the type column.

7 The second SET statement is used to save the value of @@ERROR so you can tell

whether the second UPDATE statement succeeded

8 If there was an error on the second UPDATE statement, the first ROLLBACK

TRANSACTION statement undoes the transaction back to the savepoint

9 If there are no errors at all, the transaction is committed, and a message is

printed Note the use of BEGIN and END to group two T-SQL statements intoone logical statement This is necessary because the IF statement refers only tothe following statement

Trang 5

10 If there are any errors, the second ROLLBACK TRANSACTION statement undoes

all of the work

Distributed Transactions

So far, we’ve been discussing local transactions: those that make changes in a singledatabase SQL Server also supports distributed transactions: transactions that makechanges to data stored in more than one database These databases need not be SQLServer databases; they can be databases on other linked servers

NOTE For more information on linked servers, see Chapter 6

A distributed transaction can be managed in code using exactly the same SQLstatements as you’d use for a local transaction However, when you issue a COMMITTRANSACTION on a distributed transaction, SQL Server automatically invokes a pro-

tocol called two-phase commit (sometimes referred to as 2PC) In the first phase, SQL

Server asks every database involved to prepare the transaction The individual bases verify that they can commit the transaction and set aside all the resources nec-essary to do so It’s only if every involved database tells SQL Server that it’s OK tocommit the transaction that the second phase starts In this phase, SQL Server tellsevery involved database to commit the transaction If any of the databases involvedare unable to commit the transaction, SQL Server tells all of the databases to roll backthe transaction instead

data-Microsoft DTC

Distributed transactions are managed by a SQL Server component called the

Distrib-uted Transaction Coordinator (DTC) This is a separate service that’s installed at the

same time as SQL Server If you’re going to use distributed transactions, you shouldset this service to autostart Figure 8.1 shows this service selected in the SQL ServerService Manager

Trang 6

BEGIN DISTRIBUTED TRANSACTION

You can tell SQL Server explicitly to start a distributed transaction with the BEGINDISTRIBUTED TRANSACTION statement:

BEGIN DISTRIBUTED TRANS[ACTION]

Transaction Tips

Transactions consume resources on the server In particular, when you change datawithin a transaction, that data must be locked to ensure that it’s available if you com-mit the transaction So, in general, you need to make transactions efficient to avoidcausing problems for other users Here are a few points to consider:

• Don’t do anything that requires user interaction within a transaction, becausethis can cause locks to be held for a long time while the application is waitingfor the user

• Don’t start transactions for a single SQL statement

• Change as little data as possible when in a transaction

Trang 7

• Don’t start a transaction while the user is browsing through data Wait untilthey’re actually ready to change the data.

• Keep transactions as short as possible

Rowset Functions

Rowset functions are functions that return an object that can be used in place of a table

in another SQL statement For example, as you saw in Chapter 7, some rowset tions can be used to provide the rows to be inserted with an INSERT statement Thereare five rowset functions in SQL Server 2000:

of most of the statements we’ve examined so far:

CONTAINSTABLE (table_name, {column_name | *},

<search_condition> […n]

}

Trang 8

<simple_term> ::=

word | “phrase”

<weighted_term> ::=

ISABOUT ({{

CON-• Using the asterisk (*) to specify columns tells CONTAINSTABLE to search allcolumns that have been registered for full-text searching, which might not beall the columns in the table

• Weight values are numbers between zero and one that specify how importanteach match is considered to be in the final virtual table

Trang 9

• You can limit the number of results returned by specifying an integer in the

top_n parameter This is useful when you’re searching a very large source table

and want to see only the most important matches

The CONTAINSTABLE statement returns a virtual table containing two columns,always named KEY and RANK For example, consider the following statement:

SELECT * FROMCONTAINSTABLE(Products, ProductName,

‘ISABOUT(mix WEIGHT(.8), sauce WEIGHT(.2))’)

Assuming that you’ve enabled the Product table in the Northwind sample databasefor full-text searching on the ProductName column, this statement returns the resultsshown in Figure 8.2 The ISABOUT search condition here specifies that results con-

taining the word mix should be rated as more important than those containing the word sauce.

FIGURE 8.2

Using CONTAINSTABLE

to generate a virtual table

The KEY column will always contain values from the column that you identified asthe primary key to the full-text indexing service To make this statement more useful,you’ll probably want to use this column to join back to the original table Figure 8.3shows the results of the following statement:

SELECT ProductName, RANK FROMCONTAINSTABLE(Products, ProductName,

‘ISABOUT(mix WEIGHT(.8), sauce WEIGHT(.2))’)

Trang 10

AS CINNER JOIN Products

ON Products.ProductID = C.[KEY]

FIGURE 8.3

Using CONTAINSTABLE joined to the original search table

N OTE The virtual table needs to be aliased to be included in a join, and you mustinclude the square brackets around the joining name because KEY is a SQL Server keyword

Trang 11

You can think of FREETEXTTABLE as being like a black-box version of TABLE Internally, SQL Server breaks the freetext string up into words, assigns aweight to each word, and then looks for similar words For example, the followingstatement could be used to retrieve items whose description looks somehow similar

Trang 12

OPENQUERY

The OPENQUERY statement lets you use any query (SQL statement that returns rows)

on a linked server to return a virtual table The syntax of OPENQUERY is as follows:

OPENQUERY(linked_server, ‘query’)

NOTE For more information on creating linked servers, see Chapter 6

Figure 8.5 shows in SQL Server Enterprise Manager that the MOOCOW serverknows about a linked server named BIGREDBARN, which is also a Microsoft SQLServer If you connected to the BIGREDBARN server directly, you could run a querylike the following:

SELECT * FROM Northwind.dbo.Customers

FIGURE 8.5

Inspecting properties for a linked server

This query would return all of the rows in the Customers table owned by dbo inthe Northwind database So far, there’s no need for OPENQUERY However, suppose

ROWSET FUNCTIONS

P A R TII

Trang 13

you want to join the Customers table from the BIGREDBARN server to the Orderstable from the MOOCOW server In this case, you might connect to the MOOCOWserver and run the following statement instead:

SELECT CompanyName, OrderID, OrderDate FROMOPENQUERY(BIGREDBARN, ‘SELECT * FROM Northwind.dbo.Customers’)

AS CustomersINNER JOIN Orders

ON Customers.CustomerID = Orders.CustomerIDORDER BY OrderID

Note that the original query that retrieved the records in the context of theBIGREDBARN server has been incorporated as one of the parameters of the OPEN-QUERY statement

OPENQUERY is the easiest tool that you can use to perform distributed queriesusing SQL Server By using OPENQUERY, you can join any number of tables from dif-ferent data sources These data sources don’t even need to be SQL Server tables; aslong as they’re data sources that you can represent as linked servers (basically, anydata source that you have an OLE DB provider to connect with), you can use themwith OPENQUERY

OPENROWSET

OPENROWSET also provides a way to use data from a different server in a SQL Serverstatement In the case of OPENROWSET, you supply the information needed to con-nect via OLE DB directly:

par-SELECT CompanyName, OrderID, OrderDate FROMOPENROWSET(‘SQLOLEDB’, ‘BIGREDBARN’;’sa’;’’,

‘SELECT * FROM Northwind.dbo.Customers’)

AS CustomersINNER JOIN Orders

ON Customers.CustomerID = Orders.CustomerIDORDER BY OrderID

Trang 14

OPEN-OPENDATASOURCE(provider_name, connection_string)

OPENDATASOURCE is more flexible than OPENROWSET in that SOURCE can be used in place of a linked server name, so it need not refer to any par-ticular database or table on the other server You can use OPENDATASOURCE to refer

Trang 15

For example, you could perform the same query that was shown in the ROWSET example with the following OPENDATASOURCE statement:

OPEN-SELECT CompanyName, OrderID, OrderDate FROMOPENDATASOURCE(‘SQLOLEDB’,

‘Data Source=BIGREDBARN;User ID=sa;Password=’

).Northwind.dbo.Customers

AS CustomersINNER JOIN Orders

ON Customers.CustomerID = Orders.CustomerIDORDER BY OrderID

TI P OPENROWSET and OPENDATASOURCE should be used only for data sources thatyou need to query on an infrequent basis If you need to regularly connect to a particulardata source, it’s more efficient to use a linked server for that connection

Cursors

Traditionally, SQL provides a set-oriented look for your data For example, when youexecute a SELECT statement, it returns a set of rows This set is all one thing, not aselection of individual rows Although this is a useful view for many traditionalbatch-processing applications, it’s less appealing for interactive applications where auser might want to work with rows one at a time

What Are Cursors?

SQL Server’s solution to this problem is to introduce cursors If you’ve worked withrecordsets in a product such as Access or Visual Basic, you can understand cursors as a

server-side recordset A cursor is a set of rows together with a pointer that identifies a

current row T-SQL provides statements that allow you to move the pointer and towork with the current row In the remainder of this section, you’ll learn about the fol-lowing statements:

Trang 16

DECLARE CURSOR

The DECLARE CURSOR statement is used to set aside storage for a cursor and to setthe basic properties of the cursor Actually, there are two different forms of theDECLARE CURSOR statement The first form is the ANSI standard DECLARE CURSOR:

DECLARE cursor_name [INSENSITIVE][SCROLL] CURSOR FOR select_statement

[FOR {READ ONLY | UPDATE [OF column_name [,…n]]}]

In this form of the DECLARE CURSOR statement:

• The DECLARE and CURSOR keywords are required to declare a cursor

• The cursor_name is an arbitrary SQL identifier that will identify this cursor in

subsequent T-SQL statements

• INSENSITIVE tells SQL Server to establish a temporary table just for this cursor

Modifications that other users make while the cursor is open will not bereflected in the cursor’s data, and you won’t be able to make any modificationsthrough the cursor

• SCROLL specifies that all of the options of the FETCH statement should be ported If you omit SCROLL, only FETCH NEXT is supported

• The select_statement argument is a standard T-SQL SELECT statement that

sup-plies the rows for the cursor This statement cannot use the COMPUTE, PUTE BY, FOR BROWSE, or INTO options

COM-• READ ONLY prevents any updates through the cursor By default, the cursor willallow updating (unless it was opened with the INSENSITIVE option)

• UPDATE specifies explicitly that the cursor should allow updating If you use UPDATE OF with a list of column names, only data in those columns can

be updated

There’s also an extended form of DECLARE CURSOR that is not ANSI SQL compatible:

DECLARE cursor_name CURSOR

[LOCAL | GLOBAL]

[FORWARD_ONLY | SCROLL]

[STATIC | KEYSET | DYNAMIC | FAST_FORWARD]

[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]

[TYPE_WARNING]

FOR select_statement [FOR UPDATE [OF column_name [ , n]]]

In this form of the DECLARE CURSOR statement:

• The DECLARE and CURSOR keywords are required to declare a cursor

Trang 17

• The cursor_name is an arbitrary SQL identifier that will identify this cursor in

subsequent T-SQL statements

• The LOCAL keyword limits the use of the cursor to the batch, stored procedure,

or trigger where it was created

• The GLOBAL keyword makes the cursor available to any statement on the rent connection

cur-• FORWARD_ONLY specifies that only the NEXT option of the FETCH statement

• KEYSET specifies that the cursor should be updateable, both by the connectionand by other users However, new rows added by other users won’t be reflected

in the cursor

• DYNAMIC specifies that the cursor should be fully updateable and that itshould reflect new rows

• READ_ONLY specifies that the cursor should be read-only

• SCROLL_LOCKS specifies that updates or deletions made through the cursorshould always succeed SQL Server ensures this by locking the rows as soon asthey’re read into the cursor

• OPTIMISTIC uses optimistic locking when you attempt to change a rowthrough the cursor

• TYPE_WARNING tells SQL Server to send a warning if the selected cursoroptions can’t all be fulfilled

• The select_statement argument is a standard T-SQL SELECT statement that

sup-plies the rows for the cursor This statement cannot use the COMPUTE, PUTE BY, FOR BROWSE, or INTO options

COM-• FOR UPDATE specifies explicitly that the cursor should allow updating If youuse UPDATE OF with a list of column names, only data in those columns can beupdated

Trang 18

OPEN and @@CURSOR_ROWS

The OPEN statement is used to populate a cursor with the records to which it refers:

OPEN {{[GLOBAL] cursor_name} | cursor_variable_name}

You must use the GLOBAL keyword if you’re referring to a cursor declared with theGLOBAL keyword You can use either the name of a cursor directly or the name of acursor variable (one declared with the DECLARE statement and set equal to a cursorwith the SET statement)

Of course, the cursor must be declared before you issue the OPEN statement

If the cursor was declared with the INSENSITIVE or STATIC keywords, the OPENstatement will create a temporary table in the tempdb database to hold the records Ifthe cursor was declared with the KEYSET keyword, the OPEN statement will create atemporary table in the tempdb database to hold the keys You don’t need to worryabout these tables; SQL Server will delete them when the cursor is closed

Once a cursor has been opened, you can use the @@CURSOR_ROWS global able to retrieve the number of rows in this cursor For example, consider the followingT-SQL batch:

vari-DECLARE customer_cursor CURSORLOCAL SCROLL STATIC

FORSELECT * FROM CustomersOPEN customer_cursorPRINT @@CURSOR_ROWS

As you can see in Figure 8.7, the PRINT statement shows that all 91 rows of theCustomers table are in the cursor

Trang 19

WAR N I N G The @@CURSOR_ROWS variable always refers to the most recentlyopened cursor You may want to store the value of this variable directly after the OPENstatement so that you can refer to it later.

You need to be a bit cautious about using @@CURSOR_ROWS, because under somecircumstances, it won’t reflect the actual number of rows in the cursor That’s becauseSQL Server might decide to fetch data into the cursor asynchronously, so that process-ing can continue while the cursor is still being populated

SQL Server will fill a cursor asynchronously if the cursor is declared with the TIC or KEYSET parameters and SQL Server estimates that the number of rows will begreater than a certain threshold value You can set this value with the sp_configure

STA-system stored procedure; the name of the option is cursor threshold By default, the

value is set to –1, which tells SQL Server to always populate cursors synchronously

NOTE See Chapter 14 for more information on sp_configure

Depending on the circumstances, @@CURSOR_ROWS might return one of the lowing values:

fol-• A negative number indicates that the cursor is being populated asynchronouslyand shows the number of rows retrieved so far The value –57, for example, indi-cates that the cursor has 57 rows, but that SQL Server has not finished populat-ing the cursor

• The value –1 is a special case that’s always returned for dynamic cursors Becauseother users can be adding or deleting data, SQL Server can’t be sure about thenumber of rows in a dynamic cursor, or whether it’s fully populated

• Zero indicates that there isn’t an open cursor

• A positive number indicates that the cursor is fully populated with that number

of rows

FETCH and @@FETCH_STATUS

The FETCH statement is used to retrieve data from a cursor to variables so that youcan work with the data This statement has a number of options:

FETCH[[ NEXT | PRIOR | FIRST | LAST

Trang 20

| ABSOLUTE {n | @n_variable}

| RELATIVE {n | @n_variable}

]FROM]

{{[GLOBAL] cursor_name} | @cursor_variable_name}

[INTO @variable_name [,…n]]

If you keep in mind that a cursor is a set of records with a pointer to a particularrecord, it’s pretty easy to understand the FETCH statement FETCH is used to movethe record pointer

• NEXT is the default option and fetches the next row in the cursor If FETCH NEXT

is the first statement issued, it fetches the first row from the cursor

• PRIOR fetches the previous row in the cursor

• FIRST fetches the first row in the cursor

• LAST fetches the last row in the cursor

• ABSOLUTE fetches the particular record specified For example, ABSOLUTE 5fetches the fifth record If you use a variable to hold the number, the variablemust be of type int, smallint, or tinyint

• RELATIVE fetches a record ahead or behind the current record by the specifiedamount For example, RELATIVE 5 fetches the record five past the currentrecord, and RELATIVE –5 fetches the record five before the current record If youuse a variable to hold the number, the variable must be of type int, smallint, ortinyint

• INTO lets you specify variables that will hold the fetched data You must supplyenough variables to hold all the columns from the cursor The variables will befilled in column order, and the datatypes must match those in the cursor or bedatatypes that can be implicitly converted from those in the cursor

Not all FETCH options are supported by all cursors, depending on how the cursorwas declared Here are the rules:

• If the cursor was declared with SQL-92 syntax without SCROLL, only NEXT issupported

• If the cursor was declared with SQL-92 syntax with SCROLL, all options are ported

sup-• If the cursor was declared with SQL Server syntax with FORWARD_ONLY orFAST_FORWARD, only NEXT is supported

Trang 21

• If the cursor was declared with SQL Server syntax with DYNAMIC SCROLL, alloptions except ABSOLUTE are supported.

• If the cursor was declared with SQL Server syntax and doesn’t fall into one ofthe above two categories, all options are supported

The @@FETCH_STATUS global variable contains information on the most recentFETCH operation If the value is zero, the fetch was successful If the value is not zero,the FETCH statement failed for some reason

As a simple example of FETCH, here’s how you might print the data from the firstrow of a cursor:

DECLARE @customerid nchar(5), @companyname nvarchar(100)DECLARE customer_cursor CURSOR

LOCAL SCROLL STATICFOR

SELECT CustomerID, CompanyName FROM CustomersOPEN customer_cursor

FETCH NEXT FROM customer_cursorINTO @customerid, @companynamePRINT @customerid + ‘ ‘ + @companyname

More often, you’ll want to do something that moves through an entire cursor Youcan do this by using the @@FETCH_STATUS variable with the WHILE statement Wehaven’t discussed the WHILE statement yet, but it’s similar to WHILE in most otherprogramming languages It performs the next statement repeatedly as long as somecondition is true Figure 8.8 shows an example of using FETCH to retrieve multiplerows by executing the following T-SQL batch:

DECLARE @customerid nchar(5), @companyname nvarchar(100)DECLARE customer_cursor CURSOR

LOCAL SCROLL STATICFOR

SELECT CustomerID, CompanyName FROM CustomersOPEN customer_cursor

FETCH NEXT FROM customer_cursorINTO @customerid, @companynamePRINT @customerid + ‘ ‘ + @companynameWHILE @@FETCH_STATUS = 0

BEGINFETCH NEXT FROM customer_cursorINTO @customerid, @companynamePRINT @customerid + ‘ ‘ + @companynameEND

Trang 22

FIGURE 8.8

Fetching multiple rows of data with a WHILE loop

CLOSE

The CLOSE statement is the reverse of the OPEN statement Its syntax is similar tothat of OPEN:

CLOSE {{[GLOBAL] cursor_name} | cursor_variable_name}

When you’re done with the data in a cursor, you should execute a CLOSE ment This frees up the rows that are being held in the cursor, but it does not destroythe cursor itself The cursor could be reopened by executing the OPEN statementagain While a cursor is closed, of course, you can’t execute a FETCH statement on it

state-DEALLOCATE

The DEALLOCATE statement is the reverse of the DECLARE CURSOR statement:

DEALLOCATE {{[GLOBAL] cursor_name} | cursor_variable_name}

CURSORS

P A R TII

Trang 23

When you’re done with a cursor, you should use DEALLOCATE to destroy the sor data structures and remove the name from the SQL Server namespace.

PRINT ‘Results for ‘ + CAST(@@CURSOR_ROWS AS varchar) +

‘ customers’

Print ‘—————————————’

FETCH NEXT FROM customer_cursorINTO @customerid, @companynameSELECT @norders = (

SELECT COUNT(*) FROM ORDERS WHERE CustomerID = @customerid)PRINT @companyname + ‘ (‘ + @customerid + ‘) has ‘ +CAST(@norders AS varchar) + ‘ orders’

WHILE @@FETCH_STATUS = 0BEGIN

FETCH NEXT FROM customer_cursorINTO @customerid, @companynameSELECT @norders = (

SELECT COUNT(*) FROM ORDERS WHERE CustomerID = @customerid)PRINT @companyname + ‘ (‘ + @customerid + ‘) has ‘ + CAST(@norders AS varchar) + ‘ orders’

ENDCLOSE customer_cursorDEALLOCATE customer_cursor

Trang 24

Let’s look at the statements in this batch, step by step:

• The first DECLARE statement sets aside storage for two variables

• The second DECLARE statement sets aside storage for one more variable

• The third DECLARE statement declares a static cursor to hold information fromtwo columns in the Customers table

• The OPEN statement gets the rows that the cursor declares

• The first PRINT statement uses the @@CURSOR_ROWS global variable to printthe number of records in the cursor Note the use of the CAST statement to con-vert this numeric value to character format before the value is concatenatedwith other strings

• The first FETCH NEXT statement gets the first row from the cursor

• The SELECT statement uses some of the data from the cursor together with theCOUNT function to count the rows in the Orders table for the first customer

• The PRINT statement formats the selected data for the user

• The WHILE statement tells SQL Server to continue until it’s exhausted the cursor

• The BEGIN statement marks the start of the statements controlled by theWHILE statement

• The FETCH NEXT, SELECT, and PRINT statements within the WHILE loop tellSQL Server to continue fetching rows and printing the results

• The END statement marks the end of the statements controlled by the WHILEstatement

• The CLOSE statement removes the records from the cursor

• The DEALLOCATE statement removes the cursor from memory

Can you visualize the results of running this batch of T-SQL statements? You canrefer to Figure 8.9 to confirm your results

Trang 25

FIGURE 8.9

Running a batch in SQL Query Analyzer

NOTE If you’re working with a client data-access library such as ADO, you may neverneed to deal with SQL Server’s cursor functions directly You’ll be able to get the same ben-efits by opening a recordset on the client Behind the scenes, ADO will be using the cursorfunctions itself, freeing you from managing the cursors See Chapter 19 for more informa-tion on ADO

Ngày đăng: 21/01/2014, 08:20

TỪ KHÓA LIÊN QUAN