How can you get the number of parameters - sql

How can i get the number of parameters that weree given to a MS SQL function or stored procedure?
Lets say mu function is:
CREATE FUNCTION dbo.tst
(
#idINT ,
#StartDate DATETIME ,
#EndDate DATETIME
)
...
When i call the function using SELECT dbo.tst(1, '2015-11-11 23:14:45') is there a way to determine that the function was called with only two parameters?
Edit:
Idealy I would like to have a funtion/sp that can coop with an unknow number of parameters, but as far as I know this is not possible.
The idea was to create a funtion with lets say 20 params and discover (count) the number of params passed into the function, so we can process only the values that were actually given to the funtion.
The bigger picture is implementing a hash funtion voor Data Vault 2.0 to create a hash value per record to discover changes. Since every table has a different number of fields, this can be chalanging. You do not want to create a funtion per table...
I hope this makes sense.

First of all with function like:
CREATE FUNCTION dbo.tst(
#idINT ,
#StartDate DATETIME ,
#EndDate DATETIME)
SELECT dbo.tst(1, '2015-11-11 23:14:45')
You will get:
error An insufficient number of arguments were supplied for the
procedure or function dbo.tst.
One way is to add default parameter value like:
CREATE FUNCTION dbo.tst(
#id INT,
#StartDate DATETIME = NULL,
#EndDate DATETIME = NULL)
but still you need to call it as:
SELECT dbo.tst(1, '2015-11-11 23:14:45', default)
with scalar function you can call it as:
EXECUTE dbo.tst 1, '2015-11-11 23:14:45'
I guess you want something like overloaded function in other programming languages. With functions you always need to specify all parameters.
With stored procedures you can use:
CREATE PROCEDURE dbo.tst(
#idINT ,
#StartDate DATETIME = NULL,
#EndDate DATETIME = NULL)
AS
BEGIN
IF #StartDate IS NULL
-- user does not provide start date use default or do some operations
-- SET #StartDate = ...
...
IF #EndDate IS NULL
...
END;
Then you can reason about it:
EXEC dbo.tst 1, NULL, NULL
will be the same as:
EXEC dbo.tst 1
More info: CREATE FUNCTION:
When a parameter of the function has a default value, the keyword
DEFAULT must be specified when the function is called to retrieve the
default value. This behavior is different from using parameters with
default values in stored procedures in which omitting the parameter
also implies the default value. However, the DEFAULT keyword is not
required when invoking a scalar function by using the EXECUTE
statement.

Related

Linked Table Valued Function Parameters (SQL Server)

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.

How to insert NULL into the DATETIME coulmn instead 1900-01-01 00:00:00.000 in SQL Server

I am new to SQL Server here I am trying to insert date into the column which has DATETIME as datatype .
When I pass a datetime to the stored procedure from API it insert the values which I have passed. But If I pass an empty string " ", it inserts a default value of 1900-01-01 00:00:00.000. But I want to insert NULL if the data is " ".
I googled a lot but I can't find a solution for this .
#DATEVAL1 DATETIME = '',
#DATEVAL1 DATETIME = ''
INSERT INTO TABLE (mDate1, mDate2)
VALUES (#DATEVAL1, #DATEVAL2);
This is the code I have in my stored procedure.
When you set a datetime variable to an empty string an implicit conversion happens. And an empty string converts implicitly to 1900-01-01. Either just declare the variable and don't assign them a value or explicitly set them to NULL.
#DATEVAL1 DATETIME,
#DATEVAL2 DATETIME = NULL
Or you could use NULLIF. Since you are receiving these values from an API you would most likely have to use NULLIF. Otherwise a change to the API call would be required to send in a NULL instead of an empty string.
Values( NULLIF(#DATEVAL1, '')
Dates and strings are not the same thing. For some reason, SQL Server converts an empty string into the date value '1900-01-01 00:00:00.000' rather than generating an error.
My primary advice is to not use empty strings for dates. Instead, just use NULL:
DECLARE #DATEVAL1 DATETIME = NULL;
DECLARE #DATEVAL1 DATETIME = NULL;
INSERT INTO TABLE (mDate1, mDate2)
VALUES (#DATEVAL1, #DATEVAL2);
If for some reason you have to use empty strings, then you can use a trigger to convert the 1900 value to NULL or use NULLIF() in the INSERT:
INSERT INTO TABLE (mDate1, mDate2)
VALUES (NULLIF(#DATEVAL1, ''), NULLIF(#DATEVAL2, ''));
I will go on a different direction as the other two answers.
My guess is you have an APP with some dropdown combos or some text fields. Your APP call your API and then you send those values to the stored procedure. Sometimes the app send empty string and when you send those to the stored procedure are converted to 1900-01-01.
So if you have the following stored procedure:
CREATE PROCEDURE dbo.InsertDate
#DATEVAL1 DATETIME, #DATEVAL1 DATETIME
AS
INSERT INTO TABLE (mDate1, mDate2)
VALUES (#DATEVAL1, #DATEVAL2);
GO
In this case if you send '' to the stored procedure you will get 1900-01-01 at the moment the parameters are created because an implicit conversion occurs so NULLIF() won't work here.
You can add some IF () logic to the stored procedure to convert any 1900-01-01 to NULL before run the INSERT
Or you can add the logic to your API converting any '' to NULL before calling the stored procedure.

SQL Server: user defined function parameter

I was wondering if it is possible to create a user-defined function that can take a parameter of varying length (as well as other parameters).
Essentially I want to pass a parameter that then gets used in an IN statement. What I would like to do is have something like this:
CREATE FUNCTION ufnGetOpenNotificationValue
(#LegacyTypeID INT,
#MonthEnd DATE,
#YearStart DATE,
#YearEnd DATE)
Where #LegacyTypeID is a list of integers.
So then using the function might look something like this
SELECT RE_Auxiliary.dbo.ufnGetOpenNotificationValue
((1,2,3),'2014-07-31','2013-09-01','2014-08-31')
rather than
SELECT RE_Auxiliary.dbo.ufnGetOpenNotificationValue
(1,'2014-07-31','2013-09-01','2014-08-31') +
RE_Auxiliary.dbo.ufnGetOpenNotificationValue
(2,'2014-07-31','2013-09-01','2014-08-31') +
RE_Auxiliary.dbo.ufnGetOpenNotificationValue
(3,'2014-07-31','2013-09-01','2014-08-31')
but if I try and pass multiple integers I get an error stating
Incorrect syntax near ','
As Alex K states you can't pass arrays as an input for a SQL function. You can pass table types (Pass table as parameter).
CREATE TYPE TableType
AS TABLE (LegacyTypeID INT)
CREATE FUNCTION ufnGetOpenNotificationValue
(#LegacyTypeID TableType,
#MonthEnd DATE,
#YearStart DATE,
#YearEnd DATE)
...
WHERE COLUMN_NAME IN (SELECT LegacyType FROM #LegacyTypeID)
You would then need to insert into a TableType variable before calling your function with that variable passed as a parameter
Another option would be to pass in your list in as a comma separated list of values. And then use a function (like this one) to use in your where clause
CREATE FUNCTION ufnGetOpenNotificationValue
(#LegacyTypeID NVARCHAR(256),
#MonthEnd DATE,
#YearStart DATE,
#YearEnd DATE)
...
WHERE COLUMN_NAME in (SELECT val FROM dbo.f_split(#StringParameter, ','))
Which you could then call like this:
SELECT RE_Auxiliary.dbo.ufnGetOpenNotificationValue
('1,2,3','2014-07-31','2013-09-01','2014-08-31')

Alter a SQL server function to accept new optional parameter

I already have a function in SQL Server 2005 as:
ALTER function [dbo].[fCalculateEstimateDate] (#vWorkOrderID numeric)
Returns varchar(100) AS
Begin
<Function Body>
End
I want to modify this function to accept addition optional parameter #ToDate. I am going to add logic in function if #Todate Provided then do something else continue with existing code.
I modified the function as:
ALTER function [dbo].[fCalculateEstimateDate] (#vWorkOrderID numeric,#ToDate DateTime=null)
Returns varchar(100) AS
Begin
<Function Body>
End
Now I can call function as:
SELECT dbo.fCalculateEstimateDate(647,GETDATE())
But it gives error on following call:
SELECT dbo.fCalculateEstimateDate(647)
as
An insufficient number of arguments were supplied for the procedure or
function dbo.fCalculateEstimateDate.
which as per my understanding should not happen.
Am I missing anything?
From CREATE FUNCTION:
When a parameter of the function has a default value, the keyword DEFAULT must be specified when the function is called to retrieve the default value. This behavior is different from using parameters with default values in stored procedures in which omitting the parameter also implies the default value.
So you need to do:
SELECT dbo.fCalculateEstimateDate(647,DEFAULT)
The way to keep SELECT dbo.fCalculateEstimateDate(647) call working is:
ALTER function [dbo].[fCalculateEstimateDate] (#vWorkOrderID numeric)
Returns varchar(100) AS
Declare #Result varchar(100)
SELECT #Result = [dbo].[fCalculateEstimateDate_v2] (#vWorkOrderID,DEFAULT)
Return #Result
Begin
End
CREATE function [dbo].[fCalculateEstimateDate_v2] (#vWorkOrderID numeric,#ToDate DateTime=null)
Returns varchar(100) AS
Begin
<Function Body>
End
I have found the EXECUTE command as suggested here T-SQL - function with default parameters to work well. With this approach there is no 'DEFAULT' needed when calling the function, you just omit the parameter as you would with a stored procedure.

SQL function as default parameter value?

I tried changing a default parameter value with this:
ALTER PROCEDURE [dbo].[my_sp]
#currentDate datetime = GETDATE()
and all the SQL pre-compiler gave me was this error:
Msg 102, Level 15, State 1, Procedure my_sp, Line 8 Incorrect syntax near '('.
I have already created the procedure. (I'm not sure if that's relevant.) I was using a null default value and checking for that later, but that doesn't seem proper. Can I do this in one line?
Update: I was going off of MSDN's description of stored procedure parameters:
[ = default ] Is a default value for the parameter. If a default value is defined, the function can be executed without specifying a value for that parameter.
Note:
Default parameter values can be specified for CLR functions except for the varchar(max) and varbinary(max) data types.
When a parameter of the function has a default value, the keyword DEFAULT must be specified when the function is called to retrieve the default value. This behavior is different from using parameters with default values in stored procedures in which omitting the parameter also implies the default value.
Am I reading this wrong?
Many thanks.
Default value for stored procedures parameter have to be constants.
You'd need to do the following...
ALTER Procedure [dbo].[my_sp]
#currentDate datetime = null
AS
IF #currentDate is null
SET #currentDate = getdate()
I don't think that is possible, you have to use a literal (constant) value as the default.
However you can do this:
Set #currentDate = Coalesce(#currentDate , GetDate())
You can try as follow:
Set #CurrentDate=IsNull(#CurrentDate,GetDate())
I infer you're using Microsoft SQL Server from the square brackets in your example.
From MSDN:
Only a constant value, such as a
character string; a scalar function
(either a system, user-defined, or CLR
function); or NULL can be used as a
default.
The function GETDATE() returns a different value from time to time, so it is not a constant expression.
That value is not deterministic and cannot be used
Suggestion:
Set the default to NULL
Do the Default GETDATE() in the front end.