1

I have created small table value function using T-SQL which takes one input parameter phone number as and returns area code from it. Function compiles successfully but when I run it I am getting error:

Msg 4121, Level 16, State 1, Line 1776
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.getareacode1", or the name is ambiguous

Refer to my code:

create or alter function dbo.getareacode1 (@phoneno as nvarchar(20))
returns table
with schemabinding
as
    return
       (select top 1 
            @phoneno as PhoneNumber, value as AreaCode 
        from 
            string_split(@phoneno,'-')
       );


select dbo.getareacode1( N'323-234-2111');

2 Answers 2

2

First off, the order of the rows returned from STRING_SPLIT is not guaranteed, so this function broken to begin with.

But the error is caused by trying to invoke a Table-Valued Function where a scalar is expected.

A TVF cannot be treated like a scalar function. So

create or alter function dbo.getareacode1 (@phoneno as nvarchar(20))
returns table
with schemabinding
as
return
(
select top 1 @phoneno as PhoneNumber, value as AreaCode 
from string_split(@phoneno,'-')
);
go
select * from dbo.getareacode1( N'323-234-2111');

And if you want to call it from another query use CROSS APPLY, eg

with phoneNumbers as
(
    select N'323-234-2111' phoneno
    from sys.objects 
)
select ac.*
from phoneNumbers p
cross apply dbo.getareacode1(p.phoneno) ac;
Sign up to request clarification or add additional context in comments.

Comments

1

On the flip-side of what David said: for your function to work like you were expecting you will need a scalar user-defined function (udf). This function:

-- Create function
create or alter function dbo.getareacode1 (@phoneno as nvarchar(20))
returns nvarchar(20) with schemabinding as
begin
  return
  (
    select top (1) AreaCode = ss.[value]
    from string_split(@phoneno,'-') ss
  );
  end
GO

... will allow this query to work:

select dbo.getareacode1( N'323-234-2111');

All that said, I strongly advise against using scalar udfs. I'll include a a couple good links that explain why at the bottom of this post. Leaving your function as-is and using APPLY, as David demonstrated, is the way to go. Also, string_split is not required here. If phone numbers are always coming in this format: NNN-NNN-NNNN, you could just use SUBSTRING:

SUBSTRING(N'323-234-2111', 1, 3). 

For countries with varible-length area codes in the format (area code(2 or more digits))-NNN-NNNN you could do this:

declare @phoneno nvarchar(30) = N'39-234-2111'; -- Using a variable for brevity
select substring(@phoneno,1, charindex('-',@phoneno)-1);

If you, for whatever reason, really need a function, then this is how I'd write it:

-- using the variable-length requirement as an example
create or alter function dbo.getareacode1_itvf(@phoneno as nvarchar(20))
returns table with schemabinding as
return (select areacode = substring(@phoneno,1, charindex('-',@phoneno)-1));
go

Great articles about Scalar UDFs and why iTVFs are better:

How to Make Scalar UDFs Run Faster -- Jeff Moden

Scalar functions, inlining, and performance -- Adam Machanic

TSQL Scalar functions are evil – Andy Irving -- Stackoerflow post

1 Comment

Thanks.It helped a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.