UPDATE statement not updating table - sql

I am having a problem getting this UPDATE statement to execute. No error is returned, it just does not update the table.
#recordExists varchar(10),
#fileName varchar(50),
#itemCode varchar (50),
--#uploadDate datetime,
#submittedBy varchar(30),
#revision varchar(50),
#itemCode5 varchar(50),
#itemCkDigit varchar(10),
#suffix varchar(10)
AS
DECLARE #sql varchar(1000)
DECLARE #uploadDate datetime
SET #uploadDate = GetDate()
-- Establish update or insert in to the graphics info table.
IF #recordExists = 'Y'
SET #sql = 'UPDATE tblGraphicInfo SET [uploadDate] = ''' + CONVERT(nvarchar(20), #uploadDate) + ''', [submittedBy] = ''' + #submittedBy + ''' WHERE [itemCode] = "' + #itemCode + '"; '
EXEC(#sql)
ELSE
Any help would be appreciated.
FYI, I changed passing the date in because I thought that was the problem. The uploadDate field is defined as a datetime field in the tblGraphicInfo table.

I don't see why you would even need to dynamically string together your UPDATE statement - just use:
DECLARE #sql varchar(1000)
DECLARE #uploadDate datetime
SET #uploadDate = GetDate()
-- Establish update or insert in to the graphics info table.
IF #recordExists = 'Y'
UPDATE dbo.tblGraphicInfo
SET [uploadDate] = CONVERT(NVARCHAR(20), #uploadDate),
[submittedBy] = #submittedBy
WHERE [itemCode] = #itemCode
ELSE

Your issue is your where statement
WHERE [itemCode] = "' + #itemCode + '"; '
You will want to wrap strings in single quote (') not double quote ("). When escaping them in your string, you will need to double the single quotes.
WHERE [itemCode] = ''' + #itemCode + '''; '
You might also look at sp_executsql. It has a much cleaner syntax for handling parameters.

Have you checked to see if any of the variables you are passing in are null? This can cause the whole of your #sql variable to be null too. Try printing your #sql variable with Print() to check it is what it should be.
You could also run profiler to see what is being executed.

If any of your fields are null #sql will be null (Concatinating null yields null).
Is there any reason you are using EXEC rather than doing..
#recordExists varchar(10),
#fileName varchar(50),
#itemCode varchar (50),
--#uploadDate datetime,
#submittedBy varchar(30),
#revision varchar(50),
#itemCode5 varchar(50),
#itemCkDigit varchar(10),
#suffix varchar(10)
AS
DECLARE #sql varchar(1000)
DECLARE #uploadDate datetime
SET #uploadDate = GetDate()
-- Establish update or insert in to the graphics info table.
IF #recordExists = 'Y'
UPDATE tblGraphicInfo SET [uploadDate] = #uploadDate, [submittedBy] = #submittedBy WHERE [itemCode] = #itemCode
ELSE
Additionally if you perform more than one line inside an if else you will need to wrap it in a BEGIN END
You could actually do the following instead, the ##ROWCOUNT=0 will test if the previous statement modified no records and so needs to be an insert
UPDATE tblGraphicInfo SET [uploadDate] = #uploadDate, [submittedBy] = #submittedBy WHERE [itemCode] = #itemCode
if ##ROWCOUNT=0 then
INSERT into tblGraphicInfo (uploadDate,submittedBy,itemCode) values (#uploadDate,#submittedBy,#itemCode)

Related

Conversion failed when converting the varchar value 'UPDATE table SET TypeId = ' to data type int

I need to update a table with values passed as parameters from a desktop application. But every time I try to run the query I just get this error :
Msg 245, Level 16, State 1, Line 5
Conversion failed when converting the varchar value 'UPDATE
table
SET
TypeId = ' to data type int.
I tried to isolate the problem by reducing the code to a minimum, and below is the shortest snippet of my actual code and still the problem occurs. I figure its most likely a syntax problem, but after browsing similar issues for a while now, I still can't seem to figure out the problem.
DECLARE #typeId int = 175;
DECLARE #item varchar(20)= 'ABC123'
DECLARE #SQLScript varchar(5000);
SET #SQLScript = 'UPDATE
table
SET
TypeId = ' + #typeId + '
WHERE item = ''' + #item + '''
'
Print(#SQLScript);
What I would expect to come out as a result from the Print(#SQLScript) is
the query:
UPDATE
table
SET
TypeId = 175
WHERE
item = 'ABC123'
You need to convert #typeID to a string in order to concatenate it:
DECLARE #typeId int = 175;
DECLARE #item varchar(20)= 'ABC123'
DECLARE #SQLScript varchar(5000);
SET #SQLScript = 'UPDATE
table
SET
TypeId = ' + CONVERT(VARCHAR(128),#typeId) + '
WHERE item = ''' + #item + '''
'
PRINT(#SQLScript);
Why are you using dynamic sql here at all? This should be a simple parameterized query. The code you posted is vulnerable to sql injection. http://bobby-tables.com/
DECLARE #typeId int = 175;
DECLARE #item varchar(20)= 'ABC123'
UPDATE
table
SET
TypeId = #typeId
WHERE item = #item
I don't know why you need to use the dynamic SQL here since you can simply do
DECLARE #TypeId INT = 175,
#Item VARCHAR(20) = 'ABC123';
UPDATE T
SET TypeId = #TypeId
WHERE Item = #Item;
but if you really need to use a dynamic SQL, then do it the right way
DECLARE #TypeId INT = 175,
#Item VARCHAR(45) = 'ABC123';
EXEC sp_executesql N'UPDATE T SET TypeId = #TypeId WHERE Item = #Item',
N'#TypeId INT, #Item VARCHAR(45)',
#TypeId,
#Item;
Here is a db<>fiddle to see how it's working.
You need convert #typeId to VARCHAR
SET #SQLScript = 'UPDATE
table
SET
TypeId = ' + CAST(#typeId AS VARCHAR(10)) + '
WHERE item = ''' + #item + '''

get the column value in sql server in subquery

The following is my query and I need to column value in select subquery instead i get column name
#Temp = temporary table
insert into #Temp([dateTime],Reading)
values (#startDate,(select top(1) #trendId from TABLENAME where deviceTimestamp >= #startDate and deviceTimestamp < #tempdt order by deviceTimestamp desc))
ALTER PROCEDURE ProcName
#trendId as nvarchar(max),
#startDate as datetime,
#endDate as datetime
AS
BEGIN
declare #stt varchar(200) = 'select deviceTimestamp,' + #trendId + ' '+'as reading
from TableName
where deviceTimestamp >= '+#startDate+'and deviceTimestamp < '+#endDate+'
order by deviceTimestamp desc'
exec(#stt)END
I get the error :
Conversion failed when converting date and/or time from character string.)
DECLARE #sqlCommand varchar(1000)
DECLARE #columnList varchar(75)
DECLARE #city varchar(75)
SET #columnList = 'AddressID, AddressLine1, City'
SET #city = '''London'''
SET #sqlCommand = 'SELECT ' + #columnList + ' FROM Person.Address WHERE City = ' + #city
EXEC (#sqlCommand)
Check this link out. Dynamic SQL seems like what you need you can pass tablename,table columns dynamicly to your Query. so with this you will be able to pass column name as parameter-variable. otherwise you just selecting plainText as record.

getting error while converting to date time in stored procedure

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

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())

Single quote in custom query

I have this procedure for custom paging, search and sort options.
ALTER PROCEDURE [dbo].[stp_OrdersPaginated]
#Name NVARCHAR(50)=NULL,
#OrderNumber NVARCHAR(50)=NULL,
#Status NVARCHAR(50)=NULL,
#OrderBy NVARCHAR(100)=NULL,
#PageNumber INT,
#PageSize INT
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #ORDERS
(
[OrderId] Bigint
,[Name] Varchar(100)
,[Status] Varchar(50)
,[CreatedDate] Date
,[OrderNumber] Varchar(100)
,[UserId] Bigint
,[Amount] Decimal
,RowNumber Bigint IDENTITY(1,1)
)
DECLARE #intTotal INT
SET #intTotal = #PageSize * #PageNumber
DECLARE #sSQL NVARCHAR(MAX)
DECLARE #Where NVARCHAR(MAX) = ''
DECLARE #Order NVARCHAR(MAX) = ''
SET #sSQL = 'SELECT dbo.[Order].OrderId, [User].Name, dbo.[Order].Status,
dbo.[Order].CreatedDate, [Order].OrderNumber, dbo.[User].UserId,
dbo.Order.[Amount]
FROM dbo.[Order]
INNER JOIN dbo.User
ON dbo.[User].UserId = dbo.[Order].UserId'
SET #Order =' ORDER BY ' +#OrderBy
IF #Name is not null
SET #Where = #Where + ' AND dbo.[User].Name LIKE ''%'+#Name+'%'''
IF #OrderNumber is not null
SET #Where = #Where + ' AND dbo.[Order].OrderNumber LIKE '''+#OrderNumber+'%'''
IF #Status is not null
SET #Where = #Where + ' AND dbo.[Order].[Status] LIKE '''+#Status+'%'''
IF LEN(#Where) > 0
SET #sSQL = #sSQL + ' WHERE ' + RIGHT(#Where, LEN(#Where)-4)
INSERT INTO #ORDERS
EXECUTE (#sSQL + #Order)
Select [OrderId],[Name],[Status],[CreatedDate],[OrderNumber,[UserId]
,[Amount],RowNumber
From #ORDERS
WHERE RowNumber between ((#PageNumber * #PageSize)-(#PageSize- 1)) AND (#PageNumber * #PageSize)
Declare #TotalRecords Integer
Declare #TotalPage Integer
SELECT #TotalRecords=MAX(RowNumber) from #ORDERS
if(#TotalRecords is not NULL)
begin
if(#TotalRecords%#PageSize = 0)
begin
SET #TotalPage = #TotalRecords/#PageSize
end
else
begin
SET #TotalPage = #TotalRecords/#PageSize + 1
end
end
else
begin
set #TotalPage = 1
end
Select #TotalPage [TotalPages], #TotalRecords [TotalRecords]
DROP Table #ORDERS
END
As you can see one of the Search params is Name. The Procedure works perfectly for all except for Single Quote(') for obvious reason. Example: if I pass O' Brien for name it would fail. Is there any way to handle such single quote values with custom queries on SQL Server?
Your problem stems from not constructing your dynamic SQL in a best-practice manner, which along with making it difficult to construct the correct SQL, is also exposing you to SQL injection attacks.
Essentially, you should never use concatenation when adding parameters to your SQL string. I also use char(37) to represent the % sign, as this way it isn't necessary to escape it with apostrophes.
So your SQL becomes something like
IF #Name is not null
SET #Where += 'AND Name LIKE char(37)+#Name+char(37)'
IF #OrderNumber is not null
SET #Where += ' AND OrderNumber LIKE #OrderNumber+char(37)'
IF #Status is not null
SET #Where += ' AND [Status] LIKE #Status+char(37)'
IF LEN(#Where) > 0
SET #sSQL += ' WHERE ' + RIGHT(#Where, LEN(#Where)-4)
Creating the OrderBy is harder as you cannot parameterise that. if you absolutely trust the value passed in, then your code is okay, but the safest way would be to have something like an if statement that
tests the value passed in and creates the appropriate clause. e.g.
IF #OrderBy = 'status'
SET #Ssql += ' ORDER BY Status'
--Next you need to declare the parameters being included in the dynamic SQL. i'm making up the variable types, as you didn't specify what they were.
declare #params nvarchar(1000) = '#name nvarchar(100), #ordernumber nvarchar(100), #status nvarchar(10)'
--Then you can execute your dynamic SQL, passing to it the parameters provided to your procedure
insert into #temp
ExeCUTE sp_executesql #sSQL, #params, #name, #ordernumber, #status
One other benefit of constructing dynamic SQL in this manner, rather than concatenating strings, is that SQL Server can actually cache the query plan like it does for non-dynamic SQL and you don't have the performance hit that you get when you use concatenation.
Try:
IF #Name is not null
BEGIN
SET #Name = REPLACE(#Name, '''', '''''')
SET #Where = #Where + ' AND dbo.[User].Name LIKE ''%'+#Name+'%'''
END