Linked Table Valued Function Parameters (SQL Server) - sql

I need to create a SQL Server TVF that takes a single param and then used that param to build the other required parameters. Is this even possible?
The error states incorrect syntax near 'LEFT'. Simple representation below.
CREATE FUNCTION TESTFUNCTION
(
-- Add the parameters for the function here
#PRM1 VARCHAR(2) = 'ABC',
#PRM2 VARCHAR(1) = LEFT(#PRM1,1)
)
RETURNS TABLE
AS
RETURN
(
-- Add the SELECT statement with parameter references here
SELECT #PRM2
)
GO
Thank You!

BEFORE EDIT MADE IN THE QUESTION :
You need only one parameters :
SELECT #PRM2 = LEFT(#PRM1, 1);
However, you need scaler function not table valued function :
CREATE FUNCTION TESTFUNCTION
(
-- Add the parameters for the function here
#PRM1 VARCHAR(2) = 'ABC'
)
RETURNS VARCHAR(255)
AS
BEGIN
DECLARE #PRM2 VARCHAR(255)
SET #PRM2 = LEFT(#PRM1, 1)
RETURNS (#PRM2)
END
Note : Your #PRM1 will accept only two characters which are AB. So, define appropriate length.

Related

function in sql

I made a relation of criminal cases in a police station.
CREATE TABLE C_CASE
(
Case_ID int,
Case_Details varchar(255),
Case_Status varchar(255),
Section_Of_Law varchar(255)
);
INSERT INTO C_CASE
VALUES(333,'Hit and Run','Pending','304(A)');
INSERT INTO C_CASE
VALUES(444,'Robbery','Closed','392');
INSERT INTO C_CASE
VALUES(555,'Extortion','Pending','384');
INSERT INTO C_CASE
VALUES(222,'Murder','Closed','302');
I created a function which will return the number of Cases which are pending.
but I get an error. The function is :
create function NumOfCases(#statustype varchar(255)) returns varchar(255)
as
begin
return
(
select count(Case_Status) from C_CASE where Case_Status=#statustype
)
end
QUERY:
select from dbo.NumOfCases('Pending');
I keep getting the error:
Msg 156, Level 15, State 1, Line 21
Incorrect syntax near the keyword 'from'.
Where am I going wrong?
First, you need to change the return type of your function from varchar to integer using RETURNS int as you are trying to return a count.
The way you should call the function from sql is like this
select db.NumOfCases('Pending') as YourCount
You have several issues here. You did not name your column in your function. Then in your query you didn't specify anything to select. Since your query is a scalar function you don't use FROM. I would suggest however that you don't want a scalar function at all . The performance of them is horrible. A inline table valued function would be far better. Something like this.
create function NumOfCases
(
#statustype varchar(255)
) returns table
as
return
select count(Case_Status) as StatusCount
from C_CASE
where Case_Status = #statustype
Then to use this you could do something like this.
Select StatusCount
from NumOfCases('Pending')
You might also consider normalizing the status values. I would suggest using a Status table to hold the text values of your statuses. Then you have just the StatusID in your Case table.
Since it is a count of something use Integer for your return type.
create function NumOfCases(#statustype varchar(255))
returns INT
as
begin
Declare #RtnValue INT;
select #RtnValue = count(Case_Status) from C_CASE where Case_Status=#statustype
return #RtnValue
end

SQL query help - declaration of variables within a function

I'm trying to write a SQL function but an having problems with declaring the variables I need for use in the WHERE clause.
Here's the code:
CREATE FUNCTION fn_getEmployeePolicies(#employeeid smallint)
RETURNS TABLE
AS
DECLARE #empLoc varchar
DECLARE #empBusA varchar
DECLARE #empType varchar
#empLoc = SELECT Location FROM fn_getEmployeeDetails(#employeeid)
#empBusA = SELECT BusinessArea FROM fn_getEmployeeDetails(#employeeid)
#empType = SELECT Type FROM fn_getEmployeeDetails(#employeeid)
RETURN select PolicyId, PolicyGroupBusinessArea.BusinessArea, policysignoff.PolicyGroupLocation.Location, policysignoff.PolicyGroupEmployeeType.EmployeeType
from policysignoff.PolicyGroupPolicy
LEFT JOIN policysignoff.PolicyGroupBusinessArea on policysignoff.PolicyGroupBusinessArea.PolicyGroupId=policysignoff.PolicyGroupPolicy.PolicyGroupId
LEFT JOIN policysignoff.PolicyGroupLocation on policysignoff.PolicyGroupLocation.PolicyGroupId=policysignoff.PolicyGroupPolicy.PolicyGroupId
LEFT JOIN policysignoff.PolicyGroupEmployeeType on policysignoff.PolicyGroupEmployeeType.PolicyGroupId=policysignoff.PolicyGroupPolicy.PolicyGroupId
where BusinessArea = #empBusA
AND EmployeeType = #empType
AND Location = #empLoc
GO
The logic I am trying to build in is:
'given an employeeId, return all "applicable" policies'
An "Applicable" policy is one where the Business Area, Location and EmployeeType match that of the user.
I am trying to use another function (fn_getEmployeeDetails) to return the BusArea, Loc & EmpType for the given user.
Then with the results of that (stored as variables) I can run my select statement to return the policies.
The problem i am having is trying to get the variables declared correctly within the function.
Any help or tips would be appreciated.
Thanks in advance!
Without knowing what your error actually is, I can only say that you're properly not after using varchar as datatype without specifying length.
DECLARE #empLoc varchar will declare a varchar with length 1.
Chances are it should be something like varchar(255) or similar.
Second to set variables you'll either need to use SET and use paranthisis for selects or set it into the statement:
SET #empLoc = (SELECT Location FROM fn_getEmployeeDetails(#employeeid))
or
SELECT #empLoc = Location FROM fn_getEmployeeDetails(#employeeid)
There are subtle differences between these two methods, but for your purpose right now I don't think it's important.
EDIT:
Based on your comment you lack a BEGIN after AS, and an END before GO.
Basically - your function syntax is mixing up "inline" table function with "multi-statement" function.
Such a function "template" should look something like this:
CREATE FUNCTION <Table_Function_Name, sysname, FunctionName>
(
-- Add the parameters for the function here
<#param1, sysname, #p1> <data_type_for_param1, , int>,
<#param2, sysname, #p2> <data_type_for_param2, , char>
)
RETURNS
<#Table_Variable_Name, sysname, #Table_Var> TABLE
(
-- Add the column definitions for the TABLE variable here
<Column_1, sysname, c1> <Data_Type_For_Column1, , int>,
<Column_2, sysname, c2> <Data_Type_For_Column2, , int>
)
AS
BEGIN
-- Fill the table variable with the rows for your result set
RETURN
END
GO
(script taken from sql server management studio)

return 2 columns values from scalar function in sql

Is ther a way were we can return 2 values with one variable in SQL Scalar function
ALTER FUNCTION [report].[fGetKPI] (#metricName AS VARCHAR(50))
RETURNS SMALLINT
AS
BEGIN
DECLARE
#kipId AS SMALLINT,
#metricId as SMALLINT;
SELECT TOP 1 #kipId = [KPI_Id], #metricId = [MetricId] FROM report.[KPIDetails] WHERE [MetricName] = #metricName;
IF (#kipId IS NULL OR #metricId IS NULL)
DECLARE #Error AS INT = dbo.fThrowError('No key found for the component "' + #metricName + '"');
RETURN (select #kipId,#metricId);
END
Scalar functions, by definition, return a single value:
User-defined scalar functions return a single data value of the type defined in the RETURNS clause.
Source: Types of Functions on TechNet
If you want to return more than one value, you should use a table-valued function.
You could also try to somehow pack your two SMALLINT values into one INT or convert them into a string with some separator, but that could get complicated and is not really (in most cases) necessary.
You can re-write the function as :
IF OBJECT_ID('[report].[fGetKPI]') IS NOT NULL
DROP FUNCTION [report].[fGetKPI];
GO
CREATE FUNCTION [report].[fGetKPI] (#metricName AS VARCHAR(50))
RETURNS TABLE
AS
RETURN
SELECT TOP 1 [KPI_Id], [MetricId] FROM report.[KPIDetails] WHERE [MetricName] = #metricName;
Go
and then further use dbo.fThrowError by selecting data from function. Hope this helps!!!

Returning or outputting a #tableVariable in SQL

Is it possible to return or output a #tableVariable in SQL Server?
For example for the following stored procedure, how do I return the #TSV table variable?
ALTER PROCEDURE MyStoredProdecure
#Parameter1 INT,
#Parameter2 INT
AS
BEGIN
DECLARE #TSV TABLE
(
Transition_Set_Variable_ID INT,
Passed BIT
)
INSERT INTO #TSV
{ some data }
END
You cannot do it directly. Table variables are valid for READONLY input.
If you have no other data being returned from the stored procedure, you can select from the #TSV at the end and have the caller capture the output, e.g.
ALTER PROCEDURE MyStoredProdecure
#Parameter1 INT,
#Parameter2 INT
AS
BEGIN
DECLARE #TSV TABLE
(
Transition_Set_Variable_ID INT,
Passed BIT
)
INSERT INTO #TSV
{ some data }
SELECT * FROM #TSV
END
Caller
DECLARE #outerTSV TABLE
(
Transition_Set_Variable_ID INT,
Passed BIT
);
insert into #outerTSV
exec MyStoredProdecure 1, 2;
Alternatively, if the SP is really as simple as you showed, turn it into a table valued function instead.
No, but you can write a table valued function that returns a table.
create function MyTVF
#Parameter1 INT,
#Parameter2 INT
returns #tsv table
(
Transition_Set_Variable_ID INT,
Passed BIT
)
AS
BEGIN
INSERT INTO #TSV
{ some data }
return
END
Table Valued Parameters can only be used for input only, not output.
Depending on what your end goal is, here are some options:
change the sproc to a table-valued function to return a TABLE, that can then be used inline in another statement
simply SELECT the data from the #TSV table var at the end of your sproc
return an XML OUTPUT parameter (get a grubby feeling suggesting this, but just to highlight one way to return multiple rows actually using an OUTPUT parameter)
If you go for a Table Valued Function, ideally create an inline one if it is simple as it looks in your case:
e.g.
CREATE FUNCTION dbo.Func()
RETURNS TABLE
AS
RETURN
(
SELECT Something
FROM Somewhere
WHERE x = 1
)

Using SYSTEM_USER as a parameter to a table valued function

I've created a table valued function:
CREATE FUNCTION TestFunction
(
#username VARCHAR(80)
)
RETURNS TABLE
AS
RETURN
(
SELECT 0 AS TestValue
)
Then try to call it as so:
SELECT TestValue
FROM dbo.TestFunction(SYSTEM_USER)
but get the error:
Incorrect syntax near the keyword 'SYSTEM_USER'
I've even tried making this a table valued function which is not inline, but I get the same error.
Am I missing something? Why am I getting this error?
On my 2k8 server I can only reproduce that with SQL Server 2000 (80) Compatibility level set, check the level of your 2005 database.
Meantime you can;
declare #su varchar(30) = SYSTEM_USER
select * from dbo.TestFunction(#su)