getting error while converting to date time in stored procedure - sql

I am getting error like:
Msg 241, Level 16, State 1, Procedure spQueryMgt, Line 106 [Batch
Start Line 13] Conversion failed when converting date and/or time
from character string.
ALTER PROCEDURE [dbo].[spQueryMgt]
#Mode varchar(50)='',
#Query_Form varchar(20)='',
#Patient_ID bigint=0,
#Verified_By bigint = 0,
#Verified_Date datetime=''
AS
BEGIN
IF(#mode='Post_Query')
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'Update '+ CONVERT(varchar(12), #Query_Form) +' Set
Verified_By='+CONVERT(VARCHAR(12), #Verified_By)+',
Verified_Date='''+CONVERT(datetime, #Verified_Date,20)+'''
where Patient_ID = '+CONVERT(varchar(12), #Patient_ID)
EXEC sp_executeSQL #sql;
END
END

Change your query to -
SET #sql = N'Update '+ CONVERT(varchar(12), #Query_Form) +' Set
Verified_By='+CONVERT(VARCHAR(12), #Verified_By)+',
Verified_Date='''+CONVERT(VARCHAR(20), #Verified_Date,20)+'''
where Patient_ID = '+CONVERT(varchar(12), #Patient_ID)
There is issue with your convert function. You are converting #Verified_Date to datetime and concatenating datetime to varchar string.

The problem was that you where converting datetime back into datetime, and then tried to concatinate which gives you that exception.
But also, by initializing parameters to '' and 0 you are filling your database with unnesesary values like '' for varchars and 1900-01-01 for datetime columns and even worse 0 in integer columns.
Is that what you really want ? I doubt it.
It will be impossible to determine if a field was intentionaly set to this value or was left empty and get you into troubles later.
You can do your procedure like this to get NULL values in empty parameters
ALTER PROCEDURE [dbo].[spQueryMgt] (
#Mode varchar(50) = NULL,
#Query_Form varchar(20) = NULL,
#Patient_ID bigint = NULL,
#Verified_By bigint = NULL,
#Verified_Date datetime = NULL
)
AS
BEGIN
SET NOCOUNT ON;
IF #mode ='Post_Query'
BEGIN
DECLARE #sql NVARCHAR(MAX);
if (#Query_Form is not null) and (#Patient_ID is not null) -- nu use in updating when no table or id is given
begin
SET #sql = N' Update ' + CONVERT(varchar(12), #Query_Form) +
' Set Verified_By = ' + isnull(CONVERT(VARCHAR(12), #Verified_By), 'null') + ',' +
' Verified_Date = ' + case when #Verified_Date is null then 'null' else '''' + CONVERT(varchar(20), #Verified_Date, 20) + '''' end +
' where Patient_ID = ' + isnull(CONVERT(varchar(12), #Patient_ID), 'null')
EXEC sp_executeSQL #sql;
end
END
END
EDIT
As mentioned in the comments you should also take care of sql injection, and that makes your procedure safer, but also even easier
create PROCEDURE [dbo].[spQueryMgt] (
#Mode varchar(50) = NULL,
#Query_Form varchar(20) = NULL,
#Patient_ID bigint = NULL,
#Verified_By bigint = NULL,
#Verified_Date datetime = NULL
)
AS
BEGIN
SET NOCOUNT ON
IF #mode = 'Post_Query'
BEGIN
DECLARE #sql NVARCHAR(MAX)
if (#Query_Form is not null) and (#Patient_ID is not null) -- nu use in updating when no table or id is given
begin
SET #sql = N'Update #P0 ' +
'set Verified_By = #P1, ' +
' Verified_Date = #P2 ' +
'where Patient_ID = #P3'
EXEC sp_executesql #sql,
N'#P0 varchar(20), #P1 bigint, #P2 bigint, #P3 datetime',
N'#P0 = #Query_Form, #P1 = #Verified_By, #P2 = #Verified_Date, #P3 = #Patient_ID'
end
END
END

Related

Conversion failed when converting date from character string in a stored procedure

I am facing an issue with running a stored procedure with a Date parameter. I have 2 parameters in a stored procedure which returns a result set from a table. In the table name is of type nvarchar and dateclient is a date.
The value of the parameters are coming from an user interface.
ALTER PROCEDURE [dbo].[NAME_SEARCH]
#name nvarchar(255),
#dateclient datetime
AS
BEGIN
DECLARE #parsed_string nvarchar(max)
EXEC parsing_coi_input #name, #parsed_string OUTPUT
PRINT #parsed_string
SET #name = #parsed_string
DECLARE
#BaseQuery nvarchar(max) = 'SELECT Id, name, date_client
FROM Client
INNER JOIN CONTAINSTABLE (Client, ame,'''+ #name + ''') as name_key ON ID = name_key.[KEY]'
DECLARE
#OrderByQuery nvarchar(max) = ' ORDER BY name_key.RANK'
DECLARE
#OrderDesc nvarchar(max) =' DESC'
BEGIN
SET NOCOUNT ON;
SET #BaseQuery = #BaseQuery + '
INNER JOIN CONTAINSTABLE(Client, date_client,'''+ #dateclient +''') AS
date_clientkey ON ID = date_clientkey.[KEY] WHERE date_client_matter_open >= '+ #dateclientmatter
+''
SET #OrderByQuery = #OrderByQuery + ',date_client_key.RANK'
END
DECLARE #fullQuery nvarchar(max)= #BaseQuery + #OrderByQuery + #OrderDesc
EXECUTE sp_executesql #fullQuery
END
I am executing:
EXEC [dbo].[NAME_SEARCH] 'MGeolo','2009-04-05'
But I get this error:
Conversion failed when converting date and/or time from character string.
Any suggestions how to handle this?
You are missing the ' characters around your date when the SQL script is generated and a cast from datetime to varchar.
You should do like:
BEGIN
SET NOCOUNT ON;
SET #BaseQuery = #BaseQuery + '
INNER JOIN CONTAINSTABLE(Client, date_client,'''+ cast(#dateclient as varchar(200)) +''') AS
date_clientkey ON ID = date_clientkey.[KEY] WHERE date_client_matter_open >= '''+ cast(#dateclientmatter as varchar(200)) +''''
SET #OrderByQuery = #OrderByQuery + ',date_client_key.RANK'
It is probably a typo but the #dateclientmatter is undeclared because in the header you have only #dateclient.

sql Append for value with single quotes - String Concatenation

This extended version on my previous question sql Append for value with single quotes which am trying to fix
DECLARE #fNAME varchar(40) = 'O'brain'
DECLARE #query nvarchar(256)
DECLARE #id nvarchar(5) = '8'
SET #query = 'UPDATE TableName SET columnname = ''' + #fNAME + '''' +'Added on '+ GETDATE() + ''' WHERE Id= ' + convert(nvarchar, #id)
am trying to get below output using
EXEC sp_executesql
Update table name set columnname = 'O''brain Added on Aug 8 2017 11:15AM' where id = 8
Basically am trying to append some text and current date along with name to be updates as text in one column
I would define and execute the query as:
DECLARE #fNAME varchar(40) = 'O''brain';
DECLARE #query nvarchar(256);
DECLARE #id nvarchar(5) = '8';
SET #query = '
UPDATE TableName
SET columnname = #fNAME + '' added on '' + convert(varchar(255), GETDATE() )
WHERE Id = #id';
EXEC sp_executesql #query, N'#fname varchar(40), #id nvarchar(5)', #fname=#fname, #id=#id;
Note: This is not going to format the date exactly as in your question. You haven't chosen a formatting for the date in your code, so I didn't either.
Here is how you would do this with a normal update. There appears to be no reason at all to use dynamic sql here.
DECLARE #fNAME varchar(40) = 'O''brain';
DECLARE #id nvarchar(5) = '8';
Update TableName
set columnname = #fNAME + ' added on ' + convert(varchar(255), getdate())

Passing either null or a string to a stored procedure doesn't work (because of quotes?)

I am using a stored procedure below. For parameters called LockedByName and LockedByLoginName I want to pass either a string (which can contain spaces etc. - so I quote it with single quotes) or a NULL value.
The procedure works with strings but doesn't work with null value. I assume this is because it somehow silently fails because it cannot put the NULL value into quotes.
What could be the way to both keep the quotes and also keep the ability to use null value?
It similarly fails when the parameter is an empty string which would be fine to use too.
ALTER PROCEDURE [dbo].[ChangeLockFormStatus]
#FormID as int,
#LockedByName as nvarchar(50) = null,
#LockedByLoginName as nvarchar(50) = null,
#TableName as varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ActualTableName AS varchar(255)
SELECT #ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TableName
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'UPDATE ' + #ActualTableName
+ ' SET LockedByName=''' + #LockedByName + ''','
+ 'LockedByLoginName=''' + #LockedByLoginName
+ ''' WHERE [ID] = ' + CAST(#FormID AS VARCHAR(25)) + ';'
EXEC(#sql)
END
If you use sp_executesql, you can continue to use your parameters directly, rather than having to mangle them into the string. Something like:
ALTER PROCEDURE [dbo].[ChangeLockFormStatus]
#FormID as int,
#LockedByName as nvarchar(50) = null,
#LockedByLoginName as nvarchar(50) = null,
#TableName as varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ActualTableName AS varchar(255)
SELECT #ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TableName
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'UPDATE ' + #ActualTableName
+ ' SET LockedByName=#LockedByName,'
+ 'LockedByLoginName=#LockedByLoginName'
+ ' WHERE [ID] = #FormID;'
EXEC sp_executesql #sql,
N'#LockedByName nvarchar(50),#LockedByLoginName nvarchar(50),#FormID int',
#LockedByName,#LockedByLoginName,#FormID
END

Stored Procedure Operand type clash: date is incompatible with int

This is my stored procedure
ALTER PROCEDURE [dbo].[sp_ListFirmJobFilter]
(#Status as nvarchar(10),
#CityID as nvarchar(10),
#DataStart as date,
#DataEnd as date,
#FirmID as nvarchar(10)
)
AS
BEGIN
DECLARE #Sql NVARCHAR(MAX)
SET #Sql = N'SELECT * FROM Jobs WHERE 1=1'
IF #Status IS NOT NULL
BEGIN
SET #Sql += ' AND Status = '+#Status+''
END
IF #CityID IS NOT NULL
BEGIN
SET #Sql += ' AND CityID = '+#CityID+''
END
IF #FirmID IS NOT NULL
BEGIN
SET #Sql += ' AND FirmID = '+#FirmID+' '
END
IF #DataStart IS NOT NULL
BEGIN
SET #Sql += ' AND (InsertedDate >= ' + CONVERT(VARCHAR(50), #DataStart)
SET #Sql += ' AND InsertedDate <= ' + CONVERT(VARCHAR(50), #DataEnd)
SET #Sql += ')'
END
PRINT(#Sql)
EXEC(#Sql)
END
The command completed successfully.
But when I execute that stored procedure with that parameter
DECLARE #return_value int
EXEC #return_value = [dbo].[sp_ListFirmJobFilter]
#Status = NULL,
#CityID = null,
#DataStart = N'2016-06-26',
#DataEnd = N'2016-06-28',
#FirmID = 4
SELECT 'Return Value' = #return_value
GO
I get an error:
Operand type clash: date is incompatible with int
I look for executed SQL command (Print SQL string). This is executed command:
SELECT *
FROM Jobs
WHERE 1=1
AND FirmID = 4
AND (InsertedDate >= 2016-06-26 AND InsertedDate <= 2016-06-28)
When I execute that it give same error. I changed it to:
SELECT *
FROM Jobs
WHERE 1=1
AND FirmID = 4
AND (InsertedDate >= '2016-06-26' AND InsertedDate <= '2016-06-28')
this worked.
What should I do? InsertedDate type is date
Wrap dates in single quotes
SET #Sql += ' AND (InsertedDate >= ''' + CONVERT(VARCHAR(50), #DataStart) +''''
SET #Sql += ' AND InsertedDate <= ''' + CONVERT(VARCHAR(50), #DataEnd) +''''
SET #Sql += ')'
As mentioned by Squirrel, and you noticed it yourself as well, dates have to be enclosed in single quotes.
Personally I like to use QUOTENAME for this:
SET #Sql += ' AND InsertedDate <= ' + QUOTENAME(CONVERT(VARCHAR(50), #DataEnd), '''')
you need to enclosed your date string in single quote
SET #Sql += ' AND (InsertedDate >= ==' + CONVERT(VARCHAR(50), #DataStart) + ''''

How to express a BETWEEN statement in SQL when running query from a variable

I have a rather large statement that I've built up using an #SQL variable and then running the query from the variable at the end of the statement. This works fine except for when inserting a date into one of the parameters.
The query then returns no data and come back with an error:
Conversion failed when converting date and/or time from character string.
The SQL I currently have is as follows:
ALTER PROCEDURE [dbo].[GetVisitListFiltered]
#sitekey int,
#VisitNo int = NULL,
#DNS varchar(max) = NULL,
#SessionStarted varchar(15) = '01/01/1900',
#Page varchar(max) = NULL,
#SecondsOnSite int = NULL,
#SecondsOnSiteRange int = NULL,
#Pages int = NULL,
#Cost int = NULL,
#City varchar(max) = NULL,
#Country varchar(max) = NULL,
#Keywords varchar(max) = NULL,
#Referrer varchar(max) = NULL
AS
BEGIN
BEGIN TRY
SET #SecondsOnSiteRange =
CASE #SecondsOnSiteRange
WHEN 1 THEN '='
WHEN 2 THEN '>'
WHEN 3 THEN '<'
ELSE NULL
END
DECLARE #SQL NVARCHAR(MAX)
, #SQLParams NVARCHAR(MAX);
SET #SQL = N'
SELECT VKey,
VisitIP,
SiteKey,
Alert,
AlertNo,
VisitNo,
Invited,
Chatted,
Prospect,
Customer,
HackRaised,
Spider,
Cost,
Revenue,
Visits,
FirstDate,
TotalCost,
TotalRevenue,
OperatingSystem,
Browser,
SearchEngine,
Referrer,
Keywords,
ReferrerQuery,
Name,
Email,
Company,
Telephone,
Fax,
Street,
City,
Zip,
Country,
Web,
Organization,
CRMID,
Notes,
DNS,
Region,
FirstAlert,
FirstVisitReferrer,
ProspectTypes,
VisitDate,
SecondsOnSite,
Page
FROM dbo.VisitDetail
WHERE SiteKey = #p0';
IF NULLIF(#VisitNo, '') IS NOT NULL SET #SQL += N' AND VisitNo = #p1';
IF NULLIF(#DNS, '') IS NOT NULL SET #SQL += N' AND DNS = #p2';
IF NULLIF(#SessionStarted, '01/01/1900') IS NOT NULL SET #SQL += N' AND VisitDate between #p3 and #p3 23:59:59';
IF NULLIF(#Page, '') IS NOT NULL SET #SQL += N' AND Page = #p4';
IF NULLIF(#SecondsOnSite, '') IS NOT NULL AND NULLIF(#SecondsOnSiteRange, '') IS NOT NULL SET #SQL += N' AND SecondsOnSite' + '#p12' + '#p5';
IF NULLIF(#Pages, '') IS NOT NULL SET #SQL += N' AND PagesSeen = #p6';
IF NULLIF(#Cost, '') IS NOT NULL SET #SQL += N' AND Cost = #p7';
IF NULLIF(#City, '') IS NOT NULL SET #SQL += N' AND City = #p8';
IF NULLIF(#Country, '') IS NOT NULL SET #SQL += N' AND Country = #p9';
IF NULLIF(#Keywords, '') IS NOT NULL SET #SQL += N' AND Keywords = #p10';
IF NULLIF(#Referrer, '') IS NOT NULL SET #SQL += N' AND ReferrerQuery = #p11';
SET #SQLParams = N'
#p0 INT
, #p1 INT
, #p2 VARCHAR(MAX)
, #p3 VARCHAR(15)
, #p4 VARCHAR(MAX)
, #p5 INT
, #p6 INT
, #p7 INT
, #p8 VARCHAR(MAX)
, #p9 VARCHAR(MAX)
, #p10 VARCHAR(MAX)
, #p11 VARCHAR(MAX)
, #p12 VARCHAR(10)';
EXECUTE sp_executesql #SQL
, #SQLParams
, #p0 = #SiteKey
, #p1 = #VisitNo
, #p2 = #DNS
, #p3 = #SessionStarted
, #p4 = #Page
, #p5 = #SecondsOnSite
, #p6 = #Pages
, #p7 = #Cost
, #p8 = #City
, #p9 = #Country
, #p10 = #Keywords
, #p11 = #Referrer
, #p12 = #SecondsOnSiteRange;
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE();
END CATCH
END
I know the problem lies somewhere in this area:
IF NULLIF(#SessionStarted, '01/01/1900') IS NOT NULL
SET #SQL += N' AND VisitDate between #p3 and #p3 23:59:59';
But I'm not sure how to fix it - can anyone suggest what I might be doing wrong?
It has already been pointed out that #SessionStarted is a VARCHAR when it should be a date. And that your final SQL is malformed, and no more valid than:
DECLARE #p3 DATE = GETDATE();
SELECT Test = #p3 '23:59:59';
Which gives:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '23:59:59'.
But I want to stress another point:
DON'T USE BETWEEN LIKE THIS
You are trying to construct a statement like:
WHERE Date BETWEEN '2015-09-03' AND '2015-09-03 23:59:59'
But what about if Date is '2015-09-03 23:59:59.5' - Do you really want this to be excluded? The best practice is to use an open ended range:
WHERE Date >= '2015-09-03'
AND Date < '2015-09-04'
Pretty much the same, but covers the entire day, not just most of it. SO your exact statement should probably be:
IF NULLIF(#SessionStarted, '01/01/1900') IS NOT NULL
SET #SQL += N' AND VisitDate >= #p3 AND VisitDate < DATEADD(DAY, 1, #p3)';
Aaron Bertrand has written a great article on this for further reading.
So in summary, a partial fix would be to use the concatenatation operator +:
DECLARE #p3 VARCHAR(50) = '03/09/2015';
SELECT Test = #p3 + ' 23:59:59';
A better fix would be to convert to the right datatype:
DECLARE #p3 VARCHAR(50) = '03/09/2015';
SELECT Test = CONVERT(DATETIME, #p3 + ' 23:59:59');
Even better would be to use a culture invariant date format, so it is clear whether you mean 3rd September or 9th March:
DECLARE #p3 VARCHAR(50) = '20150903';
SELECT Test = CONVERT(DATETIME, #p3 + ' 23:59:59');
Even better still would be to use the correct datatype in the first place:
DECLARE #p3 DATETIME = '20150903';
SELECT Test = #p3 + '23:59:59';
And better yet, would be to use an open ended date range as described above.
You have declared sessionstarted to be a character rather than a date. I imagine that this is the root cause of your problem.
Change the type to a date. I would also recommend that you use ISO standard YYYY-MM-DD format for the date, rather than a culture-specific format.
Your problem is in this bit
#p3 23:59:59';
You are trying to concatenate a string value to a date. What you need to do is a an addition (DATEADD) to the date held in #p3, and use that as another parameter
First of all, you need to use the correct data type. In your case #SessionStarted should be declared as DATE instead of VARCHAR.
After you do that, instead of adding 23:59:59 to your date field to get records occurring on that day, you should use this instead:
SET #SQL += N' AND VisitDate >= #p3 AND VisitDate < DATEADD(DAY, -1, #p3)'