473,385 Members | 2,015 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Problem with nested function call (UDFs)

Hello Folks,

I encountered a problem with SQL server 2000 and UDFs.

I have a scalar UDF and a table UDF where I would like the scalar UDF
to provide the argument for the table UDF like in:

SELECT
*
FROM
transaction_t
WHERE
trxn_gu_id in (
select get_trxns_for_quarter(get_current_quarter( GetDate() ) )
)

'get_current_quarter' returns an integer which is a GUID in a table
containing business quarter definitions, like start date, end date.
'get_current_quarter' is a scalar UDF.
'get_trxns_for_quarter' will then get all transctions that fall into
that quarter and return their GUID's in a table.
'get_trxns_for_quarter' is a table UDF.

This doesn't seem to work at all. Regardless whether I provide the
namespace (schema) calling the scalar UDF or not. Error message is
just different.

Both functions operate correctly invoked un-nested.

The whole expression does work fine if I turn 'get_trxns_for_quarter'
into a scalar UDF as well, e.g. by returning just one trxn_gu_id with
e.g. MAX() in a scalar datatype. But of course that's no good to me.

It also works fine if I select the result of 'get_current_quarter'
into a variable and pass that variable into 'get_trxns_for_quarter'.
But that's no good to me either since then I cannot use the whole
thing embedded into other SELECT clauses.

Both UDF's are non-deterministic but I couldnt see how that would have
an impact anyway.

Never mind the syntax on that example or anyhting, I tried all the
obvious and not so obvious stuff and it really seems to come down to
the fact that one UDF is scalar and the other one is not. However, I
did not come across any type of information saying that this cannot be
done.

Have you any ideas?

Any help would be greatly appreciated.

Carsten

Jul 20 '07 #1
6 4829
You are right, you can't do that.

BOL doesn't explicitely say that it is impossible (at least I didn't
find it), it only mentions that no columns from any outer query can be
used as parameter. I think it is not possible because scalar UDFs are
executed for each (relevant) row, which means that by definition they
cannot be used as a parameter to a table valued UDF since it needs a
scalar per parameter.

The obvious solution would be to create a new table valued UDF that
implements both the current table valued and current scalar UDF (and
takes the parameter of the scalar UDF).

If you do not want duplication of code, then you could consider building
a table "current_quarters" and fill it with values returned by the
scalar UDF, and join to that table whenever you need to determine the
current_quarter.

Having said all that, from a performance point of view, if you want only
one value for a query, then you want to calculate it before hand. You
don't want to put a scalar UDF in the query if this UDF will return the
same value over and over again. Assigning a value to a local variable,
or implementing the logic in a table valued UDF will do just that.

HTH,
Gert-Jan
Carsten wrote:
>
Hello Folks,

I encountered a problem with SQL server 2000 and UDFs.

I have a scalar UDF and a table UDF where I would like the scalar UDF
to provide the argument for the table UDF like in:

SELECT
*
FROM
transaction_t
WHERE
trxn_gu_id in (
select get_trxns_for_quarter(get_current_quarter( GetDate() ) )
)

'get_current_quarter' returns an integer which is a GUID in a table
containing business quarter definitions, like start date, end date.
'get_current_quarter' is a scalar UDF.
'get_trxns_for_quarter' will then get all transctions that fall into
that quarter and return their GUID's in a table.
'get_trxns_for_quarter' is a table UDF.

This doesn't seem to work at all. Regardless whether I provide the
namespace (schema) calling the scalar UDF or not. Error message is
just different.

Both functions operate correctly invoked un-nested.

The whole expression does work fine if I turn 'get_trxns_for_quarter'
into a scalar UDF as well, e.g. by returning just one trxn_gu_id with
e.g. MAX() in a scalar datatype. But of course that's no good to me.

It also works fine if I select the result of 'get_current_quarter'
into a variable and pass that variable into 'get_trxns_for_quarter'.
But that's no good to me either since then I cannot use the whole
thing embedded into other SELECT clauses.

Both UDF's are non-deterministic but I couldnt see how that would have
an impact anyway.

Never mind the syntax on that example or anyhting, I tried all the
obvious and not so obvious stuff and it really seems to come down to
the fact that one UDF is scalar and the other one is not. However, I
did not come across any type of information saying that this cannot be
done.

Have you any ideas?

Any help would be greatly appreciated.

Carsten
Jul 20 '07 #2
On Fri, 20 Jul 2007 09:39:44 -0700, Carsten wrote:
>Hello Folks,

I encountered a problem with SQL server 2000 and UDFs.

I have a scalar UDF and a table UDF where I would like the scalar UDF
to provide the argument for the table UDF like in:

SELECT
*
FROM
transaction_t
WHERE
trxn_gu_id in (
select get_trxns_for_quarter(get_current_quarter( GetDate() ) )
)

'get_current_quarter' returns an integer which is a GUID in a table
containing business quarter definitions, like start date, end date.
'get_current_quarter' is a scalar UDF.
'get_trxns_for_quarter' will then get all transctions that fall into
that quarter and return their GUID's in a table.
'get_trxns_for_quarter' is a table UDF.
Hi Carsten,

You need to select from a table-valued function. And you need to
schema-qualify UDF's.

SELECT Column1, Column2, ... -- Don't use SELECT * !!
FROM transaction_t
WHERE trxn_gu_id IN
(SELECT Column_name
FROM dbo.get_trxns_for_quarter
(dbo.get_current_quarter(CURRENT_TIMESTAMP)));

--
Hugo Kornelis, SQL Server MVP
My SQL Server blog: http://sqlblog.com/blogs/hugo_kornelis
Jul 20 '07 #3
Carsten (ca*************@gmail.com) writes:
'get_current_quarter' returns an integer which is a GUID in a table
containing business quarter definitions, like start date, end date.
'get_current_quarter' is a scalar UDF.
Be very careful with doing data access from scalar UDFs. It can have
adverse effect on performance.

I think Gert-Jan said this in his post, but I just wanted to
emphasize it more strongly.

--
Erland Sommarskog, SQL Server MVP, es****@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pro...ads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinf...ons/books.mspx
Jul 20 '07 #4
Sorry about the confusion. I first tested on SQL Server 2000 and later
(when Hugo gave a reply) I retested on 2005.

In SQL Server 2005, this all works just fine. All you need to do is
access the scalar UDF with its 2-part name.

However, in SQL Server 2000 (the OP's platform), it doesn't work.
Calling it with the 2-part name gives the error "Incorrect syntax near
'.'", calling it with the 1-part name gives the error "Incorrect syntax
near '('.". Schemabinding doesn't make a difference.

Gert-Jan
Jul 21 '07 #5
On Sun, 22 Jul 2007 00:42:01 +0200, Gert-Jan Strik wrote:
>Sorry about the confusion. I first tested on SQL Server 2000 and later
(when Hugo gave a reply) I retested on 2005.

In SQL Server 2005, this all works just fine. All you need to do is
access the scalar UDF with its 2-part name.

However, in SQL Server 2000 (the OP's platform), it doesn't work.
Calling it with the 2-part name gives the error "Incorrect syntax near
'.'", calling it with the 1-part name gives the error "Incorrect syntax
near '('.". Schemabinding doesn't make a difference.
Hi Gert-Jan,

I missed both the requirement of the OP that it run under SQL2000 and
the odd behaviour on that platform.

I can confirm the same behaviour here. And I can't find any explanation
in Books Online. I guess it's a bug - but not one I expect to ever see
fixed.

The workaround is of course simple:

DECLARE @d datetime
SET @d = dbo.get_current_quarter(GetDate())
SELECT id, dt
FROM (SELECT 1, CAST('20070701' AS datetime)
UNION ALL
SELECT 2, CAST('20070815' AS datetime)) AS t(id, dt)
WHERE dt IN (SELECT TheDate
FROM dbo.get_trxns_for_quarter(@d));
--
Hugo Kornelis, SQL Server MVP
My SQL Server blog: http://sqlblog.com/blogs/hugo_kornelis
Jul 22 '07 #6
Carsten wrote: [snip]
I was hoping
that once I found a suitbale way of replacing such stuff I could
consolidate the codebase entirely.
Software maintenance can be very expensive. You could consider upgrading
to SQL Server 2005...
This has been very helpful nonetheless and I'm sure I'll find a way
around this. Thank you.
You're welcome.

Gert-Jan
Jul 23 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Chris Michael | last post by:
Hello everybody, Newbie here. I've been working on this for the last two days and I can't figure out where this problem is. I think it's something so obvious, but I can't see it! OK, firstly...
4
by: mangi03 | last post by:
Hi, I came acrosss g++ compile errors whenever I make a function call by reference and found out from the test program that compiler is treating the function argument differently when another...
1
by: Hohn Upshew | last post by:
I have a function for rating the clients depending on their quantity which works perfectly. My only problem is that my second function called GetSize is not recognized, and i need it in order to...
10
by: Robert Rodriguez | last post by:
does anyone know if the ms c compiler has nested function support, I have a large gcc project I need to merge into another ms c program. Thanks in advance.
6
by: Marc Pelletier | last post by:
Hello, Are nested function calls inefficient (or inherently evil)? In Delphi I've seen small but significant performance improvements by always declaring a local variable and 'unwrapping' the...
13
by: Bern McCarty | last post by:
I have run an experiment to try to learn some things about floating point performance in managed C++. I am using Visual Studio 2003. I was hoping to get a feel for whether or not it would make...
78
by: Josiah Manson | last post by:
I found that I was repeating the same couple of lines over and over in a function and decided to split those lines into a nested function after copying one too many minor changes all over. The only...
5
by: marcsirois | last post by:
I have an SQL Query that looks like this. I simplified it for the purpose of this example, but it's still a runnable query SELECT TOP 1 FundedPositions.PositionNumber AS , (select top 1...
4
by: Wolfgang Draxinger | last post by:
If you know languages like Python or D you know, that nested functions can be really handy. Though some compilers (looking at GCC) provide the extension of nested functions, I wonder, how one...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.