Pass Table as parameter to function - sql

I have a temp table which contains data needed in selection, but I can't join in to main select statement because it contains too many rows, and grouping is not good enough. So I decided to use values directly from my temp table in the selection, and it works fine. But since I need to add selection from temp table 50 times as sub queries in that main selection, I was considering to move it to function, as is nicer to call a function 50 times than sub queries.
My question is how to pass values from that table to function? Function will be also supplied with other parameters needed for extraction exact value from that table. I know I can't pass temp table as a parameter, but what about table variable? I don't care if I use temp table or a table variable..
Firstly I wrote a function containing the select statement same as for temp table, and it works but too slow. So if I could pass table results to a function, it will speed up the process..
My function now look like this:
ALTER FUNCTION [document].[GetPersonPremium]
(
-- Add the parameters for the function here
#DocumentId bigint,
#PersonId bigint,
#PeriodId int,
#PersonRole nvarchar(20)
)
RETURNS DECIMAL (18,2)
AS
BEGIN
-- Declare the return variable here
DECLARE #premiumSum decimal (18,2)
-- Add the T-SQL statements to compute the return value here
set #premiumSum =
(select top 1 pt.Premium from document.Document d
inner join document.Person p on p.DocumentCalculationLayerID = dcl.DocumentCalculationLayerID
inner join document.PersonTasks pt on pt.PersonId = p.PersonId
inner join document.PersonCalculationHelper pch on pch.PersonTaskId = pt.PersonTaskId
inner join document.PersonTaskCalculationHelper ptch on ptch.PersonId = p.PersonId
inner join document.PersonMarkTypes pmt on pmt.ConcernMarkTypeID = ptch.ConcernMarkTypeId
where dcl.DocumentID = #DocumentId and p.PersonId = #PersonId and pch.PeriodId = #PeriodId and pmt.Name = #PersonRole)
-- Return the result of the function
RETURN #premiumSum
END
And I would like to use it from stored procedure like this:
...
Engineer = Coalesce(document.GetPersonPremium(#DocumentId, p.PersonID, 65, 'Intern'), 0.00),
...
Any suggestion?

The answer is for those who come to this page with same or similar problem.
I created a table type:
CREATE TYPE PremiumTableType AS TABLE
(
PersonId bigint,
PeriodId int,
PersonRole nvarchar(20),
)
Included it in function:
ALTER FUNCTION [document].[GetPersonPremium]
(
-- Add the parameters for the function here
#DocumentId bigint,
#PersonId bigint,
#PeriodId int,
#PersonRole nvarchar(20),
#PremiumTableType PremiumTableType readonly
)
RETURNS DECIMAL (18,2)
AS
BEGIN
-- Declare the return variable here
DECLARE #premiumSum decimal (18,2)
-- Add the T-SQL statements to compute the return value here
set #premiumSum = (select p.Premium from #PremiumType p where p.PersonId = #PersonId and p.PeriodId = #PeriodId and p.PersonRole = #PersonRole)
-- Return the result of the function
RETURN #premiumSum
END
In SP declared table type variable
Declare #PremiumTableType PremiumTableType
Inserted data from my temp table
Insert into #PremiumTableType (PersonID, PeriodId, ConcernRole, PersonPremium)
Select p.PersonID, ...
And called function from SP like
document.GetPersonPremium(#DocumentID, p.PersonID, pt.PeriodID, 'Intern', #PremiumTableType)

Related

Create a function that accepts list of ids?

I would like to do create a SQL function like this (pseudocode):
function PeopleInCompanies(companyIds)
SELECT * from Person WHERE CompanyId IN (companyIds)
end function
and call it like this:
define companyIds = 1,2,3
select * from PeopleInCompanies(companyIds)
is it even possible?
You would need to use a table type parameter. Assuming that CompanyID is an int:
CREATE TYPE dbo.ints AS TABLE ([value] int);
GO
CREATE FUNCTION dbo.PeopleInCompanies (#CompanyID dbo.ints READONLY)
RETURNS TABLE
AS RETURN
SELECT P.* --This should be replaced by the columns you need.
FROM dbo.Person P
JOIN #CompanyID CI ON P.CompanyID = CI.[Value];
Then you would call the function using:
DECLARE #CompanyID dbo.ints;
INSERT INTO #CompanyID
VALUES (1),(2),(3);
SELECT *
FROM dbo.PeopleInCompanies(#CompanyID);
SQL Server does not support macro substitution. That said, you have the table type as Gordon and Larnu mentioned, or you can simply parse/split the delimited string
Just another option
Declare #companyIds varchar(max) = '1,2,3'
Select A.*
From Person A
Join string_split(#companyIds,',') B
on A.CompanyID = B.Value

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

SQL Function within Function

I have a function that gets the recipeid. I am creating another function that shows the average price with recipename. How do I use the first function within the second function?
This is what I have so far. As can be seen, I am using a join for RecipeID, but I want it to use the 1st function I have (let's call it function1) that gets the ID instead. How do I go about this?
CREATE FUNCTION AveragePriceforRecipe() RETURNS #PriceTable TABLE (
[Amount] smallmoney,
[RecipeName] nvarchar(75)) AS
BEGIN
INSERT INTO #PriceTable
SELECT AVG(Amount)
FROM Prices JOIN
RecipePrices ON Prices.PriceID = RecipePrices.PriceID JOIN
Recipes ON RecipePrices.RecipeID = Recipes.RecipeID
END
are you using ms sql server (t-sql)? if so, please try the code below:
given that function1 is:
CREATE FUNCTION function1(#RecipeName)
RETURNS INT
AS
BEGIN
DECLARE #RecipeID INT
SELECT #RecipeID = ID
FROM Recipes
WHERE RecipeName = #RecipeName
RETURN #RecipeID
END
getting the recipes price table using function1:
CREATE FUNCTION AveragePriceforRecipe (#Amount SMALLMONEY, #RecipeName NVARCHAR(75))
RETURNS #PriceTable TABLE
AS
BEGIN
INSERT INTO #PriceTable
SELECT AVG(Amount)
FROM Prices
JOIN RecipePrices ON Prices.PriceID = RecipePrices.PriceID
AND RecipePrices.RecipeID = function1(#RecipeName)
END

Removing ' ' from sql query and stored proc

I have a table in which a column named data is of type varbinary . If I do a simple query
select * from tab where data = 1 then it works but if I do select * from tab where data = '1' then it does not return any row. The issue comes when I create a stored proc to retrieve data from this table and it converts the query and adds ' ' in the parameter when querying and so I am not able to retrieve any data. Can some one please tell me how to get around this issue.
Parameters
#ID INT = NULL
,#Data varchar(100) = NULL
CREATE TABLE #Results (
ID INT
,Data varchar(100)
)
BEGIN
INSERT #Results (
ID
,Data
)
SELECT
SK.ID
,SK.Data
FROM dbo.tab SK
where SK.ID = #ID And SK.data = #data
END
SELECT #TotalRows = COUNT(*)
FROM #Results
SELECT #TotalRows TotalRows
Now from the code when I execute this statement
oReader = ExecuteReader(oConn, CommandType.StoredProcedure, "Proc", New SqlParameter("#ID", Request.ID), _
New SqlParameter("#Data", Request.Data))
I see in SQL Profiler that it runs the query as 'data'
which does not return any rows
Thanks
Since you have said that you have written an SP, I think the inpput parameter is specified as NVARCHAR or VARCHAR
Below is one way of doing but i'm guessing that the column called data will only have integer values in the first solution.
DECLARE #X VARCHAR(5)
SET #X = '1 '
SELECT CAST(#X AS INT)
The above is only if the Data column specified above is Integer.
If the same is string (VARCHAR) you can write a User defined function to do the same.
CREATE FUNCTION dbo.TRIM(#string VARCHAR(8000))
RETURNS VARCHAR(8000)
BEGIN
RETURN LTRIM(RTRIM(#string))
END
SELECT dbo.TRIM('1 ')
I hope the above was useful, I did get the idea rather copied the function from here
http://blog.sqlauthority.com/2007/04/24/sql-server-trim-function-udf-trim/

Table Variable In a table Valued function

I am getting an error when trying to get this table valued function up. I have an error when I try to modify it. It is
Incorrect syntax near the keyword 'Declare'.
However when I use this outside of the function it all works great. So I was just wondering is there something I am missing or how should I be doing this. Thanks.
ALTER FUNCTION [dbo].[XXX]( #i_contactkey int,
#v_scope varchar(15),
#i_entrykey int = null,
#i_staffcontactkey int = null,
#d_startdate datetime,
#d_today datetime)
RETURNS TABLE
AS begin
Declare #temp as table
(contactkey int, contactkey1 int, rolekey1 int,contactkey2 int, rolekey2 int, relationshipid int)
insert into #temp (contactkey , contactkey1 , rolekey1 ,contactkey2 , rolekey2 , relationshipid )
select contactkey , contactkey1 , rolekey1 ,contactkey2 , rolekey2 , relationshipid
from contact clcon
LEFT JOIN contactassociation ca on ca.contactkey2 = clcon.contactkey where ca.rolekey1 in (4,5,6)
and ca.relationshipid = 181
and ca.activeind = 1
and ca.associationkey = (select top 1 associationkey
from contactassociation
where contactkey2 = clcon.contactkey and activeind = 1
and relationshipid = 181
and rolekey1 in (4,5,6)
order by begindate desc)
SELECT
clcon.contactkey'ClientId',
clcon.Stat'ClientStatus',
ctacct.optiondesc'account',
ctlvl.optiondesc'levelid',
(clcon.lastname+', '+clcon.firstname)'ClientName',
clcon.firstname'ClientFirstName',
clcon.lastname'ClientLastName',
clcon.addressline1'address1',
clcon.addressline2'address2',
clcon.city'city',
dbo.getcnfgoption(81,clcon.stateid,'D')'state',
clcon.zipcode'zipcode',
clcon.mainphone'mainphone',
cgcon.contactkey'cgkey',(cgcon.firstname+' '+cgcon.lastname)'CGName',
cgcon.firstname'CGFirstName',
cgcon.lastname'CGLastName',
cgcon.addressline1'cgaddressline1',
cgcon.addressline2'cgaddressline2',
cgcon.city'cgcity',
dbo.getcnfgoption(81,cgcon.stateid,'D')'cgstate',
cgcon.zipcode'cgzipcode',
cgcon.mainphone'cgmainphone',
dbo.getClientAltCGKeys_JSON(clcon.contactkey,'J')'AltCGsJSON',
--dbo.getClientAltCGKeys(clcon.contactkey,'C')'AltCGNames',
--dbo.getClientAltCGKeys(clcon.contactkey,'L')'altcgnamekeyslast',
--dbo.getClientAltCGKeys(clcon.contactkey,'A')'altcgkeysaddress',
dbo.getClientEventCount(clcon.contactkey, 'M', #d_startdate, #d_today) 'MLOA',
dbo.getClientEventCount(clcon.contactkey, 'N', #d_startdate, #d_today) 'NMLOA',
dbo.getClientEventCount(clcon.contactkey, 'A', #d_startdate, #d_today) 'Alts',
dbo.getClientEventCount(clcon.contactkey, 'S', #d_startdate, #d_today ) 'Suspension',
dbo.getClientEventCountAnnual(clcon.contactkey, 'C') 'MissingNotes',
-- dbo.getContactVerificationStatus(clcon.contactkey, 'D')'clverification',
-- dbo.getContactVerificationStatus(cgcon.contactkey, 'D')'cgverification',
ed1.eventkey 'mdskey',
dbo.getCnfgTableOption(54,ed1.eventstatusid,'D')'mdsstatus',
ed1.ScheduledDate 'NextMDS',
ed2.eventkey 'pockey',
dbo.getCnfgTableOption(54,ed2.eventstatusid,'D')'pocstatus',
ed2.ScheduledDate 'NextPoC',
ed3.eventkey 'hvkey',
dbo.getCnfgTableOption(54,ed3.eventstatusid,'D')'hvsstatus',
ed3.ScheduledDate 'NextHV',
ed4.eventkey 'medlistkey',
dbo.getCnfgTableOption(54,ed4.eventstatusid,'D')'medstatus',
ed4.ScheduledDate 'NextMedList',
ed5.eventkey 'semikey',
dbo.getCnfgTableOption(54,ed5.eventstatusid,'D')'semistatus',
ed5.ScheduledDate 'NextSemi',
ed6.eventkey'placementkey',
ed6.startdate'placementstart',
ed6.enddate'placementend',
[dbo].[getClientCMName](clcon.contactkey)'cmname',
[dbo].[getClientRNName](clcon.contactkey)'rnname',
[dbo].[getClientCMKey](clcon.contactkey)'cmkey',
[dbo].[getClientRNKey](clcon.contactkey)'rnkey',
alertcount=(SELECT COUNT(eventalertkey) FROM veventalert WHERE alerttype='Alert' AND clientkey=clcon.contactkey AND viewedind=0 AND contactkey=COALESCE(#i_staffcontactkey,#i_contactkey)),
alertkey=(SELECT MAX(eventalertkey) FROM veventalert WHERE alerttype='Alert' AND clientkey=clcon.contactkey AND viewedind=0 AND contactkey=COALESCE(#i_staffcontactkey,#i_contactkey)),
msgcount=(SELECT COUNT(eventalertkey) FROM veventalert WHERE alerttype='Message' AND clientkey=clcon.contactkey AND viewedind=0 AND cgkey=cgcon.contactkey),
msgkey=(SELECT MAX(eventalertkey) FROM veventalert WHERE alerttype='Message' AND clientkey=clcon.contactkey AND viewedind=0 AND cgkey=cgcon.contactkey),
clcp.birthdate
FROM (select dbo.getcontactstatus(contactkey,'ts')'Stat',* from contact where dbo.getcontactstatus(contactkey,'ts') is not null ) clcon
INNER JOIN contactrole cr
ON (clcon.contactkey = cr.contactkey)
--Find caregiver contact info
LEFT JOIN contactassociation ca on ca.contactkey2 = clcon.contactkey and ca.rolekey1 in (4,5,6)
and ca.relationshipid = 181 and ca.activeind = 1
and ca.associationkey = (select max(associationkey)
from contactassociation
where contactkey2 = clcon.contactkey and activeind = 1
and relationshipid = 181
and rolekey1 in (4,5,6))
LEFT JOIN contact cgcon
ON cgcon.contactkey = ca.contactkey1 and cgcon.activeind = 1
LEFT JOIN contactbu cbu
ON (clcon.contactkey = cbu.contactkey)
/*Account/Lvl Information*/
LEFT JOIN contactprofile clcp
ON (clcon.contactkey=clcp.contactkey)
LEFT JOIN cnfgtableoption ctlvl
ON (clcp.svclevelid = ctlvl.tableoptionkey)
LEFT JOIN cnfgtableoption ctacct
ON (clcp.accountid = ctacct.tableoptionkey)
LEFT JOIN eventdefinition ed1 /* MDS */
ON (clcon.contactkey=ed1.contactkey AND ed1.eventkey=dbo.getContactEventByWftask(clcon.contactkey, 181, 'MINOPEN'))
LEFT JOIN eventdefinition ed2 /* POC */
ON (clcon.contactkey=ed2.contactkey AND ed2.eventkey=dbo.getContactEventByWftask(clcon.contactkey, 120, 'MINOPEN'))
LEFT JOIN eventdefinition ed3 /* HV */
ON (clcon.contactkey=ed3.contactkey AND ed3.eventkey=dbo.getContactEventByWftask(clcon.contactkey, 341, 'MINOPEN'))
LEFT JOIN eventdefinition ed4 /* MED */
ON (clcon.contactkey=ed4.contactkey AND ed4.eventkey=dbo.getContactEventByWftask(clcon.contactkey, 178, 'MINOPEN'))
LEFT JOIN eventdefinition ed5 /* SEMI */
ON (clcon.contactkey=ed5.contactkey AND ed5.eventkey=dbo.getContactEventByWftask(clcon.contactkey, 122, 'MINOPEN'))
LEFT JOIN eventdefinition ed6 /* Placement */
ON (clcon.contactkey=ed6.contactkey AND ed6.wftaskkey = 49
AND ed6.eventstatusid = 16
AND ed6.activeind = 1
AND ed6.enddate = (select MAX(enddate) from eventdefinition
where contactkey = clcon.contactkey and wftaskkey = 49
and activeind = 1
and eventstatusid = 16))
WHERE
--Contact info
cr.rolekey = 8
AND cbu.entrykey = #i_entrykey
--and dbo.getcontactstatus (clcon.contactkey,'TS') not in ('Closed','Discharged')
and clcon.Stat not in ('Closed')
and clcon.activeind=1
-- filter by branch entrykey (if param exists)
--order by clcon.lastname,clcon.firstname
When you're using multiple statements in a function and returning a table, i.e. a Table-Valued User-Defined Function, you need a certain syntax, something like:
CREATE FUNCTION dbo.MyFunction(#ID int)
RETURNS #Mytable TABLE
(
-- Columns returned by the function
ID int PRIMARY KEY NOT NULL,
-- (Other columns as required)
)
AS
BEGIN
--Various statements to populate #Mytable
RETURN; -- Returns #Mytable
END
See Table-Valued User-Defined Functions for more information.
If you have a function that just has RETURNS TABLE with no definition of the table being returned, this is an Inline User-Defined Function.
Inline user-defined functions are a subset of user-defined functions
that return a table data type. Inline functions can be used to achieve
the functionality of parameterized views.
See Inline User-Defined Functions.
The syntax for this is like:
CREATE FUNCTION dbo.MyFunction(#ID int)
RETURNS TABLE
AS
RETURN
(
SELECT *
FROM MyTable
WHERE ID = #ID
);
Here you don't define the table being returned and the body of the function can only be one SELECT statement.
At the moment your code is somewhere between the two; you need to get this to work as the first option, i.e. the Table-Valued User-Defined Function; start by defining the table being returned in the RETURNS clause and go from there.
You have invalid function declaration. When returning table you should specify variable name that will hold your table, so your header may look like:
ALTER FUNCTION [dbo].[XXX](.....)
RETURNS #temp TABLE (contactkey int, contactkey1 int, rolekey1 int,contactkey2 int, rolekey2 int, relationshipid int)
AS
begin
...
You need to define the table's columns in the RETURNS statement.