SQL function as default parameter value? - sql

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.

Related

How can you get the number of parameters

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.

SQL Server: ISNULL on uniqueidentifier

I am trying to compare a column col1 and a variable #myvar in a WHERE clause. Both usually contain GUIDs, but may also have NULL values.
I thought I could get around the fact that NULL=NULL evaluates to FALSE by using WHERE ISNULL(col1, '')=ISNULL(#myvar, ''). That would compare two empty strings instead, and evaluate to TRUE.
This will, however, produce the following error message:
Msg 8169, Level 16, State 2, Line 3 Conversion failed when converting
from a character string to uniqueidentifier.
I tried
DECLARE #myvar uniqueidentifier = NULL
SELECT ISNULL(#myvar,'') as col1
Same error message.
Two questions:
First, I am trying to convert a uniqueidentifier variable - even though it has a NULL value - to an (empty!) string, not the other way around, as the error message suggests. What gives?
Second, is there a better way to word that WHERE clause I need, to allow for comparing uniqueidentifiers that might be NULL?
I think below expression can be used to check if the GUID column is empty
CAST(0x0 AS UNIQUEIDENTIFIER)
some thing like
...WHERE GuidId <> CAST(0x0 AS UNIQUEIDENTIFIER)
Since the first argument you are passing isnull is not a literal null, it will determine the return type of that call, a uniqueidentifier in your case. The second argument, '', cannot be cast to this type, hence the error you're getting.
One way around this is just to explicitly check for nulls:
WHERE (#myvar IS NULL AND col1 IS NULL) OR (col1 = #myvar)
The reason ISNULL isn't working for you is that the replacement value (the value to be used if the check expression really is null) must be implicitly convertible to the type of the check expression.
Your WHERE clause can use a col IS NULL AND #var IS NULL to check that state.
As others have pointed out, exclude the NULL values from the results and THEN do the comparison. You can use COALESCE to exclude NULL values from comparisons.
Try the following code:
WHERE ISNULL([Guid], NEWID()) = #myvar
Here is another way to overcome this issue:
DECLARE #myvar uniqueidentifier = NEWID()
SELECT * FROM TABLE
Where ISNULL(col1,#myvar) = ISNULL(Col2,#myvar)
This will resolve your error. Conversion failed when converting from a character string to uniqueidentifier.
I needed something similar on a where clause to compare 2 fields.
Declaring a uniqueidentifier variable is causing performance issues.
So I've used something like this.
WHERE COALESCE(Table1.Field1, CAST('00000000-0000-0000-0000-000000000000' AS UNIQUEIDENTIFIER))=COALESCE(Table2.Field2, CAST('00000000-0000-0000-0000-000000000000' AS UNIQUEIDENTIFIER))

How to use a default in SELECT query?

I have created a default value like this:
create default [dbo].[MAX_DATE] as '31/12/9999 23:59:59'
Now I would like to return it from a sql query. I tried this:
SELECT
CASE date_field WHEN dbo.MAX_DATE THEN '' ELSE date_field END
FROM
myTable
However, I get the following error:
Server: Msg 107, Level 16, State 2, Line 2
The column prefix 'dbo' does not match with a table name or alias name used in the query.
Defaults are used by binding them to columns. The default value is applied by the server when a row is created and a column value isn't specified. (See: http://msdn.microsoft.com/en-us/library/ms173565.aspx)
Here are 3 options for you:
Option (1)
It looks like you're using a "named constant" for use in doing compares. In this case, you might want to go with a function, such as:
CREATE Function [dbo].[MAX_DATE] ()
Returns Datetime
as
BEGIN
Return '99991231 23:59:59'
END;
GO
select dbo.MAX_DATE()
Option (2)
Another option you might consider is having a table of named constants. It might have the columns: ID (autonumber), ValueName, numValue, strValue, dtValue, binValue. You would populate the ValueName and the appropriate column depending on what type of value you're storing in it.
Option (3)
To use a constant in just your current script, you can declare a value and set it's value and use it in the rest of your script. These variables are out of scope outside of their batch, so either when the script has finished running, or SQL encounters a GO statement. E.g.
DECLARE #MAX_VALUE as datetime
set #MAX_VALUE = '99991231 23:59:59'
select #MAX_VALUE

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: datetime or varchar as parameter datatype for stored procedure

I have a SQL server stored procedure which would accept date as input param to build a query in it.So which datatype i should use for the parameter when defining stored procedure.Whats the difference between using nvarchar(15) and datetime .
1 : create procedure TestProcedure(#startDate datetime)
and
2 : create procedure TestProcedure(#startDate nvarchar(15))
IS there any advantage is i use datetime over varchar in terms of performance
Yes, always use the datetime type. Its more accurate. The datetime type is also always 8 bytes so it is smaller to transfer than 15 characters.
The front end is then responsible for handling cultural/locale issues such as MDY, DMY or YMD component field ordering. (if the database is running under a US locale and the user is in the UK does '3/4/2009' mean April 3 or March 4?)
If you know that only dates will come through the parameter, using the appropriate datatype is better as it's smaller and comparisons can be made quicker. It also prevents invalid values from being supplied.