hi
i have a problem on converting datetime from character string on createddate and leavestartdate column.....
Table structure createdby varchar(30),createddate datetime, leavetype varchar(30), leavestartdate varchar(30), status varchar(30)
ALTER Procedure [dbo].[sp_SearchLeave]
#createdby varchar(30) = null ,
#createddate DateTime = null ,
#leavetype varchar(30) = null ,
#leavestartdate varchar(30) = null ,
#status varchar(30) = null
As
Begin
if #createddate is not null and Len(#createddate) = 0 set #createddate = null
if #leavetype = 'Select' set #leavetype = null
if #leavestartdate is not null and Len(#leavestartdate) = 0 set #leavestartdate = null
if #status = 'Select' set #status = null
Select leaverequestid,leaveenddate,leavetype,leavestartdate,status
from LeaveRequest
where
(#createdby is null or createdby like '%' + #createdby + '%')
and (#createddate is null or createddate like '%' + #createddate + '%')
and (#leavetype is null or leavetype like '%' + #leavetype + '%')
and (#leavestartdate is null or leavestartdate like '%' + #leavestartdate + '%')
and (#status is null or status like '%' + #status + '%')
End
when i execute this sp as a input like
exec sp_SearchLeave '','','','12/15/2010',''
it displays the error message like
Msg 241, Level 16, State 1, Procedure sp_SearchLeave, Line 26
Conversion failed when converting datetime from character string.
The reason is likely the like statement. You're treating a datetime parameter (#createddate) as a string by appending % to it, which you cannot do.
Related
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
I have a GetUsers stored procedure as shown below. If a #GroupId or #GroupName parameter is provided, then I need to beef up the stored procedure to ensure that only users belonging to a matching group are returned.
I've created a special table variable named #GroupUserMatches which contains a UserId/GroupId association for matching user groups. I could essentially copy/paste the SQL from the ELSE block into the IF block and update it a bit to accommodate a join to #GroupUserMatches, but I was wondering if there is a more elegant way to do this?
One concern is that I'd like to avoid having to make updates to the same SQL select in 2 different blocks in the same stored procedure. If no #GroupId or #GroupName are provided, then the user list returned should be completely unfiltered by group.
ALTER PROCEDURE [dbo].[GetUsers]
#DomainId uniqueidentifier = NULL,
#DomainName varchar(100) = NULL,
#NetworkUserId varchar(100) = NULL,
#UserPrincipalName varchar(100) = NULL,
#FirstName varchar(100) = NULL,
#LastName varchar(100) = NULL,
#EmailAddress varchar(255) = NULL,
#GroupId uniqueidentifier = NULL,
#GroupName varchar(500) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE #GroupUserMatches TABLE
(
GroupId UNIQUEIDENTIFIER,
UserId UNIQUEIDENTIFIER
)
IF(#GroupId IS NOT NULL OR #GroupName IS NOT NULL)
BEGIN
INSERT INTO #GroupUserMatches (GroupId, UserId)
SELECT geue.GroupExtensionId, geue.UserExtensionId
FROM ADGroup adg
JOIN GroupExtension ge ON adg.Id = ge.ADGroupId
JOIN GroupExtensionUserExtension geue ON ge.Id = geue.GroupExtensionId
WHERE (#GroupId IS NULL OR ge.Id = #GroupId)
AND (#GroupName IS NULL OR adg.[Name] LIKE #GroupName + '%')
END
ELSE
BEGIN
SELECT
au.*,
0 HasExtendedSecurity
FROM
AllUsers au
JOIN
Domain d ON au.DomainName = d.[Name]
WHERE
(#DomainId IS NULL OR au.DomainId = #DomainId) AND
(#DomainName IS NULL OR au.DomainName = #DomainName) AND
(#NetworkUserId IS NULL OR au.NetworkUserId = #NetworkUserId) AND
(#UserPrincipalName IS NULL OR au.UserPrincipalName = #UserPrincipalName) AND
(#FirstName IS NULL OR au.FirstName LIKE #FirstName + '%') AND
(#LastName IS NULL OR au.LastName LIKE #LastName + '%' ) AND
(#EmailAddress IS NULL OR au.Email LIKE #EmailAddress + '%')
END
END
What am I missing on my query below?
When I'm passing parameter for (#Status) 'All' , there were no results even though the #status parameter condition is satisfied.
Since when I pass 'All' it will be changed to (un-assigned, assigned). But when I'm passing Assigned/ Un-Assigned directly, it works fine.
ALTER PROCEDURE [dbo].[sp_File_Search]
#Uploaded AS INT = null,
#File_Name AS VARCHAR(150) = null,
#Upload_DT AS DATETIME = null,
#Status AS VARCHAR(150) = null,
#St1 AS VARCHAR(15) = null,
#St2 AS VARCHAR(15) = null
AS
If #Status = 'All'
BEGIN
SET #St1 = 'Un-Assigned'
SET #St2 = 'Assigned'
END
ELSE
BEGIN
SET #St1 = #Status
SET #St2 = #Status
END
--ON UPLOAD DATE
Begin
if #Uploaded= 1
Begin
SELECT [FILE_ID],[FILE_NAME], [UPLOAD_DT] FROM [dbo].[FILE]
WHERE (
[FILE_NAME] like '%' + #File_Name + '%'
OR #File_Name IS NULL
)
AND (
[UPLOAD_DT] between #Upload_DT + '00:00:00' and #Upload_DT + '23:59:59'
OR #Upload_DT IS NULL OR #Upload_DT = ''
)
AND (
[STATUS] IN (#St1,#St2)
Order by Upload_DT desc
END
-- ON OR BEFORE UPLOAD DATE
if #Uploaded=2
Begin
SELECT [FILE_ID],[FILE_NAME], [UPLOAD_DT]
FROM [cobind].[FILE]
WHERE (
[FILE_NAME] like '%' + #File_Name + '%'
OR #File_Name IS NULL
)
AND (
[UPLOAD_DT] between #Upload_DT + '00:00:00' and #Upload_DT + '23:59:59'
OR [UPLOAD_DT] < #Upload_DT
OR #Upload_DT IS NULL OR #Upload_DT = ''
)
AND (
[STATUS] IN (#St1,#St2)
)
Order by Upload_DT desc
END
-- ON OR AFTER UPLPOAD DATE
if #Uploaded=3
Begin
SELECT [FILE_ID], [FILE_NAME], [UPLOAD_DT]
FROM [dbo].[FILE]
WHERE (
[FILE_NAME] like '%' + #File_Name + '%'
OR #File_Name IS NULL
)
AND (
[UPLOAD_DT] between #Upload_DT + '00:00:00' and #Upload_DT + '23:59:59'
OR [UPLOAD_DT] > #Upload_DT
OR #Upload_DT IS NULL OR #Upload_DT = ''
)
AND (
[STATUS] IN (#St1,#St2)
)
Order by Upload_DT desc
END
END
The IN keyword works with either a subquery or a list. When you create the list of values in the SET #Status statement, you are actually creating a string. The query will try to look for the specific string, and since that string does not exist in the column being searched, there won't be any results.
You can work around this by using dynamic SQL. Basically, create a variable to hold the part related to #Status, create the query itself as an NVARCHAR string and append your variable clause to it. Finally, use sp_executesql to run the query, something like this:
If #Status = 'All'
SET #Status = '(''Un-Assigned'',''Assigned'')'
declare #query nvarchar(1000) = 'SELECT * FROM [dbo].[CoM_REPO] WHERE [STATUS] IN ' + #Status + ' Order by UploadDATE desc'
exec sp_executesql #query
Are you getting any error message ?
I guess its because your query says [STATUS] IN (#Status) , meaning () are already there, so if you pass Assigned , it would be coming as [STATUS] IN ('Assigned'), whereas when you are passing 'All', it may be coming as [STATUS] IN ((''Un-Assigned'',''Assigned'')) with double brackets, just try to remove the brackets.
I have a stored procedure that does a search based on the input parameters. Now for auditing reasons the business requirement is to save what is searched and who search as a XML column in the Auditlog table.
I have simplified what I am trying to do in this example. All the declares are my input parameter. I am creating XML in my stored procedure and inserting it into the audit column. To test this out I simulated the behaviour
DECLARE #LastName varchar(50)
DECLARE #FirstName varchar(50)
DECLARE #RelationShip varchar(50)
DECLARE #CallDate date
DECLARE #CallStartTime time(7)
DECLARE #AdminID int
DECLARE #HomePhone varchar(15) = null
DECLARE #WorkPhone varchar(15) = null
DECLARE #MobilePhone varchar(15) = null
DECLARE #SearchXML xml
DECLARE #UserName varchar(50)
SET #LastName = 'rayan'
SET #FirstName = 'Meg'
SET #RelationShip = 'Friend'
SET #CallDate = (SELECT GETDATE())
SET #CallStartTime = (SELECT CONVERT (time, SYSDATETIME()))
SET #AdminID = 74
SET #HomePhone = null
SET #WorkPhone = null
SET #MobilePhone = null
SET #UserName = 'nojha'
SET #SearchXML =
'<Root>
<CallerInformation>
<LastName>' + #LastName + '</LastName>
<FirstName>' + #FirstName + '</FirstName>
<Relationship>' + #RelationShip + '</Relationship>
<CallDate>' + #CallDate + '</CallDate>
<CallStartTime>' + #CallStartTime + '<CallStartTime/>
<HomePhone>' + #HomePhone + '</HomePhone>
<WorkPhone>' + #WorkPhone + '</WorkPhone>
<WorkPhone>' + #WorkPhone + '<WorkPhone/>
<UserName>' + #UserName + '</UserName>
</CallerInformation>
</Root>'
SELECT #SearchXML
I get two errors when I do this
The data types varchar and date are incompatible in the add operator.
I figured it some error due to date. So I removed CallDate and CallStartTime to see if I am getting proper XML. But running the above query returns null.
Can someone help me out with this?
Thanks
Neha
Are you certain that none of your parameters will contain reserved characters such as <, &, etc.?
Try something like this instead:
SET #SearchXML = (SELECT
#LastName As LastName,
#FirstName As FirstName,
#RelationShip As Relationship,
#CallDate As CallDate,
#CallStartTime As CallStartTime,
#HomePhone As HomePhone,
#WorkPhone As WorkPhone,
#UserName As UserName
FOR XML RAW ('CallerInformation'), ROOT ('Root'), ELEMENTS);
DATE and VARCHAR are not compatible when using '+'. Therefore you must convert the DATE to a VARCHAR to be able to concatenate them.
Some of your tags do not match, e.g, you have WorkPhone/ instead of /WorkPhone on the closing tag.
You are concatenating value's that are NULL. This causes the whole string to become NULL. You need to wrap an ISNULL(#value,'') to place an empty string when you have no value
Here is a working example of the problem section:
SET #SearchXML =
'<Root>
<CallerInformation>
<LastName>' + #LastName + '</LastName>
<FirstName>' + #FirstName + '</FirstName>
<Relationship>' + #RelationShip + '</Relationship>
<CallDate>' + CONVERT(VARCHAR,#CallDate) + '</CallDate>
<CallStartTime>' + CONVERT(VARCHAR,#CallStartTime) + '</CallStartTime>
<HomePhone>' + ISNULL(#HomePhone,'') + '</HomePhone>
<WorkPhone>' + ISNULL(#WorkPhone,'') + '</WorkPhone>
<WorkPhone>' + ISNULL(#WorkPhone,'') + '</WorkPhone>
<UserName>' + #UserName + '</UserName>
</CallerInformation>
</Root>'
I have UI where a user can search on optional parameters.I am writing a SP and as a testing database I am using AdventureWorks.
For some reasons I dont seem to find a way how to include
Where ModifiedDate between ''' + #Fromdate + ''' And '''+ #ToDate + '''')
in my existing SP.Can you help?
My sp looks like this
ALTER PROCEDURE SearchPerson_Dynamic
(
#FirstName NVARCHAR(50) = NULL,
#LastName NVARCHAR(50) = NULL,
#EmailAddress NVARCHAR(50) = NULL,
#Phone NVARCHAR(25) = NULL,
#FromDate DATETIME =NULL,
#ToDate DATETIME =NULL
AS
DECLARE #sSQL NVARCHAR(MAX), #Where NVARCHAR(1000) = ''
SET #sSQL = 'SELECT * FROM [Person].[Contact]'
IF #FirstName is not null
SET #Where = #Where + 'AND FirstName = #_FirstName '
IF #LastName is not null
SET #Where = #Where + 'AND LastName = #_LastName '
IF #EmailAddress IS NOT NULL
SET #Where = #Where + 'AND EmailAddress = #_EmailAddress '
IF #Phone IS NOT NULL
SET #Where = #Where + 'AND Phone = #_Phone '
-- NEED TO INTEGRATE A SEARCH BETWEEN #FromDate and #ToDate
IF LEN(#Where) > 0
SET #sSQL = #sSQL + 'WHERE ' + RIGHT(#Where, LEN(#Where)-3)
EXEC sp_executesql #sSQL,
N'#_FirstName VARCHAR(50),
#_LastName VARCHAR(50),
#_EmailAddress VARCHAR(50),
#_Phone NVARCHAR(25)',
#_FirstName = #FirstName,
#_LastName = #LastName,
#_EmailAddress = EmailAddress,
#_Phone = #Phone
MISSING #FROMDate and #ToDate --HOW DO i DO IT HERE
One thing I have not done is that some fields EG Surname the user can select "ALL" in the UI from the drop down. How would I implement a search where I dont have an exact parameter?
Thanks again for your help
If I was to rewrite your stored proc, I would do the following
ALTER PROCEDURE SearchPerson_Dynamic
(
#FirstName NVARCHAR(50) = NULL,
#LastName NVARCHAR(50) = NULL,
#EmailAddress NVARCHAR(50) = NULL,
#Phone NVARCHAR(25) = NULL,
#FromDate DATETIME =NULL,
#ToDate DATETIME =NULL
)
as
begin
SELECT * FROM [Person].[Contact]
where
FirstName = coalesce(#FirstName, FirstName) and
LastName = coalesce(#LastName, LastName) and
EmailAddress = coalesce(#EmailAddress, EmailAddress) and
Phone = coalesce(#Phone, Phone) and
ModifiedDate >= coalesce(#FromDate, FromDate) and
ModifiedDate <= coalesce(#ToDate, ToDate)
end
This is better as its not executing text for the stored procedure and could be optimized.
If you want to use the dynamic sql, you could cast the date to a normal string, ie
IF #FromDate IS NOT NULL AND #ToDate IS NOT NULL
SET #Where = #Where + 'AND ModifiedDate between ''' + cast( #FromDate as varchar(50) ) + ''' and ''' + cast( #ToDate as varchar(50) ) + ''' '