Executing stored procedure with date attached - sql

Everyday I have to run code that executes a stored procedure. I hard code yesterday's date after it.
EXECUTE sprm_example '2021-03-10'
I tried to do:
EXECUTE sprm_example 'getdate()-1'
EXECUTE sprm_example 'cast(getdate()-1 as date)'
Neither of these work, and it also doesn't work without quotes around it. Any ideas?

SQL Server does not allow expressions in procedure calls but you can use a variable. So:
declare #date date;
select #date = dateadd(day, -1, getdate());
EXECUTE sprm_example #date;

Related

SQL Server 2012 stored procedure runs slow

I have a SQL Server stored procedure and it runs fine on SQL Server 2008 R2.
When I try to run it on SQL Server 2012, it takes very very long time to run.
But if I create local variables inside the stored procedure and copy the values of input parameters into those local variables and use them instead of input parameters, query runs and returns result faster than on SQL Server 2008 R2 database (please note both 2008 R2 and 2012 servers run on the same box).
Could you please shed some light on what is going on here?
By creating local variables and rebinding values you disable parameter sniffing:
Parameter sniffing is the process whereby SQL Server creates an
optimal plan for a stored procedure by using the calling parameters
that are passed the first time a stored procedure is executed
Every subsequent call to the same store procedure with the same parameters will also get an optimal plan, whereas calls with different parameter values may not always get an optimal plan
Run slows:
CREATE PROC [dbo].[DisplayBillingInfo]
#BeginDate DATETIME,
#EndDate DATETIME
AS
BEGIN
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between #StartDate AND #StopDate;
END
Run fast (because it has to calculate new execution plan each time):
CREATE PROC [dbo].[DisplayBillingInfo]
#BeginDate DATETIME,
#EndDate DATETIME
AS
BEGIN
DECLARE #StartDate DATETIME = #BeginDate;
DECLARE #StopDate DATETIME = #EndDate;
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between #StartDate AND #StopDate;
END
The case is SQL Server optimizer cannot reuse cached plan and evaluate it each time.
This is the same as you use WITH RECOMPILE:
CREATE PROC [dbo].[DisplayBillingInfo]
#BeginDate DATETIME,
#EndDate DATETIME
WITH RECOMPILE
AS
BEGIN
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between #StartDate AND #StopDate;
END
using query hint:
CREATE PROC [dbo].[DisplayBillingInfo]
#BeginDate DATETIME,
#EndDate DATETIME
AS
BEGIN
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between #StartDate AND #StopDate
OPTION(RECOMPILE);
-- OPTION (OPTIMIZE FOR (#StartDate UNKNOWN, #StopDate UNKNOWN))
END

sp_executesql vs manually executing gives different results

I'm calling a stored procedure and passing in 2 dates as parameters from my windows application. Its returning all rows rather than 2 rows that I'm expecting.
The stored procedure is:
ALTER procedure [dbo].[Get_Entries]
#Start_Date datetime=null,
#End_Date datetime=null
as
begin
SELECT *
FROM MyTable
WHERE (MyTable.Date BETWEEN #Start_Date AND #End_Date
OR (#Start_Date IS NULL AND #End_Date IS NULL))
ORDER BY MyTable.Date desc
end
The following sp_executesql query returns all rows:
exec sp_executesql N'Get_Entries', N'#Start_Date datetime, #End_Date datetime',
#Start_Date='2015-06-06 11:35:06.437',
#End_Date='2015-07-06 11:35:06.437'
However if I run the stored procedure manually from Management Studio I get the expected 2 rows:
USE [MyDatabase]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[Get_Entries]
#Start_Date = N'2015-06-06 11:35:06.437',
#End_Date = N'2015-07-06 11:35:06.437'
SELECT 'Return Value' = #return_value
GO
Any ideas why sp_executesql isn't returning the filtered list? Its returning all rows.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
My recommendation for SQL Server 2008 and newer is to use DATE if you only need the date portion, and DATETIME2(n) when you need both date and time. You should try to start phasing out the DATETIME datatype if ever possible
In your case values are not passed to stored procedure and it runs with default values.
If you remove the default values in your stored procedure you will get following error:
Procedure or function 'Get_Entries' expects parameter '#Start_Date', which was not supplied.
sp_executesql is used to make a code reusable. Using sp_executesql to execute stored procedure gives no benefit.
sp_executesql executes a Transact-SQL statement or batch that can be
reused many times, or that has been built dynamically.
You can find a way around using code given below
Declare #statement nvarchar(max)
set #statement = N'Get_Entries ''2010-06-06 11:35:06.437'', ''2015-07-06 11:35:06.437'''
exec sp_executesql #statement
Let's take a look at your sp_executesql statement:
exec sp_executesql N'Get_Entries',
N'#Start_Date datetime, #End_Date datetime',
#Start_Date='2015-06-06 11:35:06.437',
#End_Date='2015-07-06 11:35:06.437'
This query tells SQL Server to execute the following query:
'Get_Entries'
The way you are invoking sp_executesql says the query uses the following parameters:
'#Start_Date datetime,#End_Date datetime'
However, the query text string 'Get_Entries' does not use these parameters. Therefore, SQL Server will not put the parameters into the query. The result query is equivalent to the following code:
exec Get_Entries
Without specifying any parameters, your stored procedure will return all rows.
To use the parameters, you need to place them in your dynamic SQL query like below. I renamed the dynamic SQL parameters to make it clearer where they are used in the query:
exec sp_executesql N'Get_Entries #Start_Date = #StartDateParm, #End_Date = #EndDateParm',
N'#StartDateParm datetime, #EndDateParm datetime',
#StartDateParm='2015-06-06 11:35:06.437',
#EndDateParm='2015-07-06 11:35:06.437'
Note that you don't need to put a stored procedure call in a call to sp_executesql. It is more efficient to call the procedure directly.

Datediff Stored Procedure?

declare #Date nvarchar(200)
set #Date=GetDate()
execute #Date
SELECT LName,DATEDIFF(yy,DOB,#Date) AS DiffDate
from Employees
the code actually works and shows the current age of the employes, but in messages it says "Could not find stored procedure 'Feb 9 2015 6:06PM'"
Is there something i should do?
Why you are doing execute #Date ? that is why you are getting the error. EXECUTE is use for executing a procedure.
Just remove that, and the error will go away.
See: EXECUTE (Transact-SQL)
Since your #Date holds Feb 9 2015 6:06PM and execute #Date tries to find a proc with this name and hence the error.

SQL stored procedure that needs to execute based on look up table value

I have a SQL stored procedure that needs to execute only if lookup table value has today's date.
If not then it should run again after 30 minutes with the same criteria.
How can I do that?
Look up table has just one date row value = '12-14-2012'. It will be change by another process.
Something like this can do it for you. Note this code will not execute, you will need to replace items with your values.
DECLARE #Today DATE
SET #Today = GETDATE()
IF EXISTS (SELECT 'x' FROM MyTable WHERE CAST(ColumnName as DATE) = #Today)
BEGIN
EXEC Sproc Here
END
At a high level, you can use SQL Server agent to schedule the proc. To decide whether or not to run you can put something like this in the proc
IF EXISTS(SELECT * FROM LOOKUP WHERE colname = convert(varchar, getdate(), 110))
BEGIN
--do stuff
END

Issue with exec statement

When I am trying to carry out following statement from Management Studio, it is executed successfully -
exec [sp_GetAllBillsForDate] '03/06/2012','03/06/2012'
But when I change it to
exec [sp_GetAllBillsForDate] getdate(), getdate()
it is generating error
Incorrect syntax near ')'.
whats wrong with this?
Thanks for sharing your time.
The answer is that you can't pass a function as an argument to a stored procedure parameter.
If you just want to use the current date/time when you don't want to pass values in, why not make those parameters optional by supplying a default value inside the procedure? This will save you from having to type it, declare local variables, and even more importantly from passing those useless tokens from client applications.
You should also avoid ambiguous date formats like m/d/y and d/m/y. If it wasn't March right now, I'd have no idea whether you meant March 6 or June 3. And when you run your code somewhere with different regional or language settings, SQL Server might get it wrong too. State it unambiguously in a clear format (e.g. YYYYMMDD) immune to language, region or human perception issues.
Anyway here is the procedure with optional parameters:
ALTER PROCEDURE dbo.sp_GetAllBillsForDate -- sp_ is a horrible prefix, by the way *
#date1 DATETIME = GETDATE(),
#date2 DATETIME = GETDATE()
AS
BEGIN
SET NOCOUNT ON;
...
END
GO
Now the code for a hard-coded date:
EXEC dbo.sp_GetAllBillsForDate #date1 = '20120306', #date2 = '20120306';
And to get todays:
EXEC dbo.sp_GetAllBillsForDate;
(Also a good idea to explicitly name your parameters. Then you don't have to worry about the parameter order changing. And also to always use the schema prefix when referencing or creating all objects.)
http://www.sqlmag.com/article/tsql3/should-i-use-the-sp_-prefix-for-procedure-names-
Try to pass through variable..
DECLARE #date1 DATETIME
,#date2 DATETIME
SELECT #date1 = GETDATE()
,#date2 = GETDATE()
EXEC [sp_GetAllBillsForDate] #date1, #date2