<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www2.sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx</link><description>So you thought that encapsulating code in user-defined functions for easy reuse is a good idea? Think again! SQL Server supports three types of user-defined functions. Only one of them qualifies as good. The other two – well, the title says it all, doesn’t</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43468</link><pubDate>Sun, 20 May 2012 20:21:18 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43468</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;I guess I should add (thank you for pointing it out, Adam) that all of the above applies to user-defined function that are created in T-SQL. You can also create user-defined functions with .Net languages (CLR). I have not done much research into them yet, I do know that they usually perform better than their T-SQL counterparts.&lt;/p&gt;
&lt;p&gt;I may do some investigation into CLR user-defined functions in the future, and if I do I'll write my findings in a blog post.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43474</link><pubDate>Mon, 21 May 2012 12:19:45 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43474</guid><dc:creator>Randall</dc:creator><description>&lt;p&gt;Why hasn't Microsoft done anything to fix the problems with scalar T-SQL UDFs? They've had the opportunity in SQL Server 2008 and 2012. Why don't they care about SQL Server performance?&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43475</link><pubDate>Mon, 21 May 2012 12:51:40 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43475</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;@Randall: I would not go as far as to say that Microsoft &amp;quot;don't care about SQL Server performance&amp;quot;. There have been many changes to help performance, just not in the area of scalar T-SQL UDFs.&lt;/p&gt;
&lt;p&gt;I can't tell you why MS has chosen not to invest in the area of scalar T-SQL UDF performance. Only they can tell you. I can give you my best guess: they had more things they wanted to do than they had developer hours available, so they had to prioritize, and other issues were considered more important.&lt;/p&gt;
&lt;p&gt;Personally, I'd *love* to see some work done here. Just adding a special syntax for an inline scalar UDF (similar to the inline table-valued UDF) would be a great addition. There is a very popular connect item for this (281 up votes; 2 down votes) at &lt;a rel="nofollow" target="_new" href="https://connect.microsoft.com/SQLServer/feedback/details/273443/the-scalar-expression-function-would-speed-performance-while-keeping-the-benefits-of-functions"&gt;https://connect.microsoft.com/SQLServer/feedback/details/273443/the-scalar-expression-function-would-speed-performance-while-keeping-the-benefits-of-functions&lt;/a&gt; - if you haven't voted yet, do so now!&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43476</link><pubDate>Mon, 21 May 2012 18:31:49 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43476</guid><dc:creator>Geoff</dc:creator><description>&lt;p&gt;&amp;quot;Why hasn't Microsoft done anything to fix the problems with scalar T-SQL UDFs? They've had the opportunity in SQL Server 2008 and 2012. Why don't they care about SQL Server performance?&amp;quot;&lt;/p&gt;
&lt;p&gt;Agreed.&lt;/p&gt;
&lt;p&gt;There is no reason that this still has to be a problem. At the very least, SQL Server could inline the code when it is compiled or give you the option to have that happen.&lt;/p&gt;
&lt;p&gt;I can't fathom why this hasn't been fixed. We've recently in-lined a bunch of functions to improve performance in a number of our procedures, and it would be much nicer to have the logic contained in one place.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43482</link><pubDate>Mon, 21 May 2012 21:45:28 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43482</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;@Geoff: &amp;quot;We've recently in-lined a bunch of functions to improve performance in a number of our procedures, and it would be much nicer to have the logic contained in one place.&amp;quot;&lt;/p&gt;
&lt;p&gt;There is a way to do that. I plan to cover it in a future blog post, but if you're impatient you can also read about it here:&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_new" href="http://sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx"&gt;http://sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43489</link><pubDate>Tue, 22 May 2012 11:29:17 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43489</guid><dc:creator>GrumpyOldDBA</dc:creator><description>&lt;p&gt;We've really known the issues with T-SQL UDFs since SQL 2000. It's a key point of much performance tuning to just remove UDFs. Typically queries which ran for hours now run in secs and with reduced io usually.&lt;/p&gt;
&lt;p&gt;I did try a bunch of ( simple ) CLR functions to replace T-SQL functions but couldn't reproduce in test the issues I had in production so the results were inconclusive, some time I will have to revisit.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43495</link><pubDate>Tue, 22 May 2012 14:34:03 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43495</guid><dc:creator>Geoff</dc:creator><description>&lt;p&gt;Hugo, thanks.&lt;/p&gt;
&lt;p&gt;We can't use an inline TVF because we are still stuck on 2000 compatibility mode. We've made the changes to get us off of compatibility mode, but they have to be tested.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43554</link><pubDate>Fri, 25 May 2012 16:00:19 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43554</guid><dc:creator>Ted</dc:creator><description>&lt;p&gt;SQL Server 2012 should make this easier with a DETERMINISTIC keyword for the function like Oracle has had for years.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43556</link><pubDate>Fri, 25 May 2012 18:13:40 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43556</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;Ted, SQL Server uses WITH SCHEMABINDING to mark user-defined functions as deterministic, so no need for a DETERMINISTIC keyword.&lt;/p&gt;
&lt;p&gt;The difference between SQL Server, apart from the term used, is that SQL Server can't force determinism on a function that is actually not deterministic. If what I just found on internet is correct, Oracle doesn't check; if you declare a non-deterministic function to be deterministic, you'll simply get unexpected results.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43557</link><pubDate>Fri, 25 May 2012 18:21:52 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43557</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;NOTE:&lt;/p&gt;
&lt;p&gt;I just found that I made a mistake with the rowcount in the table used for the demo. I corrected this by editing the text in blog post - everywhere where I first had 10,000 has been changed to 100,000; and all occurences of a million have been changed to read ten million. The actual code has not been changed; the text now accurately describes the actual number mof rows in the table,&lt;br&gt;&lt;/p&gt;
&lt;p&gt;My apologies for this stupid mistake.&lt;/p&gt;</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43587</link><pubDate>Sat, 26 May 2012 14:23:03 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43587</guid><dc:creator>TheSQLGuru</dc:creator><description>&lt;p&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/p&gt;
&lt;p&gt;There is no reason that this still has to be a problem. At the very least, SQL Server could inline the code when it is compiled or give you the option to have that happen.&lt;/p&gt;
&lt;p&gt;I can't fathom why this hasn't been fixed. We've recently in-lined a bunch of functions to improve performance in a number of our procedures, and it would be much nicer to have the logic contained in one place.&lt;/p&gt;
&lt;p&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/p&gt;
&lt;p&gt;VERY good reason:javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&amp;quot;ctl00$_$ctl00$_$ctl00$ctl00$bcr$ctl00$_$form$_$btnSubmit&amp;quot;, &amp;quot;&amp;quot;, true, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, false, true)) &amp;nbsp;It is really, REALLY f'in HARD to get the engine to know about, understand, and integrate the virtually infinite array of code that could go into any UDF into the optimizer and engine of SQL Server. &amp;nbsp;Since there are known workarounds (often several) and SOOOOO many other things that need to be fixed/improved in the engine, integrating UDFs has and never will make the cut IMNSOH. &amp;nbsp;ESPECIALLY with Steve Balmer's &amp;quot;the cloud - we're ALL IN&amp;quot; mantra redirecting hundreds of thousands of developer hours to windows/sql azure. &amp;nbsp;:(&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43588</link><pubDate>Sat, 26 May 2012 14:45:02 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43588</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;Kevin, I totally agree with your remark if you mean that it would cost too many developer hours to have the optimizer automatically inline all scalar user-defined functions. However, if you think about extending the syntax to allow a special kind of inline functions that allows only a single expression (similar to how inline table-valued funcions allow only a single query) and inlining them automatically, that would cost far less developer hours, place the burden of rewriting functions to a single expression on us, but give us the possiblity to encapsulate logic without takinng a performance hit.&lt;/p&gt;
</description></item><item><title>T-SQL User-Defined Functions: the good, the bad, and the ugly (part 2)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43591</link><pubDate>Sat, 26 May 2012 15:00:44 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43591</guid><dc:creator>SELECT Hints, Tips, Tricks FROM Hugo Kornelis WHERE RDBMS = 'SQL Server'</dc:creator><description>&lt;p&gt;In a previous blog post , I demonstrated just how much you can hurt your performance by encapsulating&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43592</link><pubDate>Sat, 26 May 2012 16:07:29 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43592</guid><dc:creator>TheSQLGuru</dc:creator><description>&lt;p&gt;Still disagree. &amp;nbsp;I can write a thousand-line-long SELECT that returns a single scalar value. &amp;nbsp;Absolutely no way that can be effectively integrated. &amp;nbsp;You are also ignoring the optimization shortcoming entirely - as in how would an estimate of number of rows or value distribution possibly be extracted from arbitrary code, especially when such output is dependent on the per-row input from the outer calling query?&lt;/p&gt;
&lt;p&gt;Perhaps you are speaking of a non-data-hitting scalar, something like RETURN int AS (@input + 3)? &amp;nbsp;Again I can make an arbitrarily complex statement that could take extraordinary efforts to get accurate statistics sucked out of it. &amp;nbsp;&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43593</link><pubDate>Sat, 26 May 2012 18:24:37 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43593</guid><dc:creator>RBarryYoung</dc:creator><description>&lt;p&gt;The strange thing is that Microsoft has had an object-type for inline scalar functions since SQL Server 2005, and they even document how they work in a query in every version of the doc since then. &amp;nbsp;They just never included the syntax to implement one. &amp;nbsp;Weird.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43594</link><pubDate>Sat, 26 May 2012 18:46:29 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43594</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;Kevin, I'm not sure what data access has to do with anything. The query optimizer generally has no problem inlining even large/complex correlated scalar subqueries or table expressions. I write large table expressions -- even scalar-valued -- all the time that the QO has absolutely no issue producing accurate statistics for.&lt;/p&gt;
&lt;p&gt;And in cases where expressions can't be inlined, they're still much faster when evaluated via a nested subtree rather than in a separate context, as occurs with scalar UDFs.&lt;/p&gt;
&lt;p&gt;... you can read my prior blog post on the topic, linked above in Hugo's response to Geoff, for more information.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43595</link><pubDate>Sat, 26 May 2012 20:31:21 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43595</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;@RBarry: Interesting, I didn't know that. Can you create such objects through the object model, or can you only read them?&lt;/p&gt;
&lt;p&gt;Kevin: It's not about the number of lines, or the number of values returned - it's about what goes between the BEGIN and END of the function definition. For the inline scalar function I would like to see added to the product, that would only be one statement: RETURN, followed by an expression that evaluates to a single scalar value. And that expression can be data-hitting (by including subqueries), or not.&lt;/p&gt;
&lt;p&gt;Yes, you can make it complicated, and that may be hard to optimize. How does that differ from manually copying and pasting that same complicated expression in the query? I don't expect a query that uses an inline scalar function to perform better than one where I inline the expression myself, but it would be great if they would perform the same. That would be a huge step forward. And it is possible, since all it takes is for the parser to replace the reference to the function with its definition, as a sort of macro expansion. Exactly how currently views and inline table-valued function are already treated.&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43596</link><pubDate>Sat, 26 May 2012 22:40:57 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43596</guid><dc:creator>Frantz</dc:creator><description>&lt;p&gt;Nice article.&lt;/p&gt;
&lt;p&gt;A fast way to optimize code that makes use of a scalar function in a situation where the logic is too complex to be re-written is to create a table with all the values and join it. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;It is not elegant and I don't know if it performs well under most situations but it helped us cut the execution time tremendously many times. &amp;nbsp;Something like:&lt;/p&gt;
&lt;p&gt;SELECT&lt;/p&gt;
&lt;p&gt;	D.DataVal,&lt;/p&gt;
&lt;p&gt;	T.MaxTriple&lt;/p&gt;
&lt;p&gt;FROM (&lt;/p&gt;
&lt;p&gt;	SELECT&lt;/p&gt;
&lt;p&gt;		DataVal,&lt;/p&gt;
&lt;p&gt;		'MaxTriple' = dbo.Triple(DataVal)&lt;/p&gt;
&lt;p&gt;	FROM 	(&lt;/p&gt;
&lt;p&gt;		SELECT DISTINCT DataVal&lt;/p&gt;
&lt;p&gt;		FROM&lt;/p&gt;
&lt;p&gt;			dbo.LargeTable) T) T&lt;/p&gt;
&lt;p&gt;INNER JOIN&lt;/p&gt;
&lt;p&gt;	dbo.LargeTable D&lt;/p&gt;
&lt;p&gt;	ON D.DataVal = T.DataVal&lt;/p&gt;
&lt;p&gt;Frantz&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43607</link><pubDate>Sun, 27 May 2012 20:00:50 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43607</guid><dc:creator>TheSQLGuru</dc:creator><description>&lt;p&gt;Here are 2 exceptionally simple UDFs, one scalar and one TVF. &amp;nbsp;Both result in horrible estimates and suboptimal executions, including memory grants 2 and 3 times larger. &amp;nbsp;I am sure I am missing something Adam, but am not sure what it is.&lt;/p&gt;
&lt;p&gt;USE AdventureWorks2008R2&lt;/p&gt;
&lt;p&gt;SET NOCOUNT ON&lt;/p&gt;
&lt;p&gt;GO&lt;/p&gt;
&lt;p&gt;--useful index&lt;/p&gt;
&lt;p&gt;CREATE NONCLUSTERED INDEX [idx_fullname] ON [Person].[Person] &lt;/p&gt;
&lt;p&gt;(&lt;/p&gt;
&lt;p&gt;	[LastName] ASC,&lt;/p&gt;
&lt;p&gt;	[FirstName] ASC&lt;/p&gt;
&lt;p&gt;)WITH (PAD_INDEX &amp;nbsp;= OFF, STATISTICS_NORECOMPUTE &amp;nbsp;= OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, &lt;/p&gt;
&lt;p&gt;DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS &amp;nbsp;= ON, ALLOW_PAGE_LOCKS &amp;nbsp;= ON) ON [PRIMARY]&lt;/p&gt;
&lt;p&gt;GO&lt;/p&gt;
&lt;p&gt;CREATE FUNCTION dbo.fn_FullName (@FirstName nvarchar(50), @MiddleName nvarchar(50), @LastName nvarchar(50))&lt;/p&gt;
&lt;p&gt;RETURNS nvarchar(153) WITH SCHEMABINDING&lt;/p&gt;
&lt;p&gt;AS&lt;/p&gt;
&lt;p&gt;BEGIN&lt;/p&gt;
&lt;p&gt; &amp;nbsp; RETURN @LastName + N', ' + @FirstName + N' ' + ISNULL(@MiddleName, N'')&lt;/p&gt;
&lt;p&gt;END&lt;/p&gt;
&lt;p&gt;GO&lt;/p&gt;
&lt;p&gt;--show actual execution plan and not estimated/actual differences and the query shape/operations&lt;/p&gt;
&lt;p&gt;SELECT dbo.fn_FullName(p.FirstName, p.MiddleName, p.LastName) as FullName,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; od.ProductID,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; SUM((UnitPrice - UnitPriceDiscount) * OrderQty) AS TotalPrice&lt;/p&gt;
&lt;p&gt; &amp;nbsp;FROM Sales.SalesOrderHeader oh&lt;/p&gt;
&lt;p&gt; INNER JOIN Sales.SalesOrderDetail od ON od.SalesOrderID = oh.SalesOrderID&lt;/p&gt;
&lt;p&gt; INNER JOIN Sales.SalesPerson sp ON sp.BusinessEntityID = oh.SalesPersonID&lt;/p&gt;
&lt;p&gt; INNER JOIN Person.Person p ON p.BusinessEntityID = sp.BusinessEntityID&lt;/p&gt;
&lt;p&gt; WHERE dbo.fn_FullName(p.FirstName, p.MiddleName, p.LastName) = N'Abbas, Syed E'&lt;/p&gt;
&lt;p&gt; GROUP BY p.LastName, p.FirstName, p.MiddleName, od.ProductID&lt;/p&gt;
&lt;p&gt;.13 duration, .15 cpu, 1231 reads, 2192 memory grant&lt;/p&gt;
&lt;p&gt;significant disparity between estimated and actual rowcounts&lt;/p&gt;
&lt;p&gt;SELECT p.LastName + N', ' + p.FirstName + N' ' + ISNULL(p.MiddleName, '') as FullName,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; od.ProductID,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; SUM((UnitPrice - UnitPriceDiscount) * OrderQty) AS TotalPrice&lt;/p&gt;
&lt;p&gt; &amp;nbsp;FROM Sales.SalesOrderHeader oh&lt;/p&gt;
&lt;p&gt; INNER JOIN Sales.SalesOrderDetail od ON od.SalesOrderID = oh.SalesOrderID&lt;/p&gt;
&lt;p&gt; INNER JOIN Sales.SalesPerson sp ON sp.BusinessEntityID = oh.SalesPersonID&lt;/p&gt;
&lt;p&gt; INNER JOIN Person.Person p ON p.BusinessEntityID = sp.BusinessEntityID&lt;/p&gt;
&lt;p&gt; WHERE p.LastName = N'Abbas'&lt;/p&gt;
&lt;p&gt; &amp;nbsp; AND p.FirstName = N'Syed'&lt;/p&gt;
&lt;p&gt; &amp;nbsp; AND p.MiddleName = N'E'&lt;/p&gt;
&lt;p&gt; GROUP BY p.LastName, p.FirstName, p.MiddleName, od.ProductID&lt;/p&gt;
&lt;p&gt;0 duration, 0 cpu, 63 reads, 1024 (default sized?) memory grant&lt;/p&gt;
&lt;p&gt;CREATE FUNCTION dbo.tvf_FullName (@FirstName nvarchar(50), @MiddleName nvarchar(50), @LastName nvarchar(50))&lt;/p&gt;
&lt;p&gt;RETURNS TABLE WITH SCHEMABINDING&lt;/p&gt;
&lt;p&gt;AS&lt;/p&gt;
&lt;p&gt; &amp;nbsp; RETURN (SELECT @LastName + N', ' + @FirstName + N' ' + ISNULL(@MiddleName, N'') AS FullName)&lt;/p&gt;
&lt;p&gt;GO&lt;/p&gt;
&lt;p&gt;SELECT tvp.FullName,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; od.ProductID,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; SUM((UnitPrice - UnitPriceDiscount) * OrderQty) AS TotalPrice&lt;/p&gt;
&lt;p&gt; &amp;nbsp;FROM Sales.SalesOrderHeader oh&lt;/p&gt;
&lt;p&gt; INNER JOIN Sales.SalesOrderDetail od ON od.SalesOrderID = oh.SalesOrderID&lt;/p&gt;
&lt;p&gt; INNER JOIN Sales.SalesPerson sp ON sp.BusinessEntityID = oh.SalesPersonID&lt;/p&gt;
&lt;p&gt; INNER JOIN Person.Person p ON p.BusinessEntityID = sp.BusinessEntityID&lt;/p&gt;
&lt;p&gt; CROSS APPLY dbo.tvf_FullName (p.FirstName, p.MiddleName, p.LastName) tvp&lt;/p&gt;
&lt;p&gt; WHERE tvp.FullName = N'Abbas, Syed E'&lt;/p&gt;
&lt;p&gt; GROUP BY tvp.FullName, od.ProductID&lt;/p&gt;
&lt;p&gt;.13 duration, .15 cpu, 1231 reads, 3712 memory grant&lt;/p&gt;
&lt;p&gt;significant disparity between estimated and actual rowcounts&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#43610</link><pubDate>Mon, 28 May 2012 02:03:42 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43610</guid><dc:creator>Dave Maiden</dc:creator><description>&lt;p&gt;I personally think this started when Microsoft decided to create the .NET Framework and go OOP, I appreciate SQL as a language but have since moved onto VB.NET/C#, but still actively use SQL. When you compile your code within the Framework the COMPILER is designed to calibrate your code (and it varies between each language on the the result).&lt;/p&gt;
&lt;p&gt;I assume (incorrectly) that the in-built SQL functions are written within the Framework, which would make more sense to me as a change in one function would not have a devastating affect. First problem LEGACY if there is a problem then they either change it or leave it, the latter being the problem for compatibility. I do however understand that legacy systems are in use and use some of the depreciated commands.&lt;/p&gt;
&lt;p&gt;You should test CLRs, I use them all the time and in these days of Asynchronous results surely we should have a essential bible (framework) which everything relies on and is standardised throughout. For example DATEDIFF(&amp;quot;D&amp;quot;) is different to Microsoft.VisualBasic.DateDiff(DateInterval.Day) as it uses Timespan.&lt;/p&gt;
&lt;p&gt;Dave&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#44762</link><pubDate>Fri, 17 Aug 2012 11:07:32 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:44762</guid><dc:creator>Mr Tea</dc:creator><description>&lt;p&gt;If I use timestamps e.g. SYSUTCDATETIME() instead of statistics time then I see a different picture. Its still bad in comparison but using STATISTICS TIME has a direct and fundamental effect on the observation.&lt;/p&gt;
&lt;p&gt;My Figures are:&lt;/p&gt;
&lt;p&gt;Using SYSUTCDATETIME with LargeTable&lt;/p&gt;
&lt;p&gt;multiplication: ~24 ms&lt;/p&gt;
&lt;p&gt;dbo.triple: ~250ms ms&lt;/p&gt;
&lt;p&gt;Using STATISTICS TIME with LargeTable&lt;/p&gt;
&lt;p&gt;multiplication: ~24 ms&lt;/p&gt;
&lt;p&gt;dbo.triple: ~450ms ms&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#46671</link><pubDate>Mon, 17 Dec 2012 05:59:05 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:46671</guid><dc:creator>Madhukar Sreeramoju</dc:creator><description>&lt;p&gt;How to know the DB - Memory Consumption in Sql Server using the query.&lt;/p&gt;
&lt;p&gt;madhukars@live.com&lt;/p&gt;
</description></item><item><title>re: T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx#47056</link><pubDate>Mon, 07 Jan 2013 17:49:20 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:47056</guid><dc:creator>Michael</dc:creator><description>&lt;p&gt;let A,B,x in R such that x&amp;gt;0 if A&amp;gt;B then xA&amp;gt;xB....so you should select 3*max(DataVal) instead of select max(3*DataVal)&lt;/p&gt;
</description></item></channel></rss>