Tải bản đầy đủ (.pdf) (10 trang)

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

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (468.1 KB, 10 trang )

Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 212
Part II Manipulating Data With Select
RESULT:
SELECT LastName,
DATENAME(yy,DateOfBirth) AS [Year],
DATENAME(mm,DateOfBirth) AS [Month],
DATENAME(dd,DateOfBirth) AS [Day],
DATENAME(weekday, DateOfBirth) AS BirthDay
FROM dbo.Guide
WHERE DateOfBirth IS NOT NULL;
LastName Year Month Day BirthDay

Frank 1958 September 4 Thursday
TABLE 9-2
DateTime Portions Used by Date Functions
Portion Abbreviation
year yy, yyyy
quarter qq, q
month mm, m
dayofyear dy, d
day dd, d
week wk, ww
weekday dw
hour hh
minute mi, n
second ss, s
millisecond ms
microsecond mcs
nanosecond ns
TZoffset tz
There are two supported types: DateTime and DateTime2. DateTime2 is new to SQL


Server 2008 and represents time to a much finer granularity: within 100 nanoseconds.
■ DatePart(date portion, date): Returns the ordinal number of the selected portion of
the datetime value. The following example retrieves the day of the year and the day of the
week as integers:
212
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 213
Data Types, Expressions, and Scalar Functions 9
SELECT DATEPART(dayofyear, CURRENT_TIMESTAMP) AS DayCount;
Result:
DayCount

321
SELECT DATEPART(weekday, CURRENT_TIMESTAMP) AS DayWeek;
Result:
DayWeek

7
An easy way to obtain just the date, stripping off the time, is to use a couple of string
functions:
SELECT CONVERT(char(10), CURRENT_TIMESTAMP, 112) AS "DateTime";
■ DateAdd(DATE PORTION, AMOUNT, BEGINNING DATE) and DateDiff(DATE PORTION,
BEGINNING DATE, ENDING DATE): Performs addition and subtraction on datetime data,
which databases often need to do. The
DATEDIFF() and the DATEADD() functions are
designed expressly for this purpose. The
DATEDIFF() doesn’t look at the complete date, only
the date part being extracted:
select DATEDIFF(year,’september 4 2008’,’november 10 2009’)
Result

1
select DATEDIFF(month,’september 4 2008’,’november 10 2009’)
2
The following query calculates the number of years and days that my wife, Melissa, and I have been
married:
SELECT
DATEDIFF(yy,’19840520’, CURRENT_TIMESTAMP) AS MarriedYears,
DATEDIFF(dd,’19840520’, CURRENT_TIMESTAMP) AS MarriedDays;
Result:
MarriedYears MarriedDays

17 6390
The next query adds 100 hours to the current millisecond:
SELECT DATEADD(hh,100, CURRENT_TIMESTAMP) AS [100HoursFromNow];
Result:
100HoursFromNow

2009-11-21 18:42:03.507
The following query is based on the Family sample database and calculates the mother’s age at the
birth of each child, using the
DateDiff() function:
213
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 214
Part II Manipulating Data With Select
USE Family;
SELECT Person.FirstName + ‘ ‘ + Person.LastName AS Mother,
DATEDIFF(yy, Person.DateOfBirth,
Child.DateOfBirth) AS AgeDiff,Child.FirstName
FROM Person

INNER JOIN Person AS Child
ON Person.PersonID = Child.MotherID
ORDER By Age DESC;
The DATEDIFF() function in this query returns the year difference between PERSON.DATEOFBIRTH,
which is the mother’s birth date, and the child’s date of birth. Because the function is in a column
expression, it is calculated for each row in the result set:
Mother AgeDiff FirstName

Audrey Halloway 33 Corwin
Kimberly Kidd 31 Logan
Elizabeth Campbell 31 Alexia
Melanie Campbell 30 Adam
Grace Halloway 30 James

This section discusses functions that are new to SQL Server 2008. You will take a look at the functions
and then see the results of some queries.
ToDateTimeOffset(expression, time_zone): Returns a DateTimeOffset value
The following example gets the date and time for a given time zone:
SELECT TODATETIMEOFFSET(CURRENT_TIMESTAMP,’-07:00’);
Result:
2009-11-05 11:24:15.490 -07:00
String Functions
Like most modern programming languages, T-SQL includes many string-manipulation functions:

SUBSTRING(string, starting position, length): Returns a portion of a string. The
first parameter is the string, the second parameter is the beginning position of the substring to
be extracted, and the third parameter is the length of the string extracted:
SELECT SUBSTRING(’abcdefg’, 3, 2);
Result:
cd

214
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 215
Data Types, Expressions, and Scalar Functions 9
■ STUFF(string, insertion position, delete count, string inserted):The
STUFF() function inserts one string into another string. The inserted string may delete a
specified number of characters as it is being inserted:
SELECT STUFF(’abcdefg’, 3, 2, ‘123’);
Result:
ab123efg
The following code sample uses nested STUFF() functions to format a U.S. social security
number:
SELECT STUFF(STUFF(’123456789’, 4, 0, ‘-’), 7, 0, ‘-’);
Result:
123-45-6789
■ CHARINDEX(search string, string, starting position): Returns the character
position of a string within a string. The third argument is optional and rarely used in practice.
It defaults to 1.
SELECT CHARINDEX(’c’, ‘abcdefg’, 1);
Result:
3
The user-defined function dbo.pTitleCase() later in this section uses CHARINDEX() to
locate the spaces separating words.

PATINDEX(pattern, string): Searches for a pattern, which may include wildcards, within
a string. The following code locates the first position of either a
c or a d in the string:
SELECT PATINDEX(’%[cd]%’, ‘abdcdefg’);
Result:
3

■ RIGHT(string, count) and Left(string, count): Returns the rightmost or leftmost
part of a string:
SELECT LEFT(’Nielsen’,2) AS ‘ [Left] ‘,
RIGHT(’Nielsen’,2) AS [Right];
Result:
Left Right

Ni en
215
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 216
Part II Manipulating Data With Select
■ LEN(string): Returns the length of a string:
SELECT LEN(’Supercalifragilisticexpialidocious’) AS [Len];
Result:
Len

34
■ RTRIM(string) and LTrim(string): Removes leading or trailing spaces. While it’s
difficult to see in print, the three leading and trailing spaces are removed from the fol-
lowing string. They are often used together as
RTRIM(LTRIM(string). I adjusted the
column-header lines with the remaining spaces to illustrate the functions:
SELECT RTRIM(’ middle earth ‘) AS [RTrim],
LTRIM(’ middle earth ‘) AS [LTrim];
Result:
RTrim LTrim

middle earth middle earth
■ UPPER(string) and Lower(string): Converts the entire string to uppercase or lowercase.

There’s not much to know about these two functions, illustrated here:
SELECT UPPER(’one TWO tHrEe’) AS UpperCase,
LOWER(’one TWO tHrEe’) AS LowerCase;
Result:
UpperCase LowerCase

ONE TWO THREE one two three
■ REPLACE(string, string):TheReplace() function operates as a global search and
replace within a string. Using
REPLACE() within an update DML command can quickly fix
problems in the data, such as removing extra tabs or correcting string patterns. The follow-
ing code sample adds apostrophes to the
LastName column in the OBXKITES database’s
CONTACT table:
USE OBXKites;
Create test case by modifying one contact’s last name.
UPDATE Contact
SET LastName = ‘Adam’’s’
WHERE LastName = ‘Adams’;
Check the modified sample data and the replacement.
SELECT LastName, REPLACE(LastName, ‘’’’, ‘’) AS Replaced
FROM Contact
WHERE LastName LIKE ‘%’’%’;
216
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 217
Data Types, Expressions, and Scalar Functions 9
Result:
LastName Replaced


Adam’s Adams
To demonstrate the REPLACE() function using an update command, the next query actually changes
the data in place and removes any apostrophes:
UPDATE Contact
SET LastName = REPLACE(LastName, ‘’’’, ‘’)
WHERE LastName LIKE ‘%’’%’;
Show that the modification was successful.
SELECT LastName
FROM Contact
WHERE LastName LIKE ‘Adam%’;
Result:
LastName

Adams
When working with string literals, it’s generally difficult to insert a quote into the string
without ending the string and causing a syntax error. SQL Server handles this situation by
accepting two single quotes and converting them into one single quote within the string:
’Life’’s Great! ‘ is interpreted as Life’s Great!
■ dbo.pTitleCase(source, search, replace): T-SQL lacks a function to convert text to
title case (first letter of each word in uppercase, and the remainder in lowercase). Therefore,
the following user-defined function accomplishes that task:
CREATE FUNCTION dbo.pTitleCase (
@StrIn NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN;
DECLARE
@StrOut NVARCHAR(MAX),
@CurrentPosition INT,
@NextSpace INT,

@CurrentWord NVARCHAR(MAX),
@StrLen INT,
@LastWord BIT;
SET @NextSpace = 1;
SET @CurrentPosition = 1;
217
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 218
Part II Manipulating Data With Select
SET @StrOut = ‘’;
SET @StrLen = LEN(@StrIn);
SET @LastWord = 0;
WHILE @LastWord = 0
BEGIN;
SET @NextSpace =
CHARINDEX(’ ‘, @StrIn, @CurrentPosition + 1);
IF @NextSpace = 0 no more spaces found
BEGIN;
SET @NextSpace = @StrLen;
SET @LastWord = 1;
END;
SET @CurrentWord =
UPPER(SUBSTRING(@StrIn, @CurrentPosition, 1));
SET @CurrentWord = @CurrentWord +
LOWER(SUBSTRING(@StrIn, @CurrentPosition+1,
@NextSpace - @CurrentPosition));
SET @StrOut = @StrOut + @CurrentWord;
SET @CurrentPosition = @NextSpace + 1;
END;
RETURN @StrOut;

END;
Running a user-defined function requires including the owner name in the function name:
SELECT dbo.pTitleCase(’one TWO tHrEe’) AS TitleCase;
Result:
TitleCase

One Two Three
The dbo.pTitleCase function does not take into consideration surnames with nonstandard
capitalization, such as McDonald, VanCamp, or de Jonge. It would be inadequate to hard-
code a list of exceptions. Perhaps the best solution is to store a list of exception phrases (Mc, Van, de,
and so on) in an easily updateable list.
The code for the
pTitleCase user-defined function can be downloaded from www.SQLServerBible.com.
Soundex Functions
Soundex is a phonetic pattern-matching system created for the American census. Franklin Roosevelt
directed the United States Bureau of Archives to develop a method of cataloguing the population that
could handle variations in the spelling of similar surnames. Margaret K. Odell and Robert C. Russell
developed Soundex and were awarded U.S. patents 1261167 (1918) and 1435663 (1922) for their
efforts. The census filing card for each household was then filed under the Soundex method. Soundex
has been applied to every census since and has been post-applied to census records back to 1880.
218
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 219
Data Types, Expressions, and Scalar Functions 9
The purpose of Soundex is to sort similar-sounding names together, which is very useful for dealing
with contact information in a database application. For example, if I call a phone bank and give them
my name (Nielsen), they invariably spell it ‘‘Nelson’’ in the contact lookup form, but if the database uses
Soundex properly, then I’ll still be in the search-result list box.
For more information concerning Soundex and its history, refer to the following websites:


www.nara.gov/genealogy/coding.html
■ www.amberskyline.com/treasuremaps/uscensus.html
■ www.bluepoof.com/soundex/
Here’s how Soundex works. The first letter of a name is stored as the letter, and the following Soundex
phonetic sounds are stored according to the following code:
1 = B, F, P, V
2 = C, G, J, K, Q, S, X, Z
3 = D, T
4 = L
5 = M, N
6 = R
Double letters with the same Soundex code, A, E, I, O, U, H, W, Y, and some prefixes, are disregarded.
Therefore, ‘‘Nielsen’’ becomes ‘‘N425’’ via the following method:
1. The N is stored.
2. The i and e are disregarded.
3. The l sound is stored as the Soundex code 4.
4. The s is stored as the Soundex code 2.
5. The e is ignored.
6. The n is stored as the Soundex code 5.
By boiling them down to a few consonant sounds, Soundex assigns ‘‘Nielsen,’’ ‘‘Nelson,’’ and ‘‘Neilson’’
the same code: N425.
Following are additional Soundex name examples:
■ Brown = B650 (r = 6, n = 5)
■ Jeffers = J162 (ff = 1, r = 6, s = 2)
■ Letterman = L365 (tt = 3, r = 6, m = 5)
■ Nicholson = N242 (c = 2, l = 4, s = 2)
■ Nickols = N242 (c = 2, l = 4, s = 2)
SQL Server includes two Soundex-related functions,
SOUNDEX() and DIFFERENCE().
219

www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 220
Part II Manipulating Data With Select
Using the SOUNDEX() function
The SOUNDEX(string) function calculates the Soundex code for a string as follows:
SELECT SOUNDEX(’Nielsen’) AS Nielsen,
SOUNDEX(’Nelson’) AS NELSON,
SOUNDEX(’Neilson’) AS NEILSON;
Result:
Nielsen NELSON NEILSON

N425 N425 N425
Other, more refined, Soundex methods exist. Ken Henderson, in his book
The Guru’s Guide
to Transact SQL
(Addison-Wesley, 2000), provides an improved Soundex algorithm and
stored procedure. If you are going to implement Soundex in a production application, I recommend
exploring his version. Alternately, you can research one of the other refined Soundex methods on the
websites listed previously and write your own custom stored procedure.
There are two possible ways to add Soundex searches to a database. The simplest method is to add the
SOUNDEX() function within the WHERE clause, as follows:
USE CHA2;
SELECT LastName, FirstName
FROM dbo.Customer
WHERE SOUNDEX(’Nikolsen’) = SOUNDEX(LastName);
Result:
LastName FirstName

Nicholson Charles
Nickols Bob

While this implementation has the smallest impact on the data schema, it will cause performance issues
as the data size grows because the
SOUNDEX() function must execute for every row in the database,
and an index on the name column (if any) cannot be used with an efficient seek operation, but only
with a much more expensive scan. A faster variation of this first implementation method pre-tests for
names with the same first letter, thus enabling SQL Server to use any indexes to narrow the search, so
fewer rows must be read and the
SOUNDEX() function must be performed only for rows selected by
the index:
SELECT LastName, FirstName
FROM dbo.Customer
WHERE SOUNDEX(’Nikolsen’) = SOUNDEX(LastName)
AND LastName LIKE ‘N%’;
The first query executes in 37.7 milliseconds on my test server, while the improved second query exe-
cutes in 6.5 milliseconds. I suspect that the performance difference would increase with more data.
220
www.getcoolebook.com
Nielsen c09.tex V4 - 07/21/2009 12:40pm Page 221
Data Types, Expressions, and Scalar Functions 9
The second implementation method is to write the Soundex value in a column and index it with a non-
clustered index. Because the Soundex value for each row is calculated during the write, the
SOUNDEX()
function does not need to be called for every row read by the SELECT statement. This is the method I
recommend for a database application that heavily depends on Soundex for contact searches.
The
OBXKITES sample database demonstrates this method. The SoundexCode column is persisted cal-
culated column, so it’s automatically calculated for every insert and kept updated with every update.
Searching for a row, or all the matching rows, based on the stored Soundex code is extremely fast.
First determine the Soundex for ‘‘Smith’’:
USE OBXKites;

SELECT SOUNDEX(’Smith’);
Result:

S530
Knowing the Soundex value for ‘‘Smith,’’ the Soundex search is now a fast index seek without ever call-
ing the
SOUNDEX() function for the row being read during the select statement:
SELECT LastName, FirstName, SoundexCode
FROM Contact
WHERE SoundexCode = ‘S530’;
Result:
LastName FirstName SoundexCode

Smith Ulisius S530
Smith Oscar S530
Using the DIFFERENCE() Soundex function
The second SQL Server Soundex function, DIFFERENCE(), returns the Soundex difference between two
strings in the form of a ranking from 1 to 4, with 4 representing a perfect Soundex match:
USE CHA2
SELECT LastName, DIFFERENCE(’Smith’, LastName) AS NameSearch
FROM Customer
ORDER BY Difference(’Smith’, LastName) DESC;
Result:
LastName NameSearch

Smythe 4
Spade 3
Zeniod 3
221
www.getcoolebook.com

×