Get error in string query - sql

I'm a beginner to SQL Server
I wrote this query:
DECLARE #sql nvarchar(1000) = 'UPDATE Work
SET [Name] = Programmer, [ImageAddress] = pic.jpg
WHERE Id = 2'
SELECT #sql
EXEC Sp_executesql #sql
but I get this error
Invalid column name 'Programmer'.
Why do I get this error?
Thank you for your help

You are dealing with SQL in strings. Quoting the strings becomes a challenge. You need for Programmer to be in single quotes when the query is executed. To get this, you need double single quotes in the string:
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = ''Programmer'', [ImageAddress] = ''pic.jpg'' WHERE Id=2'
select #sql
EXEC Sp_executesql #sql;
Because you are wise enough to use sp_executesql, you should learn about parameters. You can write the query as:
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = #Programmer, [ImageAddress] = #imageaddress WHERE Id=2'
select #sql
EXEC Sp_executesql #sql, N'#programmer nvarchar(255), #imageaddress nvarchar(255)',
#programmer = N'Programmer', #imageaddress = N'pic.jpg';
This has several advantages besides the quoting. It is safer in terms of SQL injection and it allows SQL Server to cache the execution plans if the query is called more than once.

try this:
You need to use '' (Double Quotes for string) Inside Dynamic SQL
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = ''Programmer'',[ImageAddress] =''pic.jpg'' WHERE Id=2'
select #sql
EXEC Sp_executesql #sql

Related

Issues with equal sign when assigning statement to # variable for EXEC sp_executesql

Hello: I am trying to encapsulate the following Insert and select statement into a variable for SQL to run.
The issue occurs when the equals sign is included for evaluation (or right around there)
The CustomPollerAssignmentID Column had to be cast since it natively a PK and a uniqueidentifier (see image)
What must be done to have the statement evaluate properly when passes to the sp_executesql?
I receive a syntax error as illustrated below
declare
#date datetime,
#query nvarchar(Max)
set #date = getdate()-4
set #query = --'Insert into [SolarWindsOrion].[dbo].[BWC_VPN_Hourly_Long_Store]
'SELECT * FROM [SolarWindsOrion].[dbo].[CustomPollerStatistics_Hourly]
where Cast(CustomPollerAssignmentID as nvarchar(max)) = 63FEB60-4516-4C1A-9A11-DB30ACA44301'
EXEC sp_executesql #query
UPDATE-->
I tried adding the single quotes.
While the statement does execute.. no results are returned. See Image below
you need to put it in quote like this '63FEB60-4516-4C1A-9A11-DB30ACA44301' , so your adhoc query would look like this :
declare
#date datetime,
#query nvarchar(Max)
set #date = getdate()-4
set #query = --'Insert into [SolarWindsOrion].[dbo].[BWC_VPN_Hourly_Long_Store]
'SELECT * FROM [SolarWindsOrion].[dbo].[CustomPollerStatistics_Hourly]
where Cast(CustomPollerAssignmentID as nvarchar(max)) = ''63FEB60-4516-4C1A-9A11-DB30ACA44301'''
EXEC sp_executesql #query

EXEC sp_executesql will work with Integers but not VarChars

I'm using EXEC sp_executesql for a dynamic query in SQL Server 2017.
I've tried various testing scenarios, and I can get results in my query (for other parameters) as long as the values passed in are Integers. So, that means, Location and Department testing works. However, I can't figure out if there's something I need to do differently for when I'm sending a NVARCHAR or DateTime.
Here's my stored procedure, with the NVARCHAR param. Do you see anything I'm doing wrong?
(
#tktitle NVARCHAR(200)
)
AS
BEGIN
Declare #SQL NVARCHAR(MAX)
Set #SQL = 'SELECT timekeep.tkinit, timekeep.tkfirst, timekeep.tklast,
timekeep.tkemdate, timekeep.tktitle, timekeep.tkloc, timekeep.tkdept
FROM abc.xyz'
IF #tktitle IS NOT NULL
Select #SQL = #SQL + 'AND ([tktitle] = #tktitle)'
EXEC sp_executesql #SQL, N'#tktitle varchar', #tktitle
END
I can identify at least three issues:
You need to specify a length for varchar when passing it as a parameter.
You also need a space before the AND and the AND should be a WHERE.
You need to assign the parameter in the execute call.
So:
IF #tktitle IS NOT NULL
Select #SQL = #SQL + ' WHERE ([tktitle] = #tktitle)';
-------------------------^ separator
EXEC sp_executesql #SQL, N'#tktitle varchar(200)', #tktitle=#tktitle;

How to exploit a SQL injection inside "IN" condition?

I am trying to exploit the following sql (in SQL Server 2014):
declare #maliciousSQL nvarchar(max);
set #maliciousSQL = '???'
exec ('SELECT SUM(quantity) from mytable where id in ' + #maliciousSQL );
How can parameter #maliciousSQL be crafted to run any arbitrary sql? Assume the task is to execute command 'truncate table othertable' - is it doable?
Thanks to anyone for help
SQL Injection looks like this:
declare #maliciousSQL nvarchar(max);
set #maliciousSQL = '(1); DELETE test1;'
exec ('SELECT SUM(quantity) from mytable where id in ' + #maliciousSQL );
Terminate the statement with a semicolon then write what you like
You can use this:
set #maliciousSQL = '(1); truncate table XXX;'
The entire point is to do not concatenate SQL statements and preferring to use parameterized queries.
Actually, the question title is misleading: you can't run DDL inside a DML statement, but a malicious caller can run multiple separate commands if you allows unsafe concatenation.
You need to set up the SQL before executing. I also recommend sp_executesql. So:
declare #maliciousSQL nvarchar(max);
declare #sql nvarchar(max);
set #maliciousSQL = '???'
set #sql = 'SELECT SUM(quantity) from mytable where id in ' + #maliciousSQL;
exec sp_executesql #sql;

Is it possible to set a part of a select statement in a variable

I have a query of which the select-part is really long. I'd like to split this in several pieces, especially because some parts are in there twice or even more often.
What I'd like is something like the following:
Declare #SQLPart as varchar(1000)
Set #SQLPart = 'Field1,
case ... as Field2,'
Select ..., #SQLPart, ... From .....
Unfortunately this results error messages. I tried something like EXEC(#SQLPart) as well but of course this also didn't work. How would I solve this?
Yes, dynamic sql and sp_executesql:
CREATE TABLE ##Temp (Field1 int, Field2 int)
Declare #SQLPart nvarchar(1000)
Set #SQLPart = N'Field1, Field2 '
DECLARE #SQL nvarchar(1000) = N'SELECT ' + #SQLPart + 'FROM ##Temp'
PRINT #SQL
EXEC sp_executesql #SQL
DROP TABLE ##Temp
Your SQL code must be nvarchar type.
Alse sp_executesql is better than EXECUTE function, when you have many similar queries, sp_executesql caches executaion plans, and it can be better in perfomance.
You can use dynamic sql here,and use a EXECUTE keyword to execute this dynamic query
Declare #SQLPart as varchar(1000)
Set #SQLPart = 'Field1,
case ... as Field2,'
EXECUTE ('SELECT ....,'+#SQLPart+',... FROM ...')
SQL Server does not support Macro-Substitution, so you would have to use Dynamic SQL.
Declare #SQL varchar(max) ='Select ... ' + #SQLPart + '... from ...'
Exec(#SQL)

Fully qualified table names with SP_ExecuteSql to access remote server

Trying to update a table on a linked server (SQL 2000/2005) but my server name will not be known ahead of time. I'm trying this:
DECLARE #Sql NVARCHAR(4000)
DECLARE #ParamDef NVARCHAR(4000)
DECLARE #SERVER_NAME VARCHAR(35)
SET #Sql = 'UPDATE
#server_name_param.dba_sandbox.dbo.SomeTable
SET SomeCol=''data'''
SET #ParamDef = N'#server_name_param VARCHAR(35)'
print #Sql
exec sp_executesql #Sql, #ParamDef, #server_name_param=#SERVER_NAME
Which returns this:
UPDATE
#server_name_param.dba_sandbox.dbo.SomeTable
SET SomeCol='data'
Msg 170, Level 15, State 1, Line 2
Line 2: Incorrect syntax near '.'.
Any ideas? Is there anyway I view the SQL statement that is being executed after the parameters are bound?
You'll have to do this, it can't be parameterised
....
SET #Sql = 'UPDATE ' + #server_name_param + '.dba_sandbox.dbo.SomeTable SET SomeCol=''data'''
....
Edit: There is another way which I used back in my pure DBA days
EXEC sp_setnetname 'AdhocServer', #SERVER_NAME
UPDATE AdhocServer.dba_sandbox.dbo.SomeTable SET SomeCol 'data'
EXEC sp_setnetname 'AdhocServer', 'MeaninglessValue'
sp_setnetname is there from SQL Server 2000 to 2008
Edit2. Permissions:
Try EXECUTE AS LOGIN = 'login_name' , where login_name is a superuser
I've not really used this (I use "AS USER" for testing), so not sure of the finer points...
Edit 3: for concurrency, consider using sp_getapplock and a stored procedure, or some other concurrency control mechanism.
You cannot do this with parameters directly - you would have to use dynamic SQL, or send the server name as a parameter to an SP that does dynamic SQL:
DECLARE #template NVARCHAR(4000)
DECLARE #Sql NVARCHAR(4000)
DECLARE #SERVER_NAME VARCHAR(35)
SET #template = 'UPDATE {#server_name_param}.dba_sandbox.dbo.SomeTable SET SomeCol=''data'''
SET #sql = REPLACE(#template, '{#server_name_param}', #SERVER_NAME)
print #Sql
exec sp_executesql #Sql -- OR EXEC ( #sql )
I like gbn's trick. I didn't know that one and I'm gonna have to research that some more.
Since I didn't know that trick, I've had to use dynamic sql in similar situations in the past (like what Cade posted). When that happens I would normally query an information schema view to make sure the parameter value is a real database object before building the query. That way I'm sure it's not an injection attempt.