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

Microsoft SQL Server 2008 R2 Unleashed- P176 ppsx

10 58 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 213,51 KB

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

Nội dung

LISTING 43.32 Implementing a Purge/Archive Scenario, Using the OUTPUT Clause declare @purge_date datetime, @rowcount int -- find the oldest month in the sales_big table select @purge_dat

Trang 1

only in a trigger The insertedanddeletedtables provide access to the new/old images of

the modified rows; this is similar to how they provide the information in triggers In an

INSERTstatement, you are allowed to access only the insertedtable In a DELETE

state-ment, you are allowed to access only the deletedtable In an UPDATEstatement, you are

allowed to access both the insertedanddeletedtables

Following is the general syntax of the OUTPUTclause:

UPDATE [ TOP ( expression ) [ PERCENT ] ] tablename

SET { column_name = { expression | DEFAULT | NULL }

| @variable = expression

| @variable = column = expression [ , n ]

} [ , n ]

OUTPUT

{ DELETED | INSERTED | from_table_name}.{* | column_name} | scalar_expression

[ INTO { @table_variable | output_table } [ ( column_list ) ] ] }

[ FROM { table_name } [ , n ] ]

[ WHERE search_conditions ]

DELETE [ TOP ( expression ) [ PERCENT ] ] tablename

OUTPUT { DELETED | from_table_name}.{* | column_name} | scalar_expression

[ INTO { @table_variable | output_table } [ ( column_list ) ] ] }

[ FROM ] table_name

[ FROM table_name [ , n ] ]

[ WHERE search_conditions ]

INSERT [ TOP ( expression ) [ PERCENT ] ] [ INTO ] tablename

{

[ ( column_list ) ]

[ OUTPUT { INSERTED | from_table_name}.{* | column_name} | scalar_expression

[ INTO { @table_variable | output_table } [ ( column_list ) ] ] ] }

{ VALUES ( { DEFAULT | NULL | expression } [ , n ] )

| SELECT_statement

}

}

The output table (output_table ) may be a table variable, permanent table, or temporary

table Ifcolumn_listis not specified, the output table must have the same number of

columns as theOUTPUTresult set If column_listis specified, any omitted columns must

either allowNULLvalues or have default values assigned to them Any identity or

computed columns in the output table must be skipped In addition, output_tablecannot

have any enabled triggers defined on it, participate on either side of a foreign key

constraint, or have any check constraints or enabled rules

Trang 2

One use of the OUTPUTclause is to verify the rows being deleted, updated, or inserted:

begin tran

delete from sales_big output deleted.*

where sales_id in (select top 10 sales_id from sales_big order by ord_date)

rollback

go

sales_id stor_id ord_num ord_date qty payterms title_id

- - - -

-168745 7067 P2121 2005-06-15 00:00:00.000 40 Net 30 TC3218

168746 7067 P2121 2005-06-15 00:00:00.000 20 Net 30 TC4203

168747 7067 P2121 2005-06-15 00:00:00.000 20 Net 30 TC7777

20 7067 P2121 2005-06-15 00:00:00.000 40 Net 30 TC3218

21 7067 P2121 2005-06-15 00:00:00.000 20 Net 30 TC4203

22 7067 P2121 2005-06-15 00:00:00.000 20 Net 30 TC7777

337470 7067 P2121 2005-06-15 00:00:00.000 40 Net 30 TC3218

337471 7067 P2121 2005-06-15 00:00:00.000 20 Net 30 TC4203

337472 7067 P2121 2005-06-15 00:00:00.000 20 Net 30 TC7777

506195 7067 P2121 2005-06-15 00:00:00.000 40 Net 30 TC3218

Another possible use of theOUTPUTclause is as a purge/archive solution Suppose you want to

periodically purge historic data from thesales_bigtable but also want to copy the purged

data into an archive table calledsales_big_archive Rather than writing a process that has

to select the rows to be archived before deleting them, or putting a delete trigger on the

table, you could use theOUTPUTclause to insert the deleted rows into the archive table

On approach would be to implement a loop to delete historic data (for example, delete

rows for the oldest month in the sales_bigtable) in chunks, using the TOPclause to

specify the chunk size The OUTPUTclause can be specified to copy the deleted rows into

thesales_big_archivetable, as shown in Listing 43.32

LISTING 43.32 Implementing a Purge/Archive Scenario, Using the OUTPUT Clause

declare @purge_date datetime,

@rowcount int

find the oldest month in the sales_big table

select @purge_date = dateadd(day, - (datepart(day, min(ord_date))) + 1,

dateadd(month, 1, min(ord_date))),

@rowcount = 1000

from sales_big

while @rowcount = 1000

begin

delete top (1000) sales_big

output deleted.* into sales_big_archive

where ord_date < @purge_date

set @rowcount = @@rowcount

end

Trang 3

In addition to referencing columns in the table being modified by using theINSERTEDor

DELETEDqualifier, you can also retrieve information from another table included in the

FROMclause of aDELETEor anUPDATEstatement used to specify the rows to update or delete:

begin tran

delete top (5) sales

output t.title_id

from sales s

join titles t on t.title_id = s.title_id

where t.pub_id = ‘9906’

rollback

go

title_id

-FI9620

CH2080

BI7178

CH8924

FI2680

When used with anUPDATEcommand,OUTPUTproduces both adeletedand aninserted

table Thedeletedtable contains the values before theUPDATEcommand, and the

insertedtable has the values after theUPDATEcommand TheOUTPUTclause is also useful

for retrieving the value of identity or computed columns after anINSERTor anUPDATE

operation Listing 43.33 shows an example ofOUTPUTbeing used to capture the computed

column as the result of anUPDATE.

LISTING 43.33 UsingOUTPUT to Capture a Computed Column

create table UpdateOutputTest

(col1 tinyint,

col2 tinyint,

computed_col3 as convert(float, col2/convert(float, col1)))

go

insert UpdateOutputTest (col1, col2)

output inserted.computed_col3

values (10, 20)

insert UpdateOutputTest (col1, col2)

output inserted.computed_col3

values (10, 25)

go

computed_col3

Trang 4

-2

computed_col3

-2.5

declare @output_table TABLE (del_col1 int, ins_col1 int,

del_col2 int, ins_col2 int, del_computed_col3 float, ins_computed_col3 float, mod_date datetime)

update UpdateOutputTest

set col2 = col2/5.0

output deleted.col1, inserted.col1,

deleted.col2, inserted.col2,

deleted.computed_col3, inserted.computed_col3,

getdate()

into @output_table

output deleted.computed_col3,

inserted.computed_col3,

getdate() as mod_date

select del_col1, ins_col1, del_col2, ins_col2,

del_computed_col3 as del_col3, ins_computed_col3 as ins_col3,

mod_date from @output_table

go

computed_col3 computed_col3 mod_date

- -

-2 0.4 -2010-0 -2 -28 19:48:34. -240

2.5 0.5 2010-02-28 19:48:34.240

del_col1 ins_col1 del_col2 ins_col2 del_col3 ins_col3 mod_date

- - - - - -

-10 -10 20 4 2 0.4 2010-02-28 19:48:34.240

10 10 25 5 2.5 0.5 2010-02-28 19:48:34.240

TheUPDATEstatement in Listing 43.33 also demonstrates the capability to use OUTPUTto

both insert values into a table and return values to the caller

Note that the OUTPUTclause is not supported in DML statements that reference local

parti-tioned views, distributed partiparti-tioned views, remote tables, or INSERTstatements that

contain an execute_statement Columns returned from OUTPUTreflect the data as it is

after the INSERT,UPDATE, or DELETEstatement has completed but before any triggers on

the target table are executed

Trang 5

Common Table Expressions

A common table expression (CTE) is an ANSI SQL-99 expression that produces a table that

is referred to by name within the context of a single query The general syntax for a CTE is

as follows:

WITH expression_name [ ( column_name [ , n ] ) ]

AS ( CTE_query_definition )

TheWITHclause, in effect, defines a table and its columns Note that the syntax of the

WITHclause is similar to that of a view You can think of a CTE as a temporary view that

lasts only for the life of the query that defines the CTE Listing 43.34 shows an example of

a simple CTE This CTE is used to return the average and maximum sales quantities for

each store The CTE is then joined to the salestable to return the average and maximum

sales quantity for the store, along with sales records for a specific title_id

LISTING 43.34 An Example of a Simple CTE

with sales_avg (stor_id, avg_qty, max_qty)

as (select stor_id, avg(qty), max(qty)

from sales

group by stor_id)

select top 5 s.stor_id, s.ord_num,

convert(varchar(10), ord_date, 101) as ord_date,

qty, title_id, avg_qty, max_qty

from sales s

join sales_avg a on s.stor_id = a.stor_id

where s.title_id = ‘DR8514’

go

stor_id ord_num ord_date qty title_id avg_qty max_qty

- - - -

-A004 ONGGGGGGGGGGGGGGG 09/13/2006 1224 DR8514 1008 1716

A068 ONEEEEEEEEEEE 09/02/2007 1572 DR8514 961 1572

A071 ONWWWWWWWWWWWWWWWWWW 08/20/2006 1728 DR8514 948 1728

A161 ONDDDDDDDDDDDD 05/25/2006 624 DR8514 829 1668

A203 ONGGGGGGGGGGGGGGGGGG 11/16/2006 1572 DR8514 1056 1692

NOTE

If theWITHclause for a CTE is not the first statement in the batch, you should delimit

it from the preceding statement by placing a semicolon (;) in front of it The semicolon

is used to avoid ambiguity with other uses of theWITHclause (for example, for table

hints) Including a semicolon is not necessary in all cases, but it is recommended that

you use it consistently to avoid problems

Trang 6

It is also possible to define multiple CTEs in a single query, with each CTE delimited by a

comma Each CTE is able to refer to previously defined CTEs Listing 43.35 shows an

example of a nested CTE that calculates the minimum, maximum, and difference of

counts of store orders

LISTING 43.35 An Example of Multiple CTEs in a Single Query

WITH store_orders(stor_id, cnt)

AS ( SELECT stor_id, COUNT(*) FROM sales

GROUP BY stor_id ),

MinMaxCTE(MN, MX, Diff)

AS ( SELECT MIN(Cnt), MAX(Cnt), MAX(Cnt)-MIN(Cnt)

FROM store_orders )

SELECT * FROM MinMaxCTE

go

MN MX Diff

-1 22 2 -1

A CTE must be followed by a single SELECT,INSERT, UPDATE, or DELETEstatement that

references some or all of the CTE columns A CTE can also be specified in a CREATE VIEW

statement as part of the defining SELECTstatement of the view

Listing 43.36 shows an example of a CTE used in a DELETEstatement

LISTING 43.36 An Example of a CTE in a DELETE

with oldest_sales (stor_id, ord_num, ord_date)

as (select top 100 stor_id, ord_num, ord_date from sales_big order by ord_date)

delete sales_big from sales_big s, oldest_sales o

where s.stor_id = o.stor_id

and s.ord_num = o.ord_num

and s.ord_date = o.ord_date

go

Most valid SELECTstatement constructs are allowed in a CTE, except the following:

COMPUTEorCOMPUTE BY

ORDER BY(except when a TOPclause is specified)

INTO

OPTIONclause with query hints

Trang 7

FOR XML

FOR BROWSE

Recursive Queries with CTEs

Nonrecursive CTEs are ANSI SQL-99 compliant expressions that provide T-SQL coding

flex-ibility However, for each nonrecursive CTE, there is usually another T-SQL construct that

can be used to achieve the same results (for example, derived tables) The real power and

capability of CTEs is revealed when you use them to create recursive queries

A recursive CTE can help simplify the code required to run a recursive query within a

SELECT, INSERT, UPDATE, DELETE, or CREATE VIEWstatement Recursive queries are often

useful for expanding a hierarchy stored in a relational table (for example, displaying

employees in an organizational chart) In previous versions of SQL Server, a recursive

query usually required using temporary tables, cursors, and logic to control the flow of the

recursive steps

A CTE is considered recursive when it refers to itself within the CTE definition Recursive

CTEs are constructed from at least two queries One is a nonrecursive query, also referred

to as the anchor member (AM) The other is the recursive query, also referred to as the

recursive member (RM) The queries are combined using the UNION ALLoperator

The following pseudocode defines the basic structure of a recursive CTE:

WITH cte_name ( column_name [, n] )

AS

( CTE_query_definition1 Anchor member (AM) is defined.

UNION ALL

CTE_query_definition2 Recursive member (RM) is referencing cte_name.

)

Statement using the CTE

SELECT col_list FROM cte_name

Logically, you can think of the algorithm implementing the recursive CTE as follows:

1 The anchor member is activated, and the initial result set (R) is generated

2 The recursive member is activated, using the initial result set (Rn) as input and

generating result set Rn+1.

3 The logic of step 2 is run repeatedly, incrementing the step number (n) until an

empty set is returned

4 The outer query is executed, getting the cumulative (UNION ALL) result of all the

pre-vious steps when referring to the recursive CTE

You can have more than two members in a recursive CTE, but only the UNION ALL

opera-tor is allowed between a recursive member and another recursive or nonrecursive member

Other operators, such as UNION, are allowed only between nonrecursive members

Trang 8

Recursive CTEs also require an exact match of the columns in all members, including the

same data type, length, and precision

Listing 43.37 shows a simple recursive CTE that generates a list of sequential numbers

Note that the AM generates the base result, and the RM following the UNION ALLcontrols

the recursion It is important in this example that a valid endpoint be defined to avoid

infinite recursion

LISTING 43.37 An Example of a Simple Recursive CTE

with numlist (val)

as (select 1

union all

select val + 1

from numlist

where val < 10)

select * from numlist

go

val

-1

2

3

4

5

6

7

8

9

10

The following sections present some examples and uses of recursive CTEs

Using Recursive CTEs for Expanding a Hierarchy

For this hierarchy example, we use the partstable in the bigpubs2008database This table

contains a simplified hierarchy of car parts, as shown in Figure 43.1

In thepartstable, any part that is a subpart of another part has the parent part ID stored

in theparentpartidcolumn Theparentpartidcolumn is a foreign key that references

thepartidcolumn Therefore, theparentpartidmust either correspond to a valid

partidwithin the table or beNULL For example, the car itself has NULLin the

parentpartidcolumn

Following are some common requests that might be run on the partstable:

Return all the parts for the engine

Trang 9

Car

Engine Transmission Driveshaft Axle

Flywheel

Clutch

Gearbox

Reverse Gear

First Gear

Second Gear

Third Gear

Fourth Gear

Radiator

Intake Manifold

Exhaust Manifold

Carburetor

Piston

Crankshaft

Piston Rings Float Valve

FIGURE 43.1 Theparts table hierarchy.

The first request is probably the most common one: returning a part (for example, the

engine, which has partid = 2) and all subparts The recursive CTE shown in Listing 43.38

provides a solution to this request

LISTING 43.38 A Recursive CTE to Return a Part and All Subparts

WITH PartsCTE(partid, partname, parentpartid, lvl)

AS

(

SELECT partid, partname, parentpartid, 0

FROM PARTS

WHERE partid = 2 Engine

UNION ALL

SELECT P.partid, P.partname, P.parentpartid, PP.lvl+1

FROM Parts as P

JOIN PartsCTE as PP

ON P.parentpartid = PP.Partid

)

Show me all parts that are two levels below the drivetrain

Show me all the parts in such a way that it is easy to see their hierarchical

depen-dencies

Trang 10

SELECT PartID, Partname, ParentPartid, lvl

FROM PartsCTE

go

PartID Partname ParentPartid lvl

- -

-2 Engine 1 0

5 Radiator 2 1

6 Intake Manifold 2 1

7 Exhaust Manifold 2 1

8 Carburetor 2 1

13 Piston 2 1

14 Crankshaft 2 1

21 Piston Rings 13 2

11 Float Valve 8 2

Notice that the lvlvalue is repeatedly incremented with each recursive invocation of the CTE You can use this level counter to limit the number of iterations in the recursion For example, Listing 43.39 shows an example of a CTE that returns all parts two levels below the drivetrain LISTING 43.39 A Recursive CTE to Return All Subparts Two Levels Below a Part WITH PartsCTE(partid, partname, parentpartid, lvl) AS ( SELECT partid, partname, parentpartid, 0 FROM PARTS WHERE partid = 1 Drivetrain UNION ALL SELECT P.partid, P.partname, P.parentpartid, PP.lvl+1 FROM Parts as P JOIN PartsCTE as PP ON P.parentpartid = PP.Partid where lvl < 2 ) SELECT PartID, Partname, ParentPartid, lvl FROM PartsCTE where lvl = 2 go PartID Partname ParentPartid lvl - -

-9 Flywheel 3 2

Ngày đăng: 05/07/2014, 02:20

TỪ KHÓA LIÊN QUAN