Reputation: 83
I'm reading Microsoft's 70-433 SQL Training Kit, and I've come up against an example where they define the following as a "scalar UDF":
CREATE FUNCTION dbo.fnGetCustomerAccountNumber(@CustomerID INT)
RETURNS VARCHAR(10)
AS
BEGIN
RETURN ISNULL(
(
SELECT
AccountNumber
FROM Sales.Customer
WHERE CustomerID = @CustomerID
), 'NOT FOUND');
END
GO
I understand that a scalar UDF (as oppposed to a table-valued one) is one that returns a single value, but it seems to me that the above function will only return a single value if there is only one row returned by the SELECT statement - which will depend on the contents of the table. But I'm happy to assume that there will be only one row returned (what would happen if there wasn't?). But...
They then give an alternative version, which instead of calling the above UDF, does the following:
SELECT
soh.SalesOrderID
, soh.OrderDate
, ISNULL(
(
SELECT
AccountNumber
FROM Sales.Customer
WHERE CustomerID = soh.CustomerID
), 'NOT FOUND')
FROM Sales.SalesOrderHeader AS soh;
They contrast this second example by saying "The use of inline table-valued UDFs does not incur the same performance penalty as the use of scalar UDFs because..."
So, this second example, even though the code is identical to the first, is a table-valued UDF rather than a scalar one? Is this an error in the text, or am I misunderstanding the distinction between a scalar UDF and a table-valued one?
Upvotes: 1
Views: 1629
Reputation: 70538
There is a difference. Look at the where clause in the first
WHERE CustomerID = @CustomerID
Is matching CustomerID
against a single integer value (which is a parameter.)
In the 2nd where clause
WHERE CustomerID = soh.CustomerID
Is matching against every value of CustomerID
in the Sales.SalesOrderHeader
table.
Upvotes: 1