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 +''')'
Related
I am trying to write a query inside a stored procedure where I would like the comparison operator to be a variable.
For instance, here is my SQL query:
DECLARE #DueDate dateTime = '2019-11-29'
DECLARE #DueDateOperator varchar = '>'
SELECT *
FROM someTable
WHERE dueDate [#DueDateOperator] #DueDate --This doesn't work
Is it possible to put a comparison operator in a variable? If not, how can I write this query better such that I can parameterize the comparison operator to anything such as = or < or <= or >=?
Thanks in advance.
Your code looks like SQL Server. First, avoid declaring variables with no length. This is a bug waiting to happen:
DECLARE #DueDateOperator varchar = '>';
For fun, you can ponder what the result will be if you use '<>' or `!='. Always use a length:
DECLARE #DueDateOperator varchar(32) = '>';
Then, the safest way to handle this would be boolean expressions
SELECT *
FROM someTable
WHERE (DueDateOperator = '=' AND dueDate = #DueDate) OR
(DueDateOperator = '<>' AND dueDate <> #DueDate) OR
(DueDateOperator = '<' AND dueDate < #DueDate) OR
(DueDateOperator = '<=' AND dueDate <= #DueDate) OR
(DueDateOperator = '>' AND dueDate > #DueDate) OR
(DueDateOperator = '>=' AND dueDate >= #DueDate) ;
This prevents any form of SQL injection.
Finally, you can only replace constant values in a string using parameters. If you want to replace an operator (or keyword or function name or table name and so forth), you have to munge the query string. This is unsafe, because it can open the way to SQL injection attacks. But the method would be:
declare #DueDate dateTime = '2019-11-29';
declare #DueDateOperator varchar(32) = '>';
DECLARE #sql nvarchar(max) = '
select *
from sometable
where dueDate #DueDateOperator #DueDate';
set #sql = replace(#sql, '#DueDateOperator', #DueDateOperator);
exec sp_executesql #sql,
N'#DueDate datetime',
#DueDate #DueDate;
Although you cannot pass the operator in as a parameter in dynamic SQL, you can pass the constant value. This uses sp_executesql which allows the passing of parameters.
You can use dynamic SQL as below:
DECLARE #DueDate dateTime = '2019-11-29'
DECLARE #DueDateOperator varchar = '>'
DECLARE #Cmd NVARCHAR(4000) = 'SELECT * FROM someTable WHERE dueDate ' + #DueDateOperator + '''' + CONVERT( NVARCHAR(10), #DueDate , 23) + ''''
SELECT #Cmd
EXECUTE(#Cmd)
It is possible, try this:
Declare #DueDate dateTime = '2019-11-29'
Declare #DueDateOperator varchar = '>'
Declare #sql Nvarchar(MAX) = ''
Set #sql = 'Select * from someTable where dueDate ' + #DueDateOperator + ' '''+ convert(varchar, #DueDate, 23) + ''' '
EXECUTE (#sql )
--print ( #sql)
I have a very simple dynamic SQL query that specifically needs to be called using sp_executesql with parameters. This query works fine in regular dynamic SQL, but fails when using sp_executesql on a conversion error.
I have tried many combinations of dynamic SQL, but none of them seem to work specifically for datetime conversions related to sp_executesql.
declare
#sql_nvarchar nvarchar(max),
#datetime datetime = GETDATE(),
#sqlparams nvarchar(max),
#tablename nvarchar(max) = 'SomeTableName'
Set #sql_nvarchar =
N'
Select *
from ' + #tablename + '
where Date > ''' + convert(nvarchar(23), #datetime, 101) + ''' '
Set #sqlparams =
N'
#datetime datetime,
#tablename nvarchar(max)
'
EXEC(#sql_nvarchar)
EXEC [sp_executesql] #sql_nvarchar,#sqlparams, #datetime, #tablename
The first exec correctly returns the desired query, the second EXEC throws an error: 'Error converting data type nvarchar(max) to datetime.'
You cannot parameterize an identifier, such as a table name. So, phrase this as:
Set #sql_nvarchar = N'
Select *
from ' + #tablename + '
where Date > #datetime
';
Set #sqlparams = N'#datetime datetime'
exec sp_executesql #sql_nvarchar, #sqlparams,
#datetime=#datetime
I need to have a sp with dynamic query like this,
declare #query nvarchar(max)='
declare #DateParam datetime
set #DateParam=getdate()
select * from tblOrders
where Order_site='TSN'
AND CAST(ORDER_APPROVED_DATE_LT AS DATE)=CAST(GETDATE() AS DATE)'
when writing like this i have received in the quotation part of 'TSN'. It doesnt allow single quotes here. How can i achieve the where condition?
you need to build it as a string.
declare #query nvarchar(max)='
declare #DateParam datetime
set #DateParam=getdate()
select * from tblOrders
where Order_site=''TSN''
AND CAST(ORDER_APPROVED_DATE_LT AS DATE)=CAST(GETDATE() AS DATE)'
Problem is that you are breaking your main nvarchar because of 'TSN', try like this
declare #query nvarchar(max)='
declare #DateParam datetime
set #DateParam=getdate()
select * from tblOrders
where Order_site=' + 'TSN' +
'AND CAST(ORDER_APPROVED_DATE_LT AS DATE)=CAST(GETDATE() AS DATE)'
if you are working with dynamic sql in stored procedure try something like this . It is better to use different variables for main select query and dynamic where query which can be extended easily . using this approach it will be easy to maintain when you proc becomes lengthy
declare #finalquery varchar(max)
declare #mainSelectquery nvarchar(500);
declare #whereCondtions varchar (1000);
declare #DateParam datetime
set #mainSelectquery=''
set #whereCondtions =''
set #finalquery =''
set #DateParam=getdate()
set #mainSelectquery = 'select * from tblOrders where 1=1 '
set #whereCondtions = ' and Order_site =''TSN'''
set #whereCondtions = #whereCondtions + ' AND CAST(ORDER_APPROVED_DATE_LT AS DATE)=CAST(GETDATE() AS DATE)'
set #finalquery =( #mainSelectquery + #whereCondtions)
print #finalquery
---- You can further extend this by adding more where condition based on the parameter pass in stored proc
if (#OrderID !=0)
begin
set #whereCondtions = ' OrderID='+str ( #stateRefID )
end
As an alternative to escaping your string with double quotes, you can try using QUOTENAME():
declare #val nvarchar(max) = 'TSN'
declare #query nvarchar(max)='
declare #DateParam datetime
set #DateParam=getdate()
select * from tblOrders
where Order_site= ' + quotename(#val, '''') +
' AND CAST(ORDER_APPROVED_DATE_LT AS DATE)=CAST(GETDATE() AS DATE)'
select #query
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.
I have a parameter with the available values as column names and a I am using that parameter in the sql query
WHERE ((#ColumnName) BETWEEN (#StartDate) AND (#EndDate))
AND (schema.table.column_name LIKE (#Number))
When i try to run the report i get a cannot convert date/time from characters
If i remove the #ColumnName parameter the report runs fine but i want the ability to choose a column to search the date against.
If you want pass Column name dynamically you will need to use a stored procedure to do this using dynamic sql something like this....
CREATE PROCEDURE Get_Data
#ColumnName1 SYSNAME,
#ColumnName2 SYSNAME,
#StartDate DATETIME,
#EndDate DATETIME,
#Number VARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = N'SELECT * FROM TableName'
+ N'WHERE ' + QUOTENAME(#ColumnName1) + N' BETWEEN #StartDate AND #EndDate '
+ N' AND ' + QUOTENAME(#ColumnName2) + N' LIKE ''#Number'' '
EXECUTE sp_executesql #SQL
,N'#StartDate DATETIME, #EndDate DATETIME, #Number VARCHAR(100)'
,#StartDate
,#EndDate
,#Number
END