This is my first shot at writing a stored procedure. I'm trying to get a list of all orders placed between two dates. I would run this proc monthly, getting the orders for the trailing 6 months. If I ran it on the 2nd or the 15th of the month, it would still take the previous 6 months from the end of the previous month.
Here's the code:
CREATE PROCEDURE pMonthlyCustomerReport
-- Get the last day of the previous month and the first day of 6 months ago
#enddate date,
#startdate date
AS
SET #enddate = DATEADD(D,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0));
SET #startdate = DATEADD(M, DATEDIFF(MONTH, 0, GETDATE())-6, 0);
-- Get orders for the past 6 months
SELECT acct_num, date as OrderDate, type as OrderType
INTO #Orders
FROM rders
WHERE date BETWEEN #startdate AND #enddate;
When I run the proc, I get this error message:
Procedure or function 'pMonthlyCustomerReport' expects parameter '#enddate', which was not supplied.
Any suggestions or best practices I should be using here? I may be over-thinking creating the #enddate, #startdate and should just put them in the query, but I want the variable to be declared up front.
Any thoughts?
Thanks
You can just declare the vars #startdate and #enddate instead of making them parameters to the sp, since you are setting them based on the current date anyway:
DECLARE #startdate datetime
DECLARE #enddate datetime
then declare it like this:
CREATE PROCEDURE pMonthlyCustomerReport
AS
You have two problems here. The first one is that you are declaring input parameters that you are not supplying values for(which is obviously not your intention). Solution: Put them after the AS and use DECLARE to declare them as local variables.
The second problem is that you are trying to set a value of the declared input parameters. This problem will be solved with the first change.
Put
declare #enddate date
declare #startdate date
after the
AS
so they are not declared as parameters that have to be supplied when calling the procedure.
You are asking for parameters, change #enddate and #startdate to local variables by using declare statements.
Related
I have an SSRS report where a user will choose a date range (2 dropdown). Inside the stored procedure I would like to use this date as passed, but append a specific time on the end of it.
I've been googling for a while and tried many things. But am not an expert and can't seem to land on a working solution
CURRENT CODE:
In my stored procedure, I capture the dates passed in:
ALTER PROCEDURE [dbo].[sp_JollySDKSkillChange]
#in_startdate datetime,
#in_enddate datetime
Then in the where clause ....
where dbo.JollySDKSkillChange.AddedDate between #in_startdate and #in_enddate
I need not only the date, but the start date should include 00:00:00 and the end date should include 23:59:59
How can I concatenate the specific times, onto the end of the date that is passed ?
At the moment, I do not get any results. But executing the stored procedure with a date and time together for each ... it provides the expected results.
You can modify the values after you receive them inside the stored procedure. Your #in_startdate should already be 00:00:00 because you've defined it as datetime, even if you only sent in a date.
ALTER PROCEDURE [dbo].[sp_JollySDKSkillChange]
#in_startdate datetime,
#in_enddate datetime
AS BEGIN
SET NOCOUNT ON;
SET #in_enddate = DATEADD(second,-1,dateadd(day,1,#in_enddate))
--Test values here
SELECT #in_startdate, #in_enddate
...
END
declare #vaultdate varchar(10)
set #vaultdate = convert(date, getdate())-1
print #vaultdate
I got an error
Operand type clash: date is incompatible with int
Can someone see what I have done wrong? Thank you
Presumably, you are using SQL Server. If you want to work with dates, then use dates and their functions:
declare #vaultdate date;
set #vaultdate = dateadd(day, -1, convert(date, getdate()));
print #vaultdate;
I have updated the query, this will give you yyyy-mm-dd format
declare #vaultdate varchar(12)
set #vaultdate = getdate()-1
print CAST(convert(varchar,#vaultdate,20) AS DATE)
You have 1 parenthesis wrong and also you need to declare your variable as datetime. You don't even need convert:
declare #vaultdate datetime
set #vaultdate = getdate()-1
print #vaultdate
Gordon Linoff is totally correct when working with dates use date datatypes. Using correct datatypes is one of the foundations of good SQL design.
If you need to convert the date to a string this should be done at point of use i.e. the presentation layer otherwise you can end up converting the date to a varchar for presentation then the presentation layer converting it to a separate format again because the requirements changed.
If you absolutely have to use a varchar then just add a couple of lines to Gordons very correct answer.
declare #vaultdatestring varchar(10);
declare #vaultdate date;
set #vaultdate = dateadd(day, -1, convert(date, getdate()));
print #vaultdate;
set #vaultdatestring = convert(varchar(10), #vaultdate,103)
print #vaultdatestring;
There is a good resource on date formatting here: Date and Time Conversions Using SQL Server
If you could tell us why the varchar is needed we may be able to provide better suggestions.
I have a simple stored procedure where part of it I want to set 2 variables, 1 for the current time and the other for the current date. I need them in hhmm format for the time and yyyyMMdd format for the date.
Here is the code I have so far:
BEGIN
DECLARE #d AS DATETIME
DECLARE #t as TIME
SET #d = GETDATE()
SET #t = SYSDATETIME()
But everything I've tried to use to change the format of those 2 variables does not help me out. The only examples I've found online is for formatting values in regular queries.
Can anyone point me in the right direction as far as what I should do to get these values? Thanks in advance.
If 2012+ you can use Format()
Example
DECLARE #d as varchar(8) = format(GetDate(),'yyyyMMdd')
DECLARE #t as varchar(4) = format(SYSDATETIME(),'HHmm') -- use hh for 12 hour time
Select #d,#t
Returns
(No column name) (No column name)
20180511 1738
For 2005
DECLARE #d as varchar(8) = convert(varchar(10),GetDate(),112)
DECLARE #t as varchar(8) = replace(left(convert(varchar(25),SYSDATETIME(),108),5),':','')
I am trying to combine a SmallDateTime field and a Time value (result of a scalar-valued function) into a DateTime and I keep getting the following error:
Conversion failed when converting date and/or time from character
string.
Here are the variables used throughout:
DECLARE #STARTDATETIME AS DATETIME
DECLARE #ENDDATETIME AS DATETIME
SELECT #STARTDATETIME = '8/29/2016 12:00:00'
SELECT #ENDDATETIME = '8/30/2016 12:00:00'
Column definitions:
FT_START_DATE SmallDateTime
FT_END_DATE SmallDateTime
FT_START_TIME Int
FT_END_TIME Int
The date fields do not contain timestamps. The time fields are basically 24 hour time without the colon dividers. (Example: 142350 = 14:23:50)
Here's the function that is called in my queries:
USE [PWIN171]
GO
/****** Object: UserDefinedFunction [dbo].[dbo.IPC_Convert_Time] Script Date: 9/13/2016 4:50:49 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[dbo.IPC_Convert_Time]
(
#time int
)
RETURNS time
AS
BEGIN
DECLARE #Result time
SELECT #Result = CONVERT(time
, STUFF(
STUFF(
RIGHT('000000' + CONVERT(varchar(6), #time), 6)
, 5, 0, ':')
, 3, 0, ':')
)
RETURN #Result
END
Example 1 - Fails:
This is what I'm after in general.
SELECT * FROM FT WITH (NOLOCK)
WHERE
CAST(FT_END_DATE AS DATETIME) + DBO.[dbo.IPC_Convert_Time](FT_END_TIME) BETWEEN #STARTDATETIME AND #ENDDATETIME;
Example 2 - Works:
This one runs, but it won't get records from 8/29 because the end dates will be before 12:00:00 on 8/29.
SELECT * FROM FT WITH (NOLOCK)
WHERE
FT_END_DATE BETWEEN #STARTDATETIME AND #ENDDATETIME
AND CAST(FT_END_DATE AS DATETIME) + DBO.[dbo.IPC_Convert_Time](FT_END_TIME) BETWEEN #STARTDATETIME AND #ENDDATETIME;
I suppose I could do one where I split apart my paramters and check that the end time is between the time portion of the parameters as well, but that seems to be a step in the wrong direction. The error seems to only appear when there is no other usage of FT_START_DATE or FT_END_DATE in the where clause.
The time converting function works fine in every scenario I have created. I have even tried Example 2 with parameters that would give it 100% overlap with the data covered by Example 1 in case there was bad data causing the error, but it runs fine.
I also don't know exactly where the error is occurring, because it only references the line the select statement begins on, and not the actual location in the code.
Why does it behave like this?
UPDATE:
TIMEFROMPARTS is not available because this is on SQL Server 2008
If I understand this correctly, this can be done much simpler:
Try this:
DECLARE #d DATE=GETDATE();
DECLARE #t TIME=GETDATE();
SELECT #d;
SELECT #t;
SELECT CAST(#d AS datetime)+CAST(#t AS datetime);
A pure date and a pure time can simply be added to combine them...
UPDATE Read your question again...
Try this
SELECT FT_END_DATE
,FT_END_TIME
,CAST(FT_END_DATE AS DATETIME) + DBO.[dbo.IPC_Convert_Time](FT_END_TIME) AS CombinedTime
,*
FROM FT
to see if your attempt is doing the right thing.
If yes, it might help to create a CTE and do the filter on the named column.
Sometimes the engine does not work the order you would expect this.
As CTEs are fully inlined it is quite possible, that this will not help...
SQL Server is well knwon for bringing up such errors, because a type check happens before a conversion took place...
It might be an idea to use the given SELECT with INTO #tbl to push the result set into a new table and do your logic from there...
I'm not sure what I'm missing here, but when I do something like in a SQL Server 2008 SSMS session like:
declare #start datetime
declare #end datetime
set #start = GetDate()
Update blah blah...a huge amount of rows...;
set #end = GetDate()
When I try to do a datediff of seconds between #start and #end, I get zero.
So I printed #start and #end and they are identical. The query took several minutes. What is going on here?
EDIT--the problem was that the Set #start and Set #end were inside a cursor Open/close block (but not inside the fetch loop) and apparently MS treats those as the exact same time.
Thanks,
Jim
Four your specific use case you may find that Datetime2 and SYSDATETIME() will give you more precision . You can then use the nanoseconds datediff operator.
As an aside you should assume that UPDATE myDate = GETDATE() WHERE "lots of records" and UPDATE myDatefield = SYSDATETIME() during an update process are always going to give you different date values than you expect depending on the phase of the moon and the score of the last Chicago Bears game.
This is because GETDATE() is not deterministic at two different level in the bowels of SQL server.