Error message Conversion failed when converting datetime from character string - sql

ALTER PROCEDURE [dbo].[TEST_01]
(
#StartDate DateTime,
#EndDate DateTime
)
AS
BEGIN
SET NOCOUNT ON;
Declare #sql as nvarchar(MAX);
SET #sql = #sql + ';WITH CTE_ItemDetails
MAX(D.Name) as Name,
SUM(ISNULL(DT.col1, 0)) AS col1,
SUM(ISNULL(DT.col2, 0)) AS col2,
SUM(ISNULL(DT.col3, 0)) AS col3,
GROUPING(D.ItemType) AS ItemTypeGrouping
FROM Items D
INNER JOIN Details DT ON DT.ItemId = D.ItemId
INNER JOIN Report R ON R.ReportId = DT.ReportId
where 1=1'
SET #sql = #sql + ' AND (R.ReportDate >= ' + #StartDate + 'AND R.ReportDate <=' + #EndDate +')'
IF #someOtherVariable is not null
SET #sql = #sql + ' AND R.someColumn IN (''' +replace(#someOtherVariableValues,',','')+''+')'
SET #sql = #sql + 'SELECT col1, col2, col3 FROM CTE_ItemDetails'
EXECUTE (#sql)
END
I have a stored procedure that is similar to the T-SQL code above.
(Note that i have removed lots of code that i feel isn't relevant to the error i'm getting)
I'm getting the below error when i execute it.
Conversion failed when converting datetime from character string.
My parameters have values in below format
exec TEST_01 #StartDate=N'4/1/2016 12:00:00 AM',#EndDate=N'4/30/2016 12:00:00 AM'
It looks like the trouble is in the way i'm dynamically setting the SQL statement at line below
SET #sql = #sql + ' AND (R.ReportDate >= ' + #StartDate + 'AND R.ReportDate <=' + #EndDate +')'
What is the best date formatting i can apply to avoid the error.

You should use parameters via sp_executesql.
But your immediate problem is this line:
SET #sql = #sql + ' AND (R.ReportDate >= ' + #StartDate + 'AND R.ReportDate <=' + #EndDate +')'
It should look more like:
SET #sql = #sql + ' AND (R.ReportDate >= ''' + convert(varchar(10), #StartDate, 121) + ''' AND R.ReportDate <= ''' + convert(varchar(10), #EndDate, 121) +''')' ;
Note the inclusion of explicit type casting to a string and the double single quotes so the date literal is not interpreted as 2016 - 04 - 14 (i.e. 2000).
The better method of using parameters looks like:
SET #sql = #sql + ' AND (R.ReportDate >= #StartDate AND R.ReportDate <= #EndDate)' ;
. . .
exec sp_executesql #sql, N'#StartDate date, #EndDate date)', #StartDate = #StartDate, #EndDate = #EndDate;
It is easier to read the SQL statement. The type issues are handled through parameters. And, the query plan is more readily stashed. Unfortunately, parameters only work for constants, not for column or table names, for instance.

Related

Dynamic query and use of variables

The query below works if the 2 dates are hard coded, however, I would like to replace them with the 2 variables #FirstDayM and #LastDayM.
When I do so, it returns the following error
"Conversion failed when converting date and/or time from character string"
DECLARE #sql varchar(max)
DECLARE #FirstDayM DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0)
DECLARE #LastDayM DATE = DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1);
SELECT #sql = Coalesce(#sql + ' UNION ALL ', '') + 'SELECT COUNT(C1CustID) AS CertsCount, ''' + QuoteName(name)+ ''' as DBname FROM ' + QuoteName(name) + '.dbo.T_C1CustCourse'+
' WHERE C1CertificationDate_N >= '+'''2018-01-01'''+' AND C1CertificationDate_N <= '+'''2018-01-31'''
FROM sys.databases WHERE database_id > 4 AND state = 0;
EXEC (#sql);
Use sp_executesql. Always. It makes it easy to put parameters into queries. Even if the dynamic query does not start with the parameter, you might decide to add one later.
declare #sql nvarchar(max);
declare #firstDayM date;
declare #lastDayM date;
set #firstDayM = ?;
set #lastDayM = ?;
SELECT #sql = Coalesce(#sql + ' UNION ALL ', '') + '
SELECT COUNT(C1CustID) AS CertsCount, ''' + QuoteName(name)+ ''' as
DBname
FROM ' + QuoteName(name) + '.dbo.T_C1CustCourse' + '
WHERE C1CertificationDate_N >= #FirstDayM AND C1CertificationDate_N
<= #LastDayM'
FROM sys.databases
WHERE database_id > 4 AND state = 0;
EXEC sp_executesql #sql, N'#FirstDayM date, #lastDayM date',
#FirstDayM=#FirstDayM, #lastDayM=#lastDayM;

concatenate datetime with string

i am getting an error when trying to concatenate date and string.
declare #select varchar(max)
declare #where varchar(max)
set #select = 'select * from tbl Emp........'
#where = ' where Emp.date >='+ cast((cast(getdate() as date)) as varchar(20))
exec(#select+#where)
I also tried to do like below but didn't work:
declare #today varchar(20)
#today = cast((cast(getdate() as date))
#where = 'where Emp.date> =' + '#today'
Try something like this...
declare #select varchar(max)
declare #where varchar(max)
set #select = 'select * from tbl Emp '
set #where = ' where Emp.date >= ''' + CONVERT(varchar(8),getdate(),112) + ''''
exec(#select+#where)
Or an even better option would be something like this.....
DECLARE #Sql nvarchar(max);
DECLARE #Date DATE = GETDATE();
SET #Sql = N' select * from tbl Emp '
+ N' where Emp.date >= #Date'
Exec sp_executesql #Sql
,N'#Date DATE'
,#Date
But why do you even need dynamic sql for this simple query why cant you simply do
DECLARE #Date DATE = GETDATE();
select * from tbl Emp
where Emp.date >= #Date

Concatenate Date in sql Dynamic query

I am trying to execute a dynamic query in which I am concatenating a date but failed in doing
DECLARE #pStartDate datetime
DECLARE #pEndDate datetime
DECLARE #query nvarchar(MAX)
Dynamic query1
set #query = 'Select * from Table1 From tblEvent
Where (EventDate Between' + #pStartDate + ' and ' + #pEndDate +')'
Exec(#query)
Error
Conversion failed when converting date and/or time from character string.
Dynamic query2
set #query = 'Select * from Table1 From tblEvent
Where (EventDate Between' + cast(#pStartDate as varchar) + ' and ' + cast(#pEndDate as varchar) +')'
Exec(#query)
Error
Incorrect syntax near 1 [1 stands for whatever date I passed to #pStartDate]
Please suggest me how to do it.
Thanks.
The really proper way to do this would be to use a parametrized query and having sp_executeSql execute this:
DECLARE #pStartDate datetime
DECLARE #pEndDate datetime
DECLARE #query nvarchar(MAX)
SET #pStartDate = '20080301'
SET #pEndDate = '20080331'
-- if you're setting a NVARCHAR variable - **DO USE** the N'..' prefix!
SET #query = N'SELECT * FROM dbo.Table1
WHERE OrderDate BETWEEN #StartDate AND #EndDate'
-- execute the dynamic SQL, with a list of parameters, and their values
EXEC sp_executesql #query,
N'#StartDate DATETIME, #EndDate DATETIME',
#StartDate = #pStartDate, #EndDate = #pEndDate
In that case, there's no fiddling around with string concatenation and missing quotes and messy stuff like that - just a clear, properly parametrized query that isn't vulnerable to SQL injection attacks, and that performs much better since it's execution plan can be reused for subsequent executions.
Add single quote.
Because date or string specify in single quote like this '12-01-2014'.
set #query = 'Select * from Table1 From tblEvent
Where (EventDate Between''' + #pStartDate + ''' and ''' + #pEndDate +''')'

comparing datetime variables

How do I compare datetime variable passed to the store procedure with datetime variable in the table.
e.g. In my where clause #paramDate value is 2/10/2012
set sql = 'WHERE product.RegisteredDate >= ' + #paramDate
when I exec(#sql)
it fails, Error:
Conversion failed when converting datetime from character string.
Thx
SET #sql = '... WHERE product.RegisteredDate >= '''
+ CONVERT(CHAR(8), #paramDate, 112) + ''';';
If #ParamDate is NULL you can probably do this:
SET #sql = 'SELECT ...';
SET #sql = #sql + COALESCE(' WHERE product.RegisteredDate >= '''
+ CONVERT(CHAR(8), #paramDate, 112) + ''';', '');
Or even:
SET #sql = 'SELECT ...';
IF #paramDate IS NOT NULL
BEGIN
SET #sql = #sql + '... WHERE product.RegisteredDate >= '''
+ CONVERT(CHAR(8), #paramDate, 112) + ''';';
END
Try this:
CONVERT(varchar, #paramDate, 101)
See here for more information:
http://msdn.microsoft.com/en-us/library/ms187928.aspx
Since you're trying to execute a dynamic query, you could use sp_executesql instead of exec so that you can use parameters in your generated query. Here are the details for sp_executesql.
For example:
set #sql = 'WHERE product.RegisteredDate >= #dynamicParm'
EXECUTE sp_executesql #sql, N'#dynamicParm DATETIME', #dynamicParm = #paramDate

Unable to inject smalldatetime into D-SQL statement

when i try to execute this sql statement i am getting the error.. Conversion failed when converting character string to smalldatetime data type.
Does anyone know what i am doing wrong?
declare #modality varchar(50)
declare #datefrom smalldatetime
set #modality = 'xxxxxxx'
set #datefrom = '20090101'
declare #var1 nvarchar(4000)
select #var1 =
'select
sum('+ #modality +') as ' + dbo.fnc_titlecase(#modality) +'
from dbo.vw_RawData
where vw.date >= ' + #datefrom + ''
exec sp_executesql #var1
You are trying to concatenate the smalldatetime with a varchar.
Change
Solution 1
declare #datefrom smalldatetime
to
declare #datefrom varchar(8)
and
select #var1 = 'select sum('+ #modality +') as ' + dbo.fnc_titlecase(#modality) +
' from dbo.vw_RawData where vw.date >= ' + #datefrom + ''
to
select #var1 = 'select sum('+ #modality +') as ' + dbo.fnc_titlecase(#modality) +
' from dbo.vw_RawData where vw.date >= ''' + #datefrom + ''''
Solution 2
change
select #var1 = 'select sum('+ #modality +') as ' + dbo.fnc_titlecase(#modality) +
' from dbo.vw_RawData where vw.date >= ' + #datefrom + ''
to
select #var1 = 'select sum('+ #modality +') as ' + dbo.fnc_titlecase(#modality) +
' from dbo.vw_RawData where vw.date >= ''' + convert(varchar(10), #datefrom, 121) + ''''
In the statement select #var1 = 'select sum('+ #modality +') as ' + dbo.fnc_titlecase(#modality) +' from dbo.vw_RawData where vw.date >= ' + #datefrom + '' SQL Server is trying to do date arithmetic by casting all the surrounding strings to a smalldatetime instead of converting #datefrom to a string and performing string concatenation.
Possible fixes.
Change #DateFrom to a sting so that
the concatenation works. Note you
will have to add some quotes so that
the string in #Var1 is properly
formated.
Use convert function to convert #datefrom to a string. Look up the right conversion number in Books online. I don't have time to right now. Don't use cast, it won't give a
Use a paramertized SQL String. Look up sp_executesql in Books Online. (Or wait, StackOverflow always has someone to point out how to avoid dynamic SQL.)
EDIT: Just checked. cast(#DateTime as Varchar(...)) gives a string that I thought might be hard to parse, but it seems to work, might try that instead of convert. Make sure the varchar() is big enough