<table-valued function> is not a recognized built-in function name - sql

I am getting this error:
Msg 195, Level 15, State 10, Line 1
'fnParseName' is not a recognized built-in function name.
On this query:
SELECT fnParseName(DOCTORFIRSTNAME+' ' +DOCTORLASTNAME)
FROM [PracticeandPhysician]
Here's the code for fnParseName
create FUNCTION [dbo].[fnParseName]
(#FullName NVARCHAR(128))
RETURNS #FullNameParts TABLE (FirstName NVARCHAR(128),
Middle NVARCHAR(128),
LastName NVARCHAR(128))
AS
BEGIN
... function body that populates #FullNameParts ...
RETURN
END
Why am I getting this error?

It's a table-valued function. So you probably meant:
SELECT p.DOCTORFISTNAME, p.DOCTORLASTNAME, t.FirstName, t.Middle, t.LastName
FROM dbo.[PracticeandPhysician] AS p
CROSS APPLY dbo.fnParseName(p.DOCTORFIRSTNAME + ' ' + p.DOCTORLASTNAME);
Note that you can't say:
SELECT dbo.TableValueFunction('foo');
Any more than you could say:
SELECT dbo.Table;
--or
SELECT dbo.View;
You can, however, say:
SELECT * FROM dbo.fnParseName('foo bar');
--or
SELECT FirstName, Middle, LastName FROM dbo.fnParseName('foo bar');
(Not that I have validated that your function does what you think, or does so efficiently.)
Please always use the dbo. prefix as others have suggested.

You always have to prefix SQL function calls with the schema name dbo. or the schema name for that function (dbo is the default schema).
SELECT dbo.fnParseName(--etc

UDFs/Functions need to be prefixed with the schema name (most likely "dbo"). Change the call to
SELECT
dbo.fnParseName(DOCTORFIRSTNAME + ' ' + DOCTORLASTNAME)
FROM
[PracticeandPhysician]

The problem you have is similar to what I encountered too. Scalar function and Table inline functions are quite different in terms of implementation. See below for the diiferent
Create function udfCountry
(
#CountryName varchar(50)
)
returns varchar(2)
as
BEGIN
Declare #CountryID varchar(2),
#Result varchar(2)
Select #CountryID = Country from
dbo.GeoIPCountryNames where CountryName = #CountryName
set #Result = isNull(#CountryID, 'NA')
if #Result = 'NA'
set #Result = 'SD'
return #Result
End
//Implementation
select dbo.[udfCountry]('Nigeria')
// sample result
NG
// Inline table function sample
Create FUNCTION ConditionEvaluation
(
#CountrySearch varchar(50)
)
returns #CountryTable table
(
Country varchar(2),
CountryName varchar(50)
)
as
Begin
Insert into #CountryTable(Country, CountryName)
Select Country, CountryName from GeoIPCountryNames
where Country like '%'+#CountrySearch+'%'
return
end
//Implementation sample
Declare #CountrySearch varchar(50)
set #CountrySearch='a'
select * from ConditionEvaluation(#CountrySearch)
the parttern of implementating scalar is quite different inline table. I hope this helps

If you want to assign the value returned by tfn in a variable of stored procedure, you can do it this way:
select #my_local_variable_in_procedure = column_name_returned_from_tfn from dbo.my_inline_tfn (#tfn_parameter)

Related

How to assign column name to return value of scalar function in sql serve

I have defined a function in sql function, that inputs 3 names (three varchars) and outputs one name (one varchar)'. What I only want to is to give this return value a name/column name.
Right now when I call my function:
select concat_names(#first_name, #middle_name,#last_name)
I see returned varchar with no column name.
Here is complete code:
if object_id('[co1].[concat_names]') is not null
drop function [co1].[concat_names];
go
create function [co1].[concat_names]
(
#first_name varchar(20),
#middle_name varchar(20),
#last_name varchar(20)
)
returns varchar(62)
as
begin
declare #full_name varchar(62)
set #full_name = #first_name;
if(#middle_name is not null)
set #full_name = #full_name + ' ' + #middle_name;
if(#last_name is not null)
set #full_name = #full_name + ' ' + #last_name;
return #full_name;
end
go
When I do:
select concat_names('A', 'B', 'C')
I get no column name in result set.
I know I can rename the column name after its returned as no column name in above select query.
What I only want to know, if there is any way I can name the column while returning the value from the
Try this:
select fullname(#fn, #mn,#ln) AS 'yourName'
You can create table value function to return column with name, like this exmple:
create function udf_ParseDate (
#date as datetime
) returns #dateinfo table (
id int identity(1,1),
[date] datetime,
[year] int,
[month] smallint,
[day] smallint
)
as
begin
insert into #dateinfo
select #date, YEAR(#date), MONTH(#date), DAY(#date)
return;
end
In your code:
if object_id('[co1].[concat_names]') is not null
drop function [co1].[concat_names];
go
create function [co1].[concat_names]
(
#first_name varchar(20),
#middle_name varchar(20),
#last_name varchar(20)
)
returns returns #info table (
fullName varchar(256)
)
as
begin
declare #full_name varchar(62)
set #full_name = #first_name;
if(#middle_name is not null)
set #full_name = #full_name + ' ' + #middle_name;
if(#last_name is not null)
set #full_name = #full_name + ' ' + #last_name;
insert into #info select #full_name;
return;
end
go
Do this:
SELECT fullname(#fn, #mn,#ln) AS COLUM_NAME_YOU_WANT
Create your function something like this:
create function concatall (
#fn as TEXT,
#mn as TEXT,
#ln as TEXT
) returns #merged table (
[FullName] TEXT
)
as
begin
insert into #merged
SELECT CONCAT(#fn , #mn , #ln)
return;
end
What you are looking for is not possible in SQL Server for Scalar valued Functions. Even the default SQL Server Scalar valued function return data with (No column name)
For example
select Checksum('somedata')
Output
(No column name)
---------------------
-1791257452
I am not sure why you want the column name to come from function if you can use alias name, what benifit you are getting?
If you just want to know it is possible or not, in that case answer is "NO".
Only option you have is to use alias name with AS like follwong.
SELECT fullname(#fn, #mn,#ln) AS FullName

Avoid "copy&paste" method for stored procedure depending on parameter

I have 50 stored procedures that I need to add a new location to. Is there an alternative for writing my stored procedures in the following way? (where I copy the same select statement for each location)
IF #LOCATION = 'Canada'
BEGIN
SELECT location_id, location_description
INTO #tempAssetHistoryCANADA
FROM [SERVER20].[Shop_Canada].[dbo].[report_asset_history]
END
IF #LOCATION = 'USA'
BEGIN
SELECT location_id, location_description
INTO #tempAssetHistoryUSA
FROM [SERVER20].[Shop_USA].[dbo].[report_asset_history]
END
I have a select statement that fires if the #parameter = "x" And then the exact same select statement, but from a different data source with the same structure if #parameter = "y".
I'm wondering if there is a better way to write these stored procedures because in the future when I need to add a new location I will need to update all 50 stored procedures, and copy each statement and slightly alter it for the new locations data? I've researched around and haven't found anything helpful.
Thanks!
One possible way instead of using a dynamical query is to create a view:
CREATE VIEW dbo.Locations
AS
SELECT location_id, location_description, 'Canada' AS location
FROM [SERVER20].[Shop_Canada].[dbo].[report_asset_history]
UNION ALL
SELECT location_id, location_description, 'USA' AS location
FROM [SERVER20].[Shop_USA].[dbo].[report_asset_history]
And then using it:
SELECT location_id, location_description
INTO #tempAssetHistory
FROM [dbo].Locations
WHERE location = #LOCATION
If you have new tables [SERVER20].[Shop_XXX].[dbo].[report_asset_history] you will have to add them to your view.
Put the code that loads the temp table into table-valued function. Then call this function from all your other SPs that need the data
SELECT * INTO #TempAssetHistory FROM dbo.LoadTempAssetHistory(#Location)
:
: Use the data
:
The LoadTempAssetHistory SP would look something like (CODE NOT TESTED):
CREATE FUNCTION LoadTempAssetHistory
(
#LOCATION Varchar(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT location_id, location_description
FROM [SERVER20].[Shop_Canada].[dbo].[report_asset_history]
WHERE #LOCATION='CANADA'
UNION
SELECT location_id, location_description
FROM [SERVER20].[Shop_USA].[dbo].[report_asset_history]
WHERE #LOCATION = 'USA'
)
Now you can amend the function when you have a new location (or decide to reorganise all your data) without needing to change 50 SPs.
First of all you don't need a different #temp table for each location. You're storing the same data columns in each. Secondly, you could store the "From" clause in a table based on location and then use dynamic sql to select into your temp table. I'll provide some code and example shortly.
DECLARE #fromClause VARCHAR(255)
DECLARE #sql VARCHAR(MAX)
--Explicitly create the temp table
CREATE TABLE #T (location_id int, location_description varchar(255) )
--Get the FROM clause
select #fromClause = fromClause from tblLocation WHERE location = #LOCATION
--Build the Dynamic SQL
SET #sql = 'SELECT location_id, location_description ' + #fromClause
--Insert into your temp table
INSERT INTO #T execute ( #sql )
--View the results
SELECT * FROM #T
Here is tblLocation definition
You could achieve this by having a #Temp table for all your assists and checking against a location table in your DB, then calling the variable when the SP is executed:
Call the SP:
SP_Some_SP 'Canada'
Inside the SP
Declare #Location Varchar(100)
Declare #Location_ID int = (Select Location_ID from [Location] where Location_Description = #Location)
CREATE TABLE #TempAssetHistory
(
location_ID int,
location_Description varchar(100)
)
If Exists(Select Location_Description from [Location] where Location_Description = #Location )
BEGIN
Insert INTO #TempAssetHistory
Values(#Location_ID,#Location)
END
ELSE
BEGIN
-- Do something
END
You can use one table to store all selected data, use something like this:
DECLARE #country VARCHAR(20) = 'USA'
CREATE TABLE #tempHistory (country varchar(20), location_id int, location_description varchar(20))
DECLARE #sql VARCHAR(max)
SET #sql = 'SELECT ''' + #country + ''' as country, location_id, location_description FROM [SERVER20].[Shop_' + #country + '].[dbo].[report_asset_history]'
INSERT INTO #tempHistory EXEC (#sql)
Or you can use more flexible solution to put the list of countries as a parameter:
CREATE PROCEDURE dbo.prepare_tempHistory(#listOfCountries VARCHAR(max))
AS
DECLARE #sql varchar(max)
SET #sql = ''
SELECT #sql = #sql + ' UNION ALL ' +
'SELECT ''' + val + ''' as country, location_id, location_description FROM [SERVER20].[Shop_' + val + '].[dbo].[report_asset_history]'
FROM dbo.fnSplit(#listOfCountries, ',')
SET #sql = RIGHT(#sql, len(#sql)-11)
INSERT INTO #tempHistory EXEC (#sql)
GO
but then you need a small function to split parameters into table:
CREATE FUNCTION dbo.fnSplit
(
#delimited nvarchar(max),
#delimiter nvarchar(5)
)
RETURNS #ret TABLE (val nvarchar(max))
AS
BEGIN
declare #xml xml
set #xml = N'<root><r>' + replace(#delimited,#delimiter,'</r><r>') + '</r></root>'
insert into #ret(val)
select r.value('.','varchar(max)') as item
from #xml.nodes('//root/r') as records(r)
RETURN
END
GO
Now you can prepare data on easy way:
CREATE TABLE #tempHistory (country varchar(20), location_id int, location_description varchar(20))
EXEC dbo.prepare_tempHistory 'USA,Canada,Mexico'
SELECT * FROM #tempHistory
for any additional country modify only the parameter
using suggestions from the answers and comments mentioning Dynamic SQL I came up with this little solution for myself. It's nicer then what Denis Rubashkin said because using his solution I would still have to copy the entire SQL query every time a new location is added. This way, I can just copy the 4 lines...
IF #LOCATION = 'CANADA'
BEGIN
SET #location_server = 'SHOP_Canada'
END
...from the IF statement at the beginning whenever I want to add a new location, not the whole SQL statement. It will replace the server name with the correct name in the parameter and append its name to the temp tables.
#LOCATION varchar(50),
#sqlCommand nvarchar(2000),
#location_server varchar(75)
IF #LOCATION = 'CANADA'
BEGIN
SET #location_server = 'SHOP_Canada'
END
IF #LOCATION = 'USA'
BEGIN
SET #location_server = 'SHOP_USA'
END
SET #sqlCommand = 'SELECT location_id, location_description
into ##MarineShopAssetExpensesLTD_'+#location_server+'
FROM [SERVER20].'+QUOTENAME(#location_server)+'.[dbo].[report_asset_history]
INNER JOIN [SERVER20].'+QUOTENAME(#location_server)+'.[dbo].imtbl_asset ON [report_asset_history].asset_id = imtbl_asset.id
GROUP BY location_id, location_description
EXECUTE sp_executesql #sqlCommand
As every SP is looking for different data, there is another, somewhat more drastic approach that you could use.
This approach requires that you put all the data SELECT statements for all 50 SPs into a single SP, say spDataLoad, which takes two parameters - a data set name and the location. The spDataLoad selects data based on which data set and which location are specified, and returns that requested data to the caller.
You will still need multiple select statements for each different combination of data set and location, but at least everything is in one single SP, and changes to the data will not affect all 50 SPs. If the tables and data for each location are the same, then you can subdivide the code into sections, one for each location, with identical code except for the database name corresponding to the location.
Using the code above as an example, if we choose 'AssetHistory' as the data set name then the code in your existing SPs would look like this:
:
:
CREATE TABLE #AssetHistory (
location_ID int,
location_Description varchar(100)
);
INSERT INTO #AssetHistory EXEC spDataLoad #DataSet='AssetHistory', #Location=#Location;
:
: use the data set
:
Now suppose you have another SP that requires the data set 'AssetDetails' then the code would be like this:
CREATE TABLE #AssetDetails (
:
: Specification for Asset Details table
:
);
INSERT INTO #AssetDetails EXEC spDataLoad #DataSet='AssetDetails', #Location=#Location;
:
: use the data set
:
The stored procedure spDataLoad, with multiple sections, for each of the locations, with separate selects based on the requested data set might look like this:
CREATE PROCEDURE spDataLoad
#DATASET varchar(20)
, #LOCATION Varchar(50)
AS
BEGIN
-- CANADA SECTION ------------------------------------
IF #LOCATION = 'CANADA'
BEGIN
IF #DATASET = 'AssetHistory'
SELECT location_id, location_description
FROM [SERVER20].[Shop_Canada].[dbo].[report_asset_history]
ELSE IF #DATASET = 'AssetDetails'
SELECT
: Asset details data
FROM [SERVER20].[Shop_Canada].[dbo].[report_asset_details]
ELSE IF #DATASET = '....'
:
: Etc, Etc for CANADA SECTION
END;
-- USA SECTION ------------------------------------
IF #LOCATION = 'USA'
BEGIN
IF #DATASET = 'AssetHistory'
SELECT location_id, location_description
FROM [SERVER20].[Shop_USA].[dbo].[report_asset_history]
ELSE IF #DATASET = 'AssetDetails'
SELECT
: Asset details data
FROM [SERVER20].[Shop_USA].[dbo].[report_asset_details]
ELSE IF #DATASET = '....'
:
: Etc, Etc for USA SECTION
END;
-- SOME OTHER SECTION ---------------------------
IF #LOCATION = 'SOME OTHER'
BEGIN
: Same logic
END
RETURN 0;
END
To manage performance you would probably need to add defaulted parameters for filtering which can be specified by the caller, and add WHERE clauses into the data set selections.

How to make a search query where contain each words of string in SQL Server?

I want to make a search sql query to find a name where contain the string that users input. It is something like the query below, but I don't know how to make the 'where' part. I have been looking in google but I still can't find the right one.
DECLARE #string varchar(20)
SELECT #string = 'test complete name'
SELECT complete_name from users
where complete_name like '%test%'
or complete_name like '%complete%'
or complete_name like '%name%'
or complete_name like '%test complete%'
or complete_name like '%test name%'
or complete_name like '%complete name%'
or complete_name like '%test complete name%'
Create a function like below that splits the given string and returns the individual words from given input
Create function fn_stringSplit(#StringSplit varchar(max))
returns #table table(SplitValue varchar(10) not null)
as
begin
Declare #StartVal int
Declare #endVal int
set #StringSplit = #StringSplit + ' '
set #StartVal = 1
set #endVal = 1
while #endVal >= 0
begin
set #endVal = charindex(' ',#StringSplit,#StartVal);
insert into #table select SUBSTRING(#StringSplit,#StartVal,#endVal-1)
set #StringSplit= SUBSTRING(#StringSplit,#endVal+1, LEN(#StringSplit))
if #StringSplit = '' set #endVal= -1
end
return
end
Now call our function in the main query by passing the input
DECLARE #string varchar(20)
SELECT #string = 'Marketing tool designer'
SELECT JobTitle from Employee e
where JobTitle in (select e.JobTitle from fn_stringSplit(#string) ss
where e.JobTitle like '%'+SplitValue+'%') --Here Splitvalue is the column name in the table that is returned by fn_stringSplitfunction
in SQL SERVER 2016 we have a function String_Split we can write query as
DECLARE #string varchar(20)
SELECT #string = 'Marketing tool designer'
SELECT JobTitle from Employee e
where JobTitle in (select e.JobTitle from String_Split(#string) ss
where e.JobTitle like '%'+Value+'%') --Here **value** is the column name in the table that is returned by **String_Split**
you can create function to split you string into temp table of word. then then use in query.
To create function you can follow the link T-SQL split string
DECLARE #string varchar(20)
SELECT #string = 'test complete name'
SELECT complete_name from users
where complete_name in (dbo.splitstring(#string))
Take care of two things
1) Reference link uses comma separator, you will need space
2) in query will do exact search. You will need to write some more logic for like query. e.g. Pass your column value "complete_name" in created function. use like comparison inside function and return 1 Or 0. So, where will become
DECLARE #string varchar(20)
SELECT #string = 'test complete name'
SELECT complete_name from users
where 1 = dbo.test_complete_name(#string,complete_name)
Below is a method, which won't require any hard coding or creation of any additional function. I have tried describing it in different steps for easier understanding.
DECLARE #string varchar(20) ,#stringxml xml,#rowvalue varchar(20)
SELECT #string = 'test complete name'
--Convert the string to an xml
Select #stringxml=CAST(('<a>'+replace(#string,' ','</a><a>')+'</a>' )as xml)
--Split the xml to rows based on each word.i.e. each word to one row using nodes()
select Row_values.value('.' ,'varchar(max)')
AS StringValues
FROM
#stringxml.nodes('/a') As StrXml(Row_values)
The above query returns a table with rows having each word.This table can joined with your table to do the required search.
The below query is what you need as a final answer
DECLARE #string varchar(20) ,#stringxml xml,#rowvalue varchar(20)
SELECT #string = 'test complete name'
--convert string to xml
Select #stringxml=CAST(('<a>'+replace(#string,' ','</a><a>')+'</a>' )as xml)
--Inner join your table to the value from nodes
Select DISTINCT Urtbl.[ColName] from [YourTableName] Urtbl inner join(
select Row_values.value('.' ,'varchar(max)')
AS StringValues
FROM
#stringxml.nodes('/a') As StrXml(Row_values)) newtbl
on Urtbl.[ColName] like '%'+newtbl.StringValues+'%'

How do I pass a list as a parameter in a stored procedure?

Looking to pass a list of User IDs to return a list names. I have a plan to handle the outputed names (with a COALESCE something or other) but trying to find the best way to pass in the list of user IDs.
The guts of my sproc will look something like this:
create procedure [dbo].[get_user_names]
#user_id_list, --which would equal a list of incoming ID numbers like (5,44,72,81,126)
#username varchar (30) output
as
select last_name+', '+first_name
from user_mstr
where user_id in #user_id_list
Passing the values for #user_id_list is my main concern here.
The preferred method for passing an array of values to a stored procedure in SQL server is to use table valued parameters.
First you define the type like this:
CREATE TYPE UserList AS TABLE ( UserID INT );
Then you use that type in the stored procedure:
create procedure [dbo].[get_user_names]
#user_id_list UserList READONLY,
#username varchar (30) output
as
select last_name+', '+first_name
from user_mstr
where user_id in (SELECT UserID FROM #user_id_list)
So before you call that stored procedure, you fill a table variable:
DECLARE #UL UserList;
INSERT #UL VALUES (5),(44),(72),(81),(126)
And finally call the SP:
EXEC dbo.get_user_names #UL, #username OUTPUT;
As far as I can tell, there are three main contenders: Table-Valued Parameters, delimited list string, and JSON string.
Since 2016, you can use the built-in STRING_SPLIT if you want the delimited route: https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql
That would probably be the easiest/most straightforward/simple approach.
Also since 2016, JSON can be passed as a nvarchar and used with OPENJSON: https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql
That's probably best if you have a more structured data set to pass that may be significantly variable in its schema.
TVPs, it seems, used to be the canonical way to pass more structured parameters, and they are still good if you need that structure, explicitness, and basic value/type checking. They can be a little more cumbersome on the consumer side, though. If you don't have 2016+, this is probably the default/best option.
I think it's a trade off between any of these concrete considerations as well as your preference for being explicit about the structure of your params, meaning even if you have 2016+, you may prefer to explicitly state the type/schema of the parameter rather than pass a string and parse it somehow.
Azure DB, Azure Data WH and from SQL Server 2016, you can use STRING_SPLIT to achieve a similar result to what was described by #sparrow.
Recycling code from #sparrow
WHERE user_id IN (SELECT value FROM STRING_SPLIT( #user_id_list, ',')
Simple and effective way of accepting a list of values into a Stored Procedure
You can try this:
create procedure [dbo].[get_user_names]
#user_id_list varchar(2000), -- You can use any max length
#username varchar (30) output
as
select last_name+', '+first_name
from user_mstr
where user_id in (Select ID from dbo.SplitString( #user_id_list, ',') )
And here is the user defined function for SplitString:
Create FUNCTION [dbo].[SplitString]
(
#Input NVARCHAR(MAX),
#Character CHAR(1)
)
RETURNS #Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output(Item)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1)
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
END
RETURN
END
I solved this problem through the following:
In C # I built a String variable.
string userId="";
I put my list's item in this variable. I separated the ','.
for example: in C#
userId= "5,44,72,81,126";
and Send to SQL-Server
SqlParameter param = cmd.Parameters.AddWithValue("#user_id_list",userId);
I Create Separated Function in SQL-server For Convert my Received List (that it's type is NVARCHAR(Max)) to Table.
CREATE FUNCTION dbo.SplitInts
(
#List VARCHAR(MAX),
#Delimiter VARCHAR(255)
)
RETURNS TABLE
AS
RETURN ( SELECT Item = CONVERT(INT, Item) FROM
( SELECT Item = x.i.value('(./text())[1]', 'varchar(max)')
FROM ( SELECT [XML] = CONVERT(XML, '<i>'
+ REPLACE(#List, #Delimiter, '</i><i>') + '</i>').query('.')
) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y
WHERE Item IS NOT NULL
);
In the main Store Procedure, using the command below, I use the entry list.
SELECT user_id = Item FROM dbo.SplitInts(#user_id_list, ',');
this is perfect working for me . this perfect example i hope solved many users problem.
Step 1
Creare reference table in sql like this
Create TYPE dbo.tblNames
AS TABLE
(
[Name] nvarchar(max)
);
go
create TYPE dbo.tblNamesWithCols
AS TABLE
(
[Name] nvarchar(max)
);
go
Step 2
create store procedure with reference table parameters like this
create proc syTest
#VarTbleNameList AS dbo.tblNames READONLY,
#VarTbleNameColsList AS dbo.tblNamesWithCols READONLY,
#VarWhereQuery nvarchar(max)
as
begin
......
...... End
**Calling Store Procedure with parameters **
DECLARE #VarTbleList AS dbo.tblNames
INSERT INTO #VarTbleList
VALUES ( 'tblEmployes' )
INSERT INTO #VarTbleList
VALUES ( 'tblDepartments' )
INSERT INTO #VarTbleList
VALUES ( 'tblCities' )
DECLARE #VarTbleColList AS dbo.tblNamesWithCols
INSERT INTO #VarTbleColList
VALUES ( 'tblEmployes.EmployeId as empId;' )
INSERT INTO #VarTbleColList
VALUES ( 'tblEmployes.EmployeName as empName;' )
INSERT INTO #VarTbleColList
VALUES ( 'tblDepartments.DepartmentName as deptName;' )
INSERT INTO #VarTbleColList
VALUES ( 'tblDepartments.DepartmentId as deptId;' )
EXECUTE syTest #VarTbleList , #VarTbleColList , #VarWhereQuery ='test'
You can use this simple 'inline' method to construct a string_list_type parameter (works in SQL Server 2014):
declare #p1 dbo.string_list_type
insert into #p1 values(N'myFirstString')
insert into #p1 values(N'mySecondString')
Example use when executing a stored proc:
exec MyStoredProc #MyParam=#p1
Check the below code this work for me
#ManifestNoList VARCHAR(MAX)
WHERE
(
ManifestNo IN (SELECT value FROM dbo.SplitString(#ManifestNoList, ','))
)
The proper way is to create a user defined data type:
CREATE TYPE [dbo].[IntArray] AS TABLE
(
[ID] [INT] NULL
)
Then you can use this custom data type:
CREATE OR ALTER PROCEDURE [dbo].[sp_GetUserNames]
(
#userIds [IntArray] READONLY
)
AS
BEGIN
SET NOCOUNT ON;
SELECT
"Name" = u.LastName + ', ' + u.FirstName
FROM dbo.User u
JOIN #userIds uid ON u.Id = uid.Id;
END
Usage:
#DECLARE #result TABLE
(
Name NVARCHAR(max)
);
#DECLARE #ids [IntArray] = SELECT x.userId FROM dbo.sometable x;
SET #result = EXECUTE [dbo].[sp_GetUserNames] #userIds = #ids;
SELECT * FROM #result;
Maybe you could use:
select last_name+', '+first_name
from user_mstr
where ',' + #user_id_list + ',' like '%,' + convert(nvarchar, user_id) + ',%'

Microsoft t sql how to declare temporary variable within user defined function?

So how can I declare a temporary local variable with declare like:declare #tempVar varchar(max) within a user declared function?
The actual problem I'm trying to solve here is declaring and using variable within user defined stored function. I declare my function like this:
create function someFunction(#someParam varchar(100))
returns table
as
return (
declare #tempvar varchar(100)
set #tempvar = ''--Set the var to something useful
select * from sometable where somecolumn = (
select top 1 someColumn
from sometable
where somecolumn = #tempvar
)
)
Server complain about the variable being declared in wrong place. Where should I declare my variables in UDF like this?
You are creating an Inline Table-valued Function, this kind of functions must contain only a single SELECT statement.
If you want to use variables you must create a Multi-statement Table-valued Function. Your function would be declared as:
create function someFunction(#someParam varchar(100))
returns #table (field1 type, field2 type, ...)
as
begin
declare #tempvar varchar(100)
set #tempvar = ''--Set the var to something useful
insert #table
select * from sometable where somecolumn = (
select top 1 someColumn
from sometable
where somecolumn = #tempvar
)
return
end
If you wanted to keep the table function inline you could use a common table expression to define your variable(s) as shown below:
create function someFunction(#someParam varchar(100))
returns table
as
return (
WITH cte (tempvar) AS
(
SELECT '' -- Set the var to something useful
)
select * from sometable where somecolumn = (
select top 1 someColumn
from sometable
JOIN cte ON 1=1
where somecolumn = cte.tempvar
)
)