Beginning Microsoft SQL Server 2008 ... - S3 Tech Training
Beginning Microsoft SQL Server 2008 ... - S3 Tech Training Beginning Microsoft SQL Server 2008 ... - S3 Tech Training
Chapter 13: User-Defined Functions 424 Look back through the list of requirements for a deterministic function and see if you can figure out why this one doesn’t meet the grade. When I was working on this example, I got one of those not so nice little reminders about how it’s the little things that get you. You see, I was certain this function should be deterministic, and, of course, it wasn’t. After too many nights writing until the morning hours, I completely missed the obvious — SCHEMABINDING. Fortunately, we can fix the only problem this one has. All we need to do is add the WITH SCHEMABINDING option to our function, and we’ll see better results: ALTER FUNCTION dbo.DayOnly(@Date date) RETURNS date WITH SCHEMABINDING AS BEGIN RETURN @Date; END Now, we just rerun our OBJECTPROPERTY query: ----------- 1 (1 row(s) affected) And voilà — a deterministic function! We can compare this, however, with our AveragePrice function that we built in the AdventureWorks2008 database. It looked something like this: CREATE FUNCTION dbo.AveragePrice() RETURNS money WITH SCHEMABINDING AS BEGIN RETURN (SELECT AVG(ListPrice) FROM Production.Product); END GO CREATE FUNCTION dbo.PriceDifference(@Price money) RETURNS money AS BEGIN RETURN @Price - dbo.AveragePrice(); END In this function we used schema-binding right from the beginning, so let’s look at our OBJECTPROPERTY: USE AdventureWorks2008; SELECT OBJECTPROPERTY(OBJECT_ID(‘AveragePrice’), ‘IsDeterministic’);
Despite being schema-bound, this one still comes back as being non-deterministic. That’s because this function references a table that isn’t local to the function (a temporary table or table variable created inside the function). Under the heading of “one more thing,” it’s also worth noting that the PriceDifference function we created at the same time as AveragePrice is also non-deterministic. For one thing, we didn’t make it schema-bound, but, more important, it references AveragePrice — if you reference a non-deterministic function, then the function you’re creating is non-deterministic by association. Debugging User-Defined Functions This actually works just the same as the sproc example we saw in Chapter 12. Simply set up a script that calls your function, and begin stepping through the script (using the toolbar icon, or pressing F11). You can then step right into your UDF. .NET in a Database W orld Chapter 13: User-Defined Functions As we discussed in Chapter 12, the ability to use .NET assemblies in our stored procedures and functions was added to SQL Server back in SQL Server 2005. Much as it does with sprocs, this has enormous implications for functions. Considering most who read this title will be beginners, it’s hard to fully relate the impact that .NET has in our database world. The reality is that you won’t use it all that often, and yet, when you do, the effects can be profound. Need to implement a complex formula for a special function? No problem. Need to access external data sources such as credit card authorization companies and such things? No problem. Need to access other complex data sources? No problem. In short, things we used to have to either skip or perform extremely complex development to achieve (in some cases, it was all smoke and mirrors before) suddenly become relatively straightforward. What does this mean in terms of functions? Well, I already gave the example of implementing a complex formula in a function. But now imagine something like external tabular data — let’s say representing a .csv or some other data in a tabular fashion — very doable with a .NET assembly created as a function in SQL Server. .NET assemblies in SQL Server remain, however, something of an advanced concept, and one I’ll defer to the Professional series title for SQL Server 2008. That said, it’s important to understand that the option is available and consider it as something worth researching in that “Wow, I have no idea how we’re going to do this!” situation. 425
- Page 412 and 413: Chapter 12: Stored Procedures 374 [
- Page 414 and 415: Chapter 12: Stored Procedures Confi
- Page 416 and 417: Chapter 12: Stored Procedures Now,
- Page 418 and 419: Chapter 12: Stored Procedures SQL S
- Page 420 and 421: Chapter 12: Stored Procedures 382 c
- Page 422 and 423: Chapter 12: Stored Procedures It wo
- Page 424 and 425: Chapter 12: Stored Procedures 386 r
- Page 426 and 427: Chapter 12: Stored Procedures 388 -
- Page 428 and 429: Chapter 12: Stored Procedures Note
- Page 430 and 431: Chapter 12: Stored Procedures 392 n
- Page 432 and 433: Chapter 12: Stored Procedures All t
- Page 434 and 435: Chapter 12: Stored Procedures Sproc
- Page 436 and 437: Chapter 12: Stored Procedures When
- Page 438 and 439: Chapter 12: Stored Procedures 400 @
- Page 440 and 441: Chapter 12: Stored Procedures I’d
- Page 442 and 443: Chapter 12: Stored Procedures match
- Page 444 and 445: Chapter 12: Stored Procedures There
- Page 446 and 447: Chapter 12: Stored Procedures 408 f
- Page 449 and 450: 13 User-Defined Functions Well, her
- Page 451 and 452: types!), except for BLOBs, cursors,
- Page 453 and 454: We get back the same set as with th
- Page 455 and 456: AS RETURN (SELECT BusinessEntityID,
- Page 457 and 458: in your relational database. These
- Page 459 and 460: AS BEGIN ( EmployeeID int NOT NULL,
- Page 461: So, as you can see, we can actually
- Page 465 and 466: 14 Transactions and Locks This is o
- Page 467 and 468: we are unable or do not want to com
- Page 469 and 470: Figure 14-1 Data needed Data in cac
- Page 471 and 472: Transaction 4 This transaction wasn
- Page 473 and 474: Oops — problem!!! Transaction 2 h
- Page 475 and 476: The only cure for this is setting y
- Page 477 and 478: Exclusive Locks Exclusive locks are
- Page 479 and 480: Also: ❑ The Sch-S is compatible w
- Page 481 and 482: The syntax for switching between th
- Page 483 and 484: As with most things in life, howeve
- Page 485 and 486: purchased. Process 2 records sales;
- Page 487: Chapter 14: Transactions and Locks
- Page 490 and 491: Chapter 15: Triggers the world’s
- Page 492 and 493: Chapter 15: Triggers WITH ENCRYPTIO
- Page 494 and 495: Chapter 15: Triggers FOR|AFTER The
- Page 496 and 497: Chapter 15: Triggers 458 To illustr
- Page 498 and 499: Chapter 15: Triggers 460 IF EXISTS
- Page 500 and 501: Chapter 15: Triggers ❑ Feeding de
- Page 502 and 503: Chapter 15: Triggers Trigger Firing
- Page 504 and 505: Chapter 15: Triggers Like regular t
- Page 506 and 507: Chapter 15: Triggers The COLUMNS_UP
- Page 508 and 509: Chapter 15: Triggers This is the sa
- Page 510 and 511: Chapter 15: Triggers 472 we have th
Despite being schema-bound, this one still comes back as being non-deterministic. That’s because this<br />
function references a table that isn’t local to the function (a temporary table or table variable created<br />
inside the function).<br />
Under the heading of “one more thing,” it’s also worth noting that the PriceDifference function we<br />
created at the same time as AveragePrice is also non-deterministic. For one thing, we didn’t make it<br />
schema-bound, but, more important, it references AveragePrice — if you reference a non-deterministic<br />
function, then the function you’re creating is non-deterministic by association.<br />
Debugging User-Defined Functions<br />
This actually works just the same as the sproc example we saw in Chapter 12.<br />
Simply set up a script that calls your function, and begin stepping through the script (using the toolbar<br />
icon, or pressing F11). You can then step right into your UDF.<br />
.NET in a Database W orld<br />
Chapter 13: User-Defined Functions<br />
As we discussed in Chapter 12, the ability to use .NET assemblies in our stored procedures and functions<br />
was added to <strong>SQL</strong> <strong>Server</strong> back in <strong>SQL</strong> <strong>Server</strong> 2005. Much as it does with sprocs, this has enormous<br />
implications for functions.<br />
Considering most who read this title will be beginners, it’s hard to fully relate the impact that .NET has<br />
in our database world. The reality is that you won’t use it all that often, and yet, when you do, the effects<br />
can be profound. Need to implement a complex formula for a special function? No problem. Need to<br />
access external data sources such as credit card authorization companies and such things? No problem.<br />
Need to access other complex data sources? No problem. In short, things we used to have to either skip<br />
or perform extremely complex development to achieve (in some cases, it was all smoke and mirrors<br />
before) suddenly become relatively straightforward.<br />
What does this mean in terms of functions? Well, I already gave the example of implementing a complex<br />
formula in a function. But now imagine something like external tabular data — let’s say representing a<br />
.csv or some other data in a tabular fashion — very doable with a .NET assembly created as a function<br />
in <strong>SQL</strong> <strong>Server</strong>.<br />
.NET assemblies in <strong>SQL</strong> <strong>Server</strong> remain, however, something of an advanced concept, and one I’ll defer<br />
to the Professional series title for <strong>SQL</strong> <strong>Server</strong> <strong>2008</strong>. That said, it’s important to understand that the option<br />
is available and consider it as something worth researching in that “Wow, I have no idea how we’re<br />
going to do this!” situation.<br />
425