How to create new table within function in sql - sql

I created one function, That function return the table values like below
CREATE FUNCTION dbo.splitText(#strArgs VARCHAR(4000))
RETURNS #tab TABLE
(
[Key] VARCHAR(255) NOT NULL,
Value VARCHAR(4000) NOT NULL
)
AS
BEGIN
INSERT INTO #tab VALUES('Key1', 'Value1')
INSERT INTO #tab VALUES('Key2', 'Value2')
RETURN
END
GO
OUtput:
Key Value
*************
Key1 Value1
Key2 Value2
The second function i need,is to return the table values from the above fuction.
CREATE FUNCTION dbo.TableValuedParameterExample11()
RETURNS #TmpTable1 table (Value VARCHAR(4000) NOT NULL)
AS
BEGIN
DECLARE #StateDescp VARCHAR(250)
Select * into TmpTable1 from (Select value from dbo.Splittext('Test')) aa
RETURN
END
GO
after finishing the functions,i am running the below query.
Select * from TmpTable1.
Output i need
Value
********
Value1
Value2
I need this out put.
But I got error
Invalid use of a side-effecting operator 'SELECT INTO' within a function.

When you write select * into [table]... you must be sure the [table] doesnot exist. use insert into [table] select ... instead. also, you need a # when you deal with variable or function table:
CREATE FUNCTION dbo.TableValuedParameterExample11()
RETURNS #TmpTable1 table (Value VARCHAR(4000) NOT NULL)
AS
BEGIN
DECLARE #StateDescp VARCHAR(250)
INSERT INTO
#TmpTable1([Value])
SELECT
value
FROM
dbo.SplitArgs('Test')) aa
RETURN
END
GO

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

How do I create a function to accept [[customerID]] and return CustName Please look at details

I have been asked to created a Function to accept CustomerID and return CustomerName for the CustomerID, I m a new Student/Developer Please if the question is not clear let me know so i can add more details about it, but that is what I was exactly asked.
functions in SQL are of three types.ignoring rest CLR functions ...
create table test
(
id int,
name varchar(4)
)
insert into test
select 1,'abc'
union all
select 2,'cde'
1.Scalar function takes one value and return one value
now for the above table ,you can create scalar function like below
create function dbo.test
(
#id int
)
returns varchar(4)
as
begin
declare #name varchar(4)
select #name=name from test where id =#id
return #name
End
You invoke it like:
select dbo.test(1)
2.Inline table valued functions:takes a single input same like scalar functions and returns table
create function dbo.test
(
#id int
)
as
returns TABLE
(
select * from test where id=#id)
You invoke it like:
select * from dbo.test(1)
3.Multi table valued function:
create function dbo.test
(
#id int
)
returns
#test table
(
id int,
name varchar(4)
)
as
begin
insert into #test
select * from test where id =#id
return
end
You invoke it like:
select * from dbo.test(1)
Take any one of Itzik Ben Gan books and start learning SQL the way it should be learned

Function return table variable

I'm trying to create a function that return a table variable.So firstly i get data from Table1 and put it in another table variable. Here i want check if this variable isempty the function return the parameter result else return the result of the table variable
The function script is bellow :
USE[DATABase1]
GO
IF OBJECT_ID (N'CodeFunc', N'TF') IS NOT NULL DROP FUNCTION dbo.CodeFunc;
GO
CREATE FUNCTION CodeFunc ( #Code nvarchar(4) , #Table nvarchar(40) = '' )
RETURNS #VirtualDAT TABLE
(
RowID INT IDENTITY ( 1 , 1 ),
Code nvarchar(400)
)
AS
BEGIN
DECLARE #CodeM nvarchar(400)
DECLARE #imax INT SET #imax = ##ROWCOUNT
DECLARE #i INT SET #i = 1
DECLARE #SelectDAT TABLE
(
RowID INT IDENTITY ( 1 , 1 ),
Code nvarchar(400)
)
INSERT #SelectDAT
SELECT Code FROM table1
WHERE table1.id = 41
IF(EXISTS (SELECT 1 FROM #SelectDAT))
BEGIN
WHILE (#i <= #imax)
BEGIN
SELECT #CodeM = Code FROM #SelectDAT WHERE RowID = #i
INSERT INTO #VirtualDAT(Code) VALUES (#CodeM)
SET #i = #i + 1
END
END
ELSE
INSERT INTO #VirtualDAT(Code) VALUES (#Code)
RETURN
END
So this script works without put it inside function.
And i test this function like this :SELECT * FROM dbo.CodeFunc( 'toto',Default ) the result is :
IF(EXISTS (SELECT 1 FROM #SelectDAT)) no record returned
esle the result is ok
As VR46 says. The ##ROWCOUNT will be set to 0 because there is no query before it. Any code executing in a function happens as a seperate set of queries. It was probably returning a value outside the function because you had previously used the query window for another unrelated query
You could re-factor this function quite dramatically. Look below, ##ROWCOUNT will work here as it is just after the insert query and will definitely have a value based on the insert.
I have not been able to test this, but I think something like this should do the same job.
USE[DATABase1]
GO
IF OBJECT_ID (N'CodeFunc', N'TF') IS NOT NULL DROP FUNCTION dbo.CodeFunc;
GO
CREATE FUNCTION CodeFunc ( #Code nvarchar(4) , #Table nvarchar(40) = '' )
RETURNS #VirtualDAT TABLE
(
RowID INT IDENTITY ( 1 , 1 ),
Code nvarchar(400)
)
AS
BEGIN
insert into #VirtualDAT
Select Code from table1 where table1.id = 41
if ##ROWCOUNT = 0
begin
INSERT INTO #VirtualDAT(Code) VALUES (#Code)
end
RETURN
END
Since you are assigning #imax with ##ROWCOUNT right after declaration of variable will be initialized with zero.
From MSDN ##ROWCOUNT
Returns the number of rows affected by the last statement.
If am not wrong you need to assign value to #imax after the insert into..select query.
INSERT #SelectDAT
SELECT Code FROM table1
WHERE table1.id = 41
SET #imax= ##ROWCOUNT
You can do the same in SET BASED APPROACH without using while loop.
CREATE FUNCTION Codefunc (#Code NVARCHAR(4),
#Table NVARCHAR(40) = '')
returns #VirtualDAT TABLE (
rowid INT IDENTITY ( 1, 1 ),
code NVARCHAR(400))
AS
BEGIN
IF EXISTS (SELECT code
FROM table1
WHERE table1.id = 41)
BEGIN
INSERT INTO #VirtualDAT
(code)
SELECT code
FROM table1
WHERE table1.id = 41
END
ELSE
INSERT INTO #VirtualDAT
(code)
VALUES (#Code)
RETURN
END

SQL server stored procedure return a table

I have a stored procedure that takes in two parameters. I can execute it successfully in Server Management Studio. It shows me the results which are as I expect. However it also returns a Return Value.
It has added this line,
SELECT 'Return Value' = #return_value
I would like the stored procedure to return the table it shows me in the results not the return value as I am calling this stored procedure from MATLAB and all it returns is true or false.
Do I need to specify in my stored procedure what it should return? If so how do I specify a table of 4 columns (varchar(10), float, float, float)?
A procedure can't return a table as such. However you can select from a table in a procedure and direct it into a table (or table variable) like this:
create procedure p_x
as
begin
declare #t table(col1 varchar(10), col2 float, col3 float, col4 float)
insert #t values('a', 1,1,1)
insert #t values('b', 2,2,2)
select * from #t
end
go
declare #t table(col1 varchar(10), col2 float, col3 float, col4 float)
insert #t
exec p_x
select * from #t
I do this frequently using Table Types to ensure more consistency and simplify code. You can't technically return "a table", but you can return a result set and using INSERT INTO .. EXEC ... syntax, you can clearly call a PROC and store the results into a table type. In the following example I'm actually passing a table into a PROC along with another param I need to add logic, then I'm effectively "returning a table" and can then work with that as a table variable.
/****** Check if my table type and/or proc exists and drop them ******/
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'returnTableTypeData')
DROP PROCEDURE returnTableTypeData
GO
IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = 'myTableType')
DROP TYPE myTableType
GO
/****** Create the type that I'll pass into the proc and return from it ******/
CREATE TYPE [dbo].[myTableType] AS TABLE(
[someInt] [int] NULL,
[somenVarChar] [nvarchar](100) NULL
)
GO
CREATE PROC returnTableTypeData
#someInputInt INT,
#myInputTable myTableType READONLY --Must be readonly because
AS
BEGIN
--Return the subset of data consistent with the type
SELECT
*
FROM
#myInputTable
WHERE
someInt < #someInputInt
END
GO
DECLARE #myInputTableOrig myTableType
DECLARE #myUpdatedTable myTableType
INSERT INTO #myInputTableOrig ( someInt,somenVarChar )
VALUES ( 0, N'Value 0' ), ( 1, N'Value 1' ), ( 2, N'Value 2' )
INSERT INTO #myUpdatedTable EXEC returnTableTypeData #someInputInt=1, #myInputTable=#myInputTableOrig
SELECT * FROM #myUpdatedTable
DROP PROCEDURE returnTableTypeData
GO
DROP TYPE myTableType
GO
Consider creating a function which can return a table and be used in a query.
https://msdn.microsoft.com/en-us/library/ms186755.aspx
The main difference between a function and a procedure is that a function makes no changes to any table. It only returns a value.
In this example I'm creating a query to give me the counts of all the columns in a given table which aren't null or empty.
There are probably many ways to clean this up. But it illustrates a function well.
USE Northwind
CREATE FUNCTION usp_listFields(#schema VARCHAR(50), #table VARCHAR(50))
RETURNS #query TABLE (
FieldName VARCHAR(255)
)
BEGIN
INSERT #query
SELECT
'SELECT ''' + #table+'~'+RTRIM(COLUMN_NAME)+'~''+CONVERT(VARCHAR, COUNT(*)) '+
'FROM '+#schema+'.'+#table+' '+
' WHERE isnull("'+RTRIM(COLUMN_NAME)+'",'''')<>'''' UNION'
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #table and TABLE_SCHEMA = #schema
RETURN
END
Then executing the function with
SELECT * FROM usp_listFields('Employees')
produces a number of rows like:
SELECT 'Employees~EmployeeID~'+CONVERT(VARCHAR, COUNT(*)) FROM dbo.Employees WHERE isnull("EmployeeID",'')<>'' UNION
SELECT 'Employees~LastName~'+CONVERT(VARCHAR, COUNT(*)) FROM dbo.Employees WHERE isnull("LastName",'')<>'' UNION
SELECT 'Employees~FirstName~'+CONVERT(VARCHAR, COUNT(*)) FROM dbo.Employees WHERE isnull("FirstName",'')<>'' UNION
You can use an out parameter instead of the return value if you want both a result set and a return value
CREATE PROCEDURE proc_name
#param int out
AS
BEGIN
SET #param = value
SELECT ... FROM [Table] WHERE Condition
END
GO
I had a similar situation and solved by using a temp table inside the procedure, with the same fields being returned by the original Stored Procedure:
CREATE PROCEDURE mynewstoredprocedure
AS
BEGIN
INSERT INTO temptable (field1, field2)
EXEC mystoredprocedure #param1, #param2
select field1, field2 from temptable
-- (mystoredprocedure returns field1, field2)
END
The Status Value being returned by a Stored Procedure can only be an INT datatype. You cannot return other datatypes in the RETURN statement.
From Lesson 2: Designing Stored Procedures:
Every stored procedure can return an integer value known as the
execution status value or return code.
If you still want a table returned from the SP, you'll either have to work the record set returned from a SELECT within the SP or tie into an OUTPUT variable that passes an XML datatype.
HTH,
John
Though this question is very old but as a new in Software Development I can't stop my self to share what I have learnt :D
Creation of Stored Procedure:
CREATE PROC usp_ValidateUSer
(
#UserName nVARCHAR(50),
#Password nVARCHAR(50)
)
AS
BEGIN
IF EXISTS(SELECT '#' FROM Users WHERE Username=#UserName AND Password=#Password)
BEGIN
SELECT u.UserId, u.Username, r.UserRole
FROM Users u
INNER JOIN UserRoles r
ON u.UserRoleId=r.UserRoleId
END
END
Execution of Stored Procedure:
(If you want to test the execution of Stored Procedure in SQL)
EXEC usp_ValidateUSer #UserName='admin', #Password='admin'
The Output:
create procedure PSaleCForms
as
begin
declare
#b varchar(9),
#c nvarchar(500),
#q nvarchar(max)
declare #T table(FY nvarchar(9),Qtr int,title nvarchar (max),invoicenumber nvarchar(max),invoicedate datetime,sp decimal 18,2),grandtotal decimal(18,2))
declare #data cursor
set #data= Cursor
forward_only static
for
select x.DBTitle,y.CurrentFinancialYear from [Accounts Manager].dbo.DBManager x inner join [Accounts Manager].dbo.Accounts y on y.DBID=x.DBID where x.cfy=1
open #data
fetch next from #data
into #c,#b
while ##FETCH_STATUS=0
begin
set #q=N'Select '''+#b+''' [fy], case cast(month(i.invoicedate)/3.1 as int) when 0 then 4 else cast(month(i.invoicedate)/3.1 as int) end [Qtr], l.title,i.invoicenumber,i.invoicedate,i.sp,i.grandtotal from ['+#c+'].dbo.invoicemain i inner join ['+#c+'].dbo.ledgermain l on l.ledgerid=i.ledgerid where (sp=0 or stocktype=''x'') and invoicetype=''DS'''
insert into #T exec [master].dbo.sp_executesql #q
fetch next from #data
into #c,#b
end
close #data
deallocate #data
select * from #T
return
end
Here's an example of a SP that both returns a table and a return value. I don't know if you need the return the "Return Value" and I have no idea about MATLAB and what it requires.
CREATE PROCEDURE test
AS
BEGIN
SELECT * FROM sys.databases
RETURN 27
END
--Use this to test
DECLARE #returnval int
EXEC #returnval = test
SELECT #returnval

Pass table as parameter into sql server UDF

I'd like to pass a table as a parameter into a scaler UDF.
I'd also prefer to restrict the parameter to tables with only one column. (optional)
Is this possible?
EDIT
I don't want to pass a table name, I'd like to pass the table of data (as a reference I presume)
EDIT
I would want my Scaler UDF to basically take a table of values and return a CSV list of the rows.
IE
col1
"My First Value"
"My Second Value"
...
"My nth Value"
would return
"My First Value, My Second Value,... My nth Value"
I'd like to do some filtering on the table though, IE ensuring that there are no nulls and to ensure there are no duplicates. I was expecting something along the lines of:
SELECT dbo.MyFunction(SELECT DISTINCT myDate FROM myTable WHERE myDate IS NOT NULL)
You can, however no any table. From documentation:
For Transact-SQL functions, all data
types, including CLR user-defined
types and user-defined table types,
are allowed except the timestamp data
type.
You can use user-defined table types.
Example of user-defined table type:
CREATE TYPE TableType
AS TABLE (LocationName VARCHAR(50))
GO
DECLARE #myTable TableType
INSERT INTO #myTable(LocationName) VALUES('aaa')
SELECT * FROM #myTable
So what you can do is to define your table type, for example TableType and define the function which takes the parameter of this type. An example function:
CREATE FUNCTION Example( #TableName TableType READONLY)
RETURNS VARCHAR(50)
AS
BEGIN
DECLARE #name VARCHAR(50)
SELECT TOP 1 #name = LocationName FROM #TableName
RETURN #name
END
The parameter has to be READONLY. And example usage:
DECLARE #myTable TableType
INSERT INTO #myTable(LocationName) VALUES('aaa')
SELECT * FROM #myTable
SELECT dbo.Example(#myTable)
Depending on what you want achieve you can modify this code.
EDIT:
If you have a data in a table you may create a variable:
DECLARE #myTable TableType
And take data from your table to the variable
INSERT INTO #myTable(field_name)
SELECT field_name_2 FROM my_other_table
Unfortunately, there is no simple way in SQL Server 2005. Lukasz' answer is correct for SQL Server 2008 though and the feature is long overdue
Any solution would involve temp tables, or passing in xml/CSV and parsing in the UDF. Example: change to xml, parse in udf
DECLARE #psuedotable xml
SELECT
#psuedotable = ...
FROM
...
FOR XML ...
SELECT ... dbo.MyUDF (#psuedotable)
What do you want to do in the bigger picture though? There may be another way to do this...
Edit: Why not pass in the query as a string and use a stored proc with output parameter
Note: this is an untested bit of code, and you'd need to think about SQL injection etc. However, it also satisfies your "one column" requirement and should help you along
CREATE PROC dbo.ToCSV (
#MyQuery varchar(2000),
#CSVOut varchar(max)
)
AS
SET NOCOUNT ON
CREATE TABLE #foo (bar varchar(max))
INSERT #foo
EXEC (#MyQuery)
SELECT
#CSVOut = SUBSTRING(buzz, 2, 2000000000)
FROM
(
SELECT
bar -- maybe CAST(bar AS varchar(max))??
FROM
#foo
FOR XML PATH (',')
) fizz(buzz)
GO
Step 1: Create a Type as Table with name TableType that will accept a table having one varchar column
create type TableType
as table ([value] varchar(100) null)
Step 2: Create a function that will accept above declared TableType as Table-Valued Parameter and String Value as Separator
create function dbo.fn_get_string_with_delimeter (#table TableType readonly,#Separator varchar(5))
returns varchar(500)
As
begin
declare #return varchar(500)
set #return = stuff((select #Separator + value from #table for xml path('')),1,1,'')
return #return
end
Step 3: Pass table with one varchar column to the user-defined type TableType and ',' as separator in the function
select dbo.fn_get_string_with_delimeter(#tab, ',')
Cutting to the bottom line, you want a query like SELECT x FROM y to be passed into a function that returns the values as a comma separated string.
As has already been explained you can do this by creating a table type and passing a UDT into the function, but this needs a multi-line statement.
You can pass XML around without declaring a typed table, but this seems to need a xml variable which is still a multi-line statement i.e.
DECLARE #MyXML XML = (SELECT x FROM y FOR XML RAW);
SELECT Dbo.CreateCSV(#MyXml);
The "FOR XML RAW" makes the SQL give you it's result set as some xml.
But you can bypass the variable using Cast(... AS XML). Then it's just a matter of some XQuery and a little concatenation trick:
CREATE FUNCTION CreateCSV (#MyXML XML)
RETURNS VARCHAR(MAX)
BEGIN
DECLARE #listStr VARCHAR(MAX);
SELECT
#listStr =
COALESCE(#listStr+',' ,'') +
c.value('#Value[1]','nvarchar(max)')
FROM #myxml.nodes('/row') as T(c)
RETURN #listStr
END
GO
-- And you call it like this:
SELECT Dbo.CreateCSV(CAST(( SELECT x FROM y FOR XML RAW) AS XML));
-- Or a working example
SELECT Dbo.CreateCSV(CAST((
SELECT DISTINCT number AS Value
FROM master..spt_values
WHERE type = 'P'
AND number <= 20
FOR XML RAW) AS XML));
As long as you use FOR XML RAW all you need do is alias the column you want as Value, as this is hard coded in the function.
PASSING TABLE AS PARAMETER IN STORED PROCEDURE
Step 1:
CREATE TABLE [DBO].T_EMPLOYEES_DETAILS
(
Id int,
Name nvarchar(50),
Gender nvarchar(10),
Salary int
)
Step 2:
CREATE TYPE EmpInsertType AS TABLE
(
Id int,
Name nvarchar(50),
Gender nvarchar(10),
Salary int
)
Step 3:
/* Must add READONLY keyword at end of the variable */
CREATE PROC PRC_EmpInsertType
#EmployeeInsertType EmpInsertType READONLY
AS
BEGIN
INSERT INTO [DBO].T_EMPLOYEES_DETAILS
SELECT * FROM #EmployeeInsertType
END
Step 4:
DECLARE #EmployeeInsertType EmpInsertType
INSERT INTO #EmployeeInsertType VALUES(1,'John','Male',50000)
INSERT INTO #EmployeeInsertType VALUES(2,'Praveen','Male',60000)
INSERT INTO #EmployeeInsertType VALUES(3,'Chitra','Female',45000)
INSERT INTO #EmployeeInsertType VALUES(4,'Mathy','Female',6600)
INSERT INTO #EmployeeInsertType VALUES(5,'Sam','Male',50000)
EXEC PRC_EmpInsertType #EmployeeInsertType
=======================================
SELECT * FROM T_EMPLOYEES_DETAILS
OUTPUT
1 John Male 50000
2 Praveen Male 60000
3 Chitra Female 45000
4 Mathy Female 6600
5 Sam Male 50000
I've been dealing with a very similar problem and have been able to achieve what I was looking for, even though I'm using SQL Server 2000. I know it is an old question, but think its valid to post here the solution since there should be others like me that use old versions and still need help.
Here's the trick: SQL Server won't accept passing a table to a UDF, nor you can pass a T-SQL query so the function creates a temp table or even calls a stored procedure to do that. So, instead, I've created a reserved table, which I called xtList. This will hold the list of values (1 column, as needed) to work with.
CREATE TABLE [dbo].[xtList](
[List] [varchar](1000) NULL
) ON [PRIMARY]
Then, a stored procedure to populate the list. This is not strictly necessary, but I think is very usefull and best practice.
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpCreateList]
#ListQuery varchar(2000)
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM xtList
INSERT INTO xtList
EXEC(#ListQuery)
END
Now, just deal with the list in any way you want, using the xtList. You can use in a procedure (for executing several T-SQL commands), scalar functions (for retrieving several strings) or multi-statement table-valued functions (retrieves the strings but like it was inside a table, 1 string per row). For any of that, you'll need cursors:
DECLARE #Item varchar(100)
DECLARE cList CURSOR DYNAMIC
FOR (SELECT * FROM xtList WHERE List is not NULL)
OPEN cList
FETCH FIRST FROM cList INTO #Item
WHILE ##FETCH_STATUS = 0 BEGIN
<< desired action with values >>
FETCH NEXT FROM cList INTO #Item
END
CLOSE cList
DEALLOCATE cList
The desired action would be as follows, depending on which type of object created:
Stored procedures
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpProcreateExec]
(
#Cmd varchar(8000),
#ReplaceWith varchar(1000)
)
AS
BEGIN
DECLARE #Query varchar(8000)
<< cursor start >>
SET #Query = REPLACE(#Cmd,#ReplaceWith,#Item)
EXEC(#Query)
<< cursor end >>
END
/* EXAMPLES
(List A,B,C)
Query = 'SELECT x FROM table'
with EXEC xpProcreateExec(Query,'x') turns into
SELECT A FROM table
SELECT B FROM table
SELECT C FROM table
Cmd = 'EXEC procedure ''arg''' --whatchout for wrong quotes, since it executes as dynamic SQL
with EXEC xpProcreateExec(Cmd,'arg') turns into
EXEC procedure 'A'
EXEC procedure 'B'
EXEC procedure 'C'
*/
Scalar functions
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateStr]
(
#OriginalText varchar(8000),
#ReplaceWith varchar(1000)
)
RETURNS varchar(8000)
AS
BEGIN
DECLARE #Result varchar(8000)
SET #Result = ''
<< cursor start >>
SET #Result = #Result + REPLACE(#OriginalText,#ReplaceWith,#Item) + char(13) + char(10)
<< cursor end >>
RETURN #Result
END
/* EXAMPLE
(List A,B,C)
Text = 'Access provided for user x'
with "SELECT dbo.xfProcreateStr(Text,'x')" turns into
'Access provided for user A
Access provided for user B
Access provided for user C'
*/
Multi-statement table-valued functions
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateInRows]
(
#OriginalText varchar(8000),
#ReplaceWith varchar(1000)
)
RETURNS
#Texts TABLE
(
Text varchar(2000)
)
AS
BEGIN
<< cursor start >>
INSERT INTO #Texts VALUES(REPLACE(#OriginalText,#ReplaceWith,#Item))
<< cursor end >>
END
/* EXAMPLE
(List A,B,C)
Text = 'Access provided for user x'
with "SELECT * FROM dbo.xfProcreateInRow(Text,'x')" returns rows
'Access provided for user A'
'Access provided for user B'
'Access provided for user C'
*/
To obtain the column count on a table, use this:
select count(id) from syscolumns where id = object_id('tablename')
and to pass a table to a function, try XML as show here:
create function dbo.ReadXml (#xmlMatrix xml)
returns table
as
return
( select
t.value('./#Salary', 'integer') as Salary,
t.value('./#Age', 'integer') as Age
from #xmlMatrix.nodes('//row') x(t)
)
go
declare #source table
( Salary integer,
age tinyint
)
insert into #source
select 10000, 25 union all
select 15000, 27 union all
select 12000, 18 union all
select 15000, 36 union all
select 16000, 57 union all
select 17000, 44 union all
select 18000, 32 union all
select 19000, 56 union all
select 25000, 34 union all
select 7500, 29
--select * from #source
declare #functionArgument xml
select #functionArgument =
( select
Salary as [row/#Salary],
Age as [row/#Age]
from #source
for xml path('')
)
--select #functionArgument as [#functionArgument]
select * from readXml(#functionArgument)
/* -------- Sample Output: --------
Salary Age
----------- -----------
10000 25
15000 27
12000 18
15000 36
16000 57
17000 44
18000 32
19000 56
25000 34
7500 29
*/
create table Project (ProjectId int, Description varchar(50));
insert into Project values (1, 'Chase tail, change directions');
insert into Project values (2, 'ping-pong ball in clothes dryer');
create table ProjectResource (ProjectId int, ResourceId int, Name varchar(15));
insert into ProjectResource values (1, 1, 'Adam');
insert into ProjectResource values (1, 2, 'Kerry');
insert into ProjectResource values (1, 3, 'Tom');
insert into ProjectResource values (2, 4, 'David');
insert into ProjectResource values (2, 5, 'Jeff');
SELECT *,
(SELECT Name + ' ' AS [text()]
FROM ProjectResource pr
WHERE pr.ProjectId = p.ProjectId
FOR XML PATH (''))
AS ResourceList
FROM Project p
-- ProjectId Description ResourceList
-- 1 Chase tail, change directions Adam Kerry Tom
-- 2 ping-pong ball in clothes dryer David Jeff
The following will enable you to quickly remove the duplicate,null values and return only the valid one as list.
CREATE TABLE DuplicateTable (Col1 INT)
INSERT INTO DuplicateTable
SELECT 8
UNION ALL
SELECT 1--duplicate
UNION ALL
SELECT 2 --duplicate
UNION ALL
SELECT 1
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION
SELECT NULL
GO
WITH CTE (COl1,DuplicateCount)
AS
(
SELECT COl1,
ROW_NUMBER() OVER(PARTITION BY COl1 ORDER BY Col1) AS DuplicateCount
FROM DuplicateTable
WHERE (col1 IS NOT NULL)
)
SELECT COl1
FROM CTE
WHERE DuplicateCount =1
GO
CTE are valid in SQL 2005 , you could then store the values in a temp table and use it with your function.
you can do something like this
/* CREATE USER DEFINED TABLE TYPE */
CREATE TYPE StateMaster AS TABLE
(
StateCode VARCHAR(2),
StateDescp VARCHAR(250)
)
GO
/*CREATE FUNCTION WHICH TAKES TABLE AS A PARAMETER */
CREATE FUNCTION TableValuedParameterExample(#TmpTable StateMaster READONLY)
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE #StateDescp VARCHAR(250)
SELECT #StateDescp = StateDescp FROM #TmpTable
RETURN #StateDescp
END
GO
/*CREATE STORED PROCEDURE WHICH TAKES TABLE AS A PARAMETER */
CREATE PROCEDURE TableValuedParameterExample_SP
(
#TmpTable StateMaster READONLY
)
AS
BEGIN
INSERT INTO StateMst
SELECT * FROM #TmpTable
END
GO
BEGIN
/* DECLARE VARIABLE OF TABLE USER DEFINED TYPE */
DECLARE #MyTable StateMaster
/* INSERT DATA INTO TABLE TYPE */
INSERT INTO #MyTable VALUES('11','AndhraPradesh')
INSERT INTO #MyTable VALUES('12','Assam')
/* EXECUTE STORED PROCEDURE */
EXEC TableValuedParameterExample_SP #MyTable
GO
For more details check this link: http://sailajareddy-technical.blogspot.in/2012/09/passing-table-valued-parameter-to.html