Panteley Sylvia 100 White Johnson 100 Straight Dean 100 Locksley Charlene 100 Carson Cheryl 100 Blotchet-Halls Reginald 100 del Castillo Innes 100 Note that no real difference exists bet
Trang 1Panteley Sylvia 100
White Johnson 100
Straight Dean 100
Locksley Charlene 100
Carson Cheryl 100
Blotchet-Halls Reginald 100
del Castillo Innes 100
Note that no real difference exists between left and right outer joins except for specifying which table on which side of the join condition is to be the controlling, or outer, table For example, the previous query would provide the same result if you reversed the tables in the join clause and made it a right outer join: select au_lname, au_fname, avg(royaltyper) from dbo.titleauthor ta right outer join dbo.authors a on ta.au_id = a.au_id group by au_lname, au_fname order by 3 A full outer join returns all matching rows from both tables, along with all rows from each table, without a corresponding match in the other table: select a.au_fname, p.pub_name from dbo.authors a full outer join dbo.publishers p on a.state = p.state go au_fname pub_name -
-James A NULL Francine du Plessix Kumquat Technical Publishing Jean NULL E.L Nordome Titles Justin Algodata Infosystems April Sidney’s Books and More Ron Algodata Infosystems Jack NULL Matt NULL Josef NULL
Albert Ramona Publishers
NULL Gooseberry Titles
NULL Binnet & Hardley
NULL GGG&G
NULL Lucerne Publishing
NULL Tomato Books
NULL Significant Titles Company
Trang 2OUTER JOIN Versus WHERE Clause Matching
With the ANSI join syntax, you specify the join condition in the FROMclause Additional
search conditions can be specified in either the JOINclause or WHEREclause It’s important
to remember that in a left or right outer join, search conditions specified in the ONclause
work differently than search conditions in the WHEREclause:
Search conditions in the WHEREclause always exclude nonmatching rows.
Search conditions in the ONclause sometimes exclude rows and sometimes do not.
Needless to say, it can be somewhat confusing to figure out which rows and data values
will be returned To demonstrate the use of search conditions in the WHEREclause versus
theONclause, the examples presented in this section make use of the two views shown in
Listing 43.15.
LISTING 43.15 CREATE VIEW Statements for Outer Join Examples
CREATE VIEW dbo.STORES_V1 AS
SELECT STOR_ID, CITY FROM DBO.STORES WHERE STOR_ID BETWEEN ‘A001’ AND ‘A005’
go
CREATE VIEW dbo.STORES_V2 AS
SELECT STOR_ID, STATE FROM DBO.STORES WHERE STOR_ID BETWEEN ‘A002’ AND ‘A007’
UNION ALL
SELECT ‘A004’, ‘MA’
go
select * from dbo.stores_v1
select * from dbo.stores_v2
STOR_ID CITY
-
-A001 Dublin
A002 Oakland
A003 Bisbee
A004 White Plains
A005 Thomaston
(5 row(s) affected)
STOR_ID STATE
-A002 NJ
A003 AZ
A004 NY
Trang 3A005 GA
A006 CA
A007 CA
A004 MA
Listing 43.16 provides an example of a left outer join query that includes the search
condition in the ONclause All rows are returned from STORES_V1, and NULLvalues are
returned for STORES_V2where there isn’t a matching STOR_IDor where there is a matching
STOR_IDbutSTATEis not equal to ’GA’.
LISTING 43.16 Specifying the Search Condition in the ON Clause
SELECT * FROM DBO.STORES_V1 V1
LEFT OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
AND V2.STATE <> ‘GA’
ORDER BY V1.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-A001 Dublin NULL NULL
A002 Oakland A002 NJ
A003 Bisbee A003 AZ
A004 White Plains A004 MA
A004 White Plains A004 NY
A005 Thomaston NULL NULL
Now, if you put the search condition in the WHEREclause, as shown in Listing 43.17, the
nonmatching rows from STORES_V2are filtered out because the NULLvalue returned for
STATEdoes not match the WHEREclause search criteria WHERE V2.STATE <> ‘GA’.
(Remember that NULLvalues are neither equal to nor not equal to other values.)
LISTING 43.17 Specifying a Search Condition in a WHERE Clause
SELECT * FROM DBO.STORES_V1 V1
LEFT OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
WHERE V2.STATE <> ‘GA’
ORDER BY V1.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-A002 Oakland -A002 NJ
Trang 4A003 Bisbee A003 AZ
A004 White Plains A004 MA
A004 White Plains A004 NY
To include the nonmatching rows from STORES_V2, you need to add a check for NULLto
theWHEREclause, as shown in Listing 43.18.
LISTING 43.18 Including Nonmatching Inner Table Rows That Do Not Match a WHERE Clause
Search Condition
SELECT * FROM DBO.STORES_V1 V1
LEFT OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
WHERE (V2.STATE <> ‘GA’ or V2.STATE is NULL)
ORDER BY V1.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-A001 Dublin NULL NULL
A002 Oakland A002 NJ
A003 Bisbee A003 AZ
A004 White Plains A004 MA
A004 White Plains A004 NY
Notice that the row whereSTOR_ID = ‘A005’is still not included in the result set The
query shown in Listing 43.18 also demonstrates another difference between specifying a
search condition in theWHEREclause and theONclause In this case, the outer join is
performed first, so that all rows and selected column values are returned from
STORES_V2, including the row whereSTOR_ID = ‘A005’, without considering theWHERE
clause condition:
SELECT * FROM DBO.STORES_V1 V1
LEFT OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
go
STOR_ID CITY STOR_ID STATE
-A001 Dublin NULL NULL
A002 Oakland A002 NJ
A003 Bisbee A003 AZ
A004 White Plains A004 NY
A004 White Plains A004 MA
A005 Thomaston A005 GA
Trang 5After the join result is returned, because the STATEvalue is equal to ’GA’, the search
condi-tion in the WHEREclause (V2.STATE <> ‘GA’) filters out that row.
In a left or right outer join, a search condition in the ONclause also works differently,
depending on whether it refers to a field in the inner or outer table If the ONclause search
condition refers to a field in the outer table, it determines whether the related row finds a
match (The outer row is returned regardless.) For example, Listing 43.19 demonstrates a
search condition in the ONclause that restricts which rows in STORES_V1(the outer table)
join to STORES_V2 The join is performed only for those rows in STORES_V1whereCITYis
greater than N However, all rows from STORES_V1are still returned.
LISTING 43.19 Specifying an ON Clause Search Condition on the Outer Table
SELECT * FROM DBO.STORES_V1 V1
LEFT OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
AND V1.CITY > ‘N’
ORDER BY V1.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-A001 Dublin NULL NULL
A002 Oakland A002 NJ
A003 Bisbee NULL NULL
A004 White Plains A004 MA
A004 White Plains A004 NY
A005 Thomaston A005 GA
If theONclause search condition refers to a field in the inner table, it determines
whether the related row matches the join Listing 43.20 shows an example of specifying
theONclause search condition on the inner table Again, notice that all rows from
STORES_V1are returned, but only the matching rows are returned fromSTORES_V2, where
STOR_IDis less thanA004.
LISTING 43.20 Specifying an ON Clause Search Condition on the Inner Table
SELECT * FROM DBO.STORES_V1 V1
LEFT OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
AND V2.STOR_ID < ‘A004’
ORDER BY V1.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
Trang 6
A001 Dublin NULL NULL
A002 Oakland A002 NJ
A003 Bisbee A003 AZ
A004 White Plains NULL NULL
A005 Thomaston NULL NULL
When you perform a left or right outer join, a search condition against the outer table in
theONclause works differently from the same search condition specified in the WHERE
clause As shown in Listing 43.19, when the search condition in the ONclause filters on a
field in the outer table, the outer row is returned, regardless, with no matching rows
returned from the inner table However, if the search condition on the OUTERtable is
spec-ified in the WHEREclause, the outer row is eliminated from the result set, as shown in
Listing 43.21.
LISTING 43.21 Specifying an Outer Table Search Condition in the WHERE Clause
SELECT * FROM DBO.STORES_V1 V1
LEFT OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
WHERE V1.CITY > ‘N’
ORDER BY V1.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-A002 Oakland -A002 NJ
A004 White Plains A004 MA
A004 White Plains A004 NY
A005 Thomaston A005 GA
Nested Outer Joins
When using the ANSI JOINsyntax, you must be careful about mixing outer joins with
inner joins because the query may not generate the desired result if the outer join is not
continued down to the lowest level For example, consider the query shown in Listing
43.22 The intent of this query is to list all authors whose state equals NEand, for those
authors, display the titles of their associated books, if any.
LISTING 43.22 An Outer Join Nested in an Inner Join
select left(au_lname, 20) as au_lname, au_fname, left(title, 20) as title
from dbo.authors a
left join dbo.titleauthor ta on a.au_id = ta.au_id
join dbo.titles t on ta.title_id = t.title_id
where a.state = ‘NE’
Trang 7go
au_lname au_fname title
-Patterson Richard North The Lasko Tangent
Patterson Richard North The Outside Man
Patterson Richard North Private Screening
Patterson Richard North Eyes of a Child
Patterson Richard North Degree of Guilt
Patterson Richard North Escape the Night
However, because the outer join is not carried to the titlestable, the author with no
matching row in the titleauthortable ends up getting filtered from the result set The
reason is that when the outer join is performed between authorsandtitleauthor,
because no matching row is found, NULLis returned for title_id Because a normal inner
join is performed on the titlestable, the NULLvalue for title_iddoes not match any
rows in the titlestable, so the author with no matching rows in titleauthorends up
getting filtered out To see those authors, you need to modify the query in Listing 43.22 to
carry the outer join down to the join between titleauthorandauthors:
select left(au_lname, 20) as au_lname, au_fname, left(title, 20) as title
from dbo.authors a
left join dbo.titleauthor ta on a.au_id = ta.au_id
left join dbo.titles t on ta.title_id = t.title_id
where a.state = ‘NE’
go
au_lname au_fname title
-Patterson Richard North The Lasko Tangent
Patterson Richard North The Outside Man
Patterson Richard North Private Screening
Patterson Richard North Eyes of a Child
Patterson Richard North Degree of Guilt
Patterson Richard North Escape the Night
McBadden Heather NULL
Working with Full Outer Joins
A full outer join selects rows from both tables and joins those rows that match on the join
fields In addition to the matching rows, one copy of each nonmatching row from each
table is returned Listing 43.23 shows an example of a full outer join.
Trang 8LISTING 43.23 Full Outer Join Example
SELECT * FROM DBO.STORES_V1 V1
FULL OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
ORDER BY V1.STOR_ID ,V2.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-NULL -NULL A006 CA
NULL NULL A007 CA
A001 Dublin NULL NULL
A002 Oakland A002 NJ
A003 Bisbee A003 AZ
A004 White Plains A004 MA
A004 White Plains A004 NY
A005 Thomaston A005 GA
As you can see from the results in Listing 43.23, all rows are returned from both
STORES_V1andSTORES_V2.
In a full outer join, a search condition in theONclause is handled differently from a search
condition in theWHEREclause in that it never results in a row being excluded from the result
set All it does is categorize the input row as being either matching or nonmatching In
Listing 43.24, a search condition (V1.STOR_ID > ‘A003’) is specified in theONclause As you
can see, any rows that do not meet that search condition are returned as nonmatching rows.
LISTING 43.24 Specifying a Search Condition in a Full Outer Join ON Clause
SELECT * FROM DBO.STORES_V1 V1
FULL OUTER JOIN DBO.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
AND V1.STOR_ID > ‘A003’
ORDER BY V1.STOR_ID ,V2.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-NULL -NULL A002 NJ
NULL NULL A003 AZ
NULL NULL A006 CA
NULL NULL A007 CA
A001 Dublin NULL NULL
A002 Oakland NULL NULL
A003 Bisbee NULL NULL
A004 White Plains A004 MA
A004 White Plains A004 NY
A005 Thomaston A005 GA
Trang 9As you can see, when you work with full outer joins, search arguments in the ONclause
serve only to define which rows are used as matching rows for a join Search arguments
specified in the WHEREclause define which rows are returned It’s important to note that
theWHEREclause conditions behave as if the join is an inner join and are applied after the
join is done Listing 43.25 shows an example.
LISTING 43.25 Specifying a Search Condition in a Full Outer Join WHERE Clause
SELECT * FROM dbo.STORES_V1 V1
FULL OUTER JOIN dbo.STORES_V2 V2
ON V1.STOR_ID = V2.STOR_ID
WHERE V1.STOR_ID > ‘A003’
ORDER BY V1.STOR_ID ,V2.STOR_ID ,V2.STATE
go
STOR_ID CITY STOR_ID STATE
-A004 White Plains -A004 MA
A004 White Plains A004 NY
A005 Thomaston A005 GA
Generating T-SQL Statements with T-SQL
The system catalogs in SQL Server 2008 contain a wealth of information you can use to
save a lot of time and effort when generating SQL statements that need to be run
repeat-edly on a large number of database objects or when trying to build a column list for a
query You can use T-SQL code to select information from the system catalogs, system
tables, and system views to generate SELECTstatements and the like For example, say you
want to grant EXECUTEpermission to the user fredon each stored procedure in the
bigpubs2008database This can be a tedious task to perform using SSMS because in the
Securables dialog for the user fred, you have to select each procedure, one at a time, and
click the Grant Execute check box If there were a large number of procedures, this could
be pretty time-consuming, and your mouse-clicking finger would probably get pretty tired.
The quicker and easier way would be to build the SQL statements necessary to grant
EXECUTEpermission to fredon all the stored procedures The following SELECTstatement
can be used to generate a SQL script with those commands:
select ‘grant execute on ‘ + name + ‘ to fred’
from sys.procedures
order by name
go
-grant execute on byroyalty to fred
Trang 10grant execute on cursor_proc to fred
grant execute on error_handler to fred
grant execute on find_books_by_type2 to fred
grant execute on gen_sequence to fred
grant execute on get_authors to fred
grant execute on get_next_item_from_queue to fred
grant execute on get_titles to fred
grant execute on p_explicit_cols to fred
grant execute on p_fetch_explicit_cols to fred
grant execute on p_insert_explicit_cols to fred
grant execute on reptq1 to fred
grant execute on reptq2 to fred
grant execute on reptq3 to fred
grant execute on SHOW_PARTS_LIST to fred
grant execute on title_authors to fred
grant execute on trantest to fred
grant execute on ytd_sales to fred
grant execute on ytd_sales2 to fred
You can copy and paste the output from this statement into a query window in SSMS and
execute it to grant the desired permissions When you get to know your system catalog
views, you can begin to automate the generation of a number of SQL operations in this
manner, freeing up your time to spend on more interesting projects.
When you are writing T-SQL code that needs to check for both errors and the number of
rows affected after your SQL statements, one of the common pitfalls is trying to get both
the error status and the number of rows after a SQL statement runs You have to
remem-ber that all SQL statements except the DECLAREstatement reset the value of @@ROWCOUNT
and@@ERRORto the status of the last command executed.
If after a SQL statement you check the value of @@ERROR, the statement used to check
@@ERRORresets@@ROWCOUNT If you check @@ROWCOUNTfirst, it resets the value of @@ERROR To
check both values, you need to use an assignment SELECTimmediately after the SQL
state-ment you are checking and capture both values into local variables Note that you cannot
accomplish this with the SETstatement because the SETstatement allows setting a value
to only a single variable at a time.
The example in Listing 43.26 provides a way to capture and check both @@ROWCOUNTand
@@ERRORafter an UPDATEstatement in a T-SQL batch.
LISTING 43.26 Capturing Both @@ROWCOUNT and @@ERROR After an UPDATE Statement
declare @rowcnt int,
@error int
UPDATE dbo.titles set price = price * 1.10
where type = ‘fiction’