How to pass comma separated list in sp_executesql - in-clause

I want to use IN opeartor in sp_executesql, but facing the error that Incorrect syntax near '#TagIndexListToAdjust'.
This error is due to single quotes at both side of the parameter value '(1,2,3)'.
I need to fix it with in only the sp_executesql as this query is generated by C# model class.
USE [master]
GO
IF EXISTS (SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[Persons]') AND type in (N'U'))
DROP TABLE [dbo].Persons
GO
USE [master]
GO
CREATE TABLE Persons
(
commaList nvarchar(MAX),
);
insert into Persons values ('1')
insert into Persons values ('2')
insert into Persons values ('3')
GO
exec sp_executesql N'
Select *
from Persons
where commaList in #TagIndexListToAdjust',
N'#TagIndexListToAdjust varchar(67)',
#TagIndexListToAdjust='(1,2,3)'
Any help will be appriciated in fixing the error.

Use 2 quotation marks.. one for escaping the other one.

Related

Concat "?" when insert new register in SQL

how are all? I have a problem, it's very strange. I have this script in SQL:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Pasajes]') AND
type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Pasajes]([Observaciones] Varchar(MAX));
END;
INSERT INTO Pasajes(Observaciones)
VALUES ('​Que sea hasta puente saavedra, porfa )' );
INSERT INTO Pasajes(Observaciones)
VALUES ('​Si puede ser El Pulqui, mejor');
INSERT INTO Pasajes(Observaciones)
VALUES ('​A puente Saavedra.');
When i run script, i can insert without problem. But if i go to see the rows in table Pasajes, i found this:
I don't know why concat "?" at the beggining of String. Thank for your help!

Error converting varchar to bigint

I got the error where my data type is varchar, then I want to insert value/input in textboxt = 'smh85670s'.
It appear to be error. As far as I know varchar can accept characters and numbers, but why does it keep throwing this error?
If I insert value '123456' the table can accept that value.
Please guide me. What data type should I use?
Assuming that you are using Stored procedures (which have an insert query) or directly firing an insert query into DB, you must be sending all data as parameters like say #param1, #param2,...
Your insert query will be like
INSERT INTO Sometable ( Amount, textbox,... )
SELECT #param1, #param2 ,...
Just add a cast in this query to make it work
INSERT INTO Sometable ( Amount, textbox,... )
SELECT #param1, CAST(#param2 as varchar),...

SMSS 'Invalid column name'

Before you reprimand me about how 'this has been asked here:', I'd like to point out I did indeed google. I even went to page 3 in some cases. shudders
So here's the deal:
I'm trying to audit a database we have, setting triggers for UPDATE, INSERT, DELETE statements for several tables. The triggers are created, and linked, succesfully. Each trigger executes a stored-procedure that inserts required data into our tick_audit table.
This information is:
user_account; to store who changed something
client_id; to store which client had their data changed
date_time; the date of the edit
table_name; the name of the table that was changed
table_record_id; the id of the record that was changed
descr; a description of why something was changed
remote_ip_address; so we can keep tabs where something was changed (internal or external)
The table also has a PRIMARY_KEY, AUTO_INCREMENT id field.
When I try to create the stored-procedure
create procedure update_tick_user
#UserId varchar(32),
#ClientId varchar(32),
#Table varchar(64),
#TableRecord varchar(512),
#Descr varchar(128),
#RemoteIP varchar(16)
as
begin
insert into tick_audit ('user_account', 'client_id', 'date_time', 'table_name', 'table_record_id', 'descr', 'remote_ip_address')
values
(#UserId, #ClientId, getdate(), #Table, #TableRecord, #Descr, #RemoteIP)
end;
I get the following error(s):
Msg 207, Level 16, State 1, Procedure update_tick_user, Line 10
Invalid column name 'user_account'.
This repeats for each column. When I run
exec sp_columns tick_audit
I get all the columns from tick_audit, and even copying their names into the column-fields for the insert, I get the above-mentioned errors. I even get the errors when I simply run
insert into tick_audit
('user_account', 'client_id', 'date_time', 'table_name', 'table_record_id', 'descr', 'remote_ip_address')
values
('', '', getdate(), '', '', '', '')
Whenever I try an insert, update or delete on a different table, I get no errors. Is there anything I could try to find out if there's a fault in my table, or some super-secret hocus-pocus, ritual-esque method?
Here's what I've tried so far:
Drop the table (On my feet, many many times), re-create it.
Google for three hours
Asked my co-workers
Put on my thinking cap
Check if columns actually exists (through exec, select)
Crossing my fingers and hoping someone can help me.
Remove ' to make insert as below
insert into tick_audit (user_account, client_id, date_time, table_name, table_record_id, descr, remote_ip_address)
values (#UserId, #ClientId, getdate(), #Table, #TableRecord, #Descr, #RemoteIP)
Use brackets instead of quotes:
insert into tick_audit ([user_account], [client_id], [date_time], [table_name], [table_record_id], [descr], [remote_ip_address])
values (#UserId, #ClientId, getdate(), #Table, #TableRecord, #Descr, #RemoteIP)
Single quote are for literals. For delimiting object names you should use brackets or double quotes but you can use double quotes only when QUOTED_IDENTIFIER is set to ON.
Do not use single quotes arround column names.
create procedure update_tick_user
#UserId varchar(32),
#ClientId varchar(32),
#Table varchar(64),
#TableRecord varchar(512),
#Descr varchar(128),
#RemoteIP varchar(16)
as
begin
insert into tick_audit (user_account, client_id, date_time, table_name, table_record_id, descr, remote_ip_address)
values
(#UserId, #ClientId, getdate(), #Table, #TableRecord, #Descr, #RemoteIP)
end;

Using a string of quoted values in a variable for a SQL WHERE CLAUSE

The answer escapes me...maybe because it is not possible...
Example that works...
SELECT * FROM TABLEA WHERE FIELD1 IN ('aaa','bbb','ccc')
Example that does not work...
Attempt to leverage variable so that I can define the values once in a string of statements
DECLARE #ListValues VARCHAR(50)
SET #ListValues = '''aaa'',''bbb'',''ccc'''
SELECT * FROM TABLEA WHERE FIELD1 IN (#ListValues)
This is is obviously only a small part of the equation and for other reasons...
I cannot leverage a table for the values and change this to a true sub-query
The closest question I could find was this one... but does not cover my requirements obviously...
Storing single quotes in varchar variable SQL Server 2008
Thanks in advance.
You can do this using dynamic SQL:
DECLARE #ListValues VARCHAR(MAX)
,#SQL VARCHAR(MAX)
SELECT #ListValues = '''aaa'',''bbb'',''ccc'''
,#SQL = 'SELECT * FROM TABLEA WHERE FIELD1 IN ('+#ListValues+')'
EXEC (#SQL)
It doesn't work because the IN operator expects a list of items - here strings.
What you're supplying with your #ListValues variable however is a single string - not a list of strings.
What you could do is use a table variable and store your values in it:
DECLARE #ListOfValues TABLE (ItemName VARCHAR(50))
INSERT INTO #ListOfValues(ItemName)
VALUES('aaa'), ('bbb'), ('ccc')
SELECT *
FROM TABLEA
WHERE FIELD1 IN (SELECT ItemName FROM #ListOfValues)
Build your whole SQL query dynamically (say it's stored in a string variable #sql),
and then execute it with EXEC (#sql). Better yet, use the sp_executesql SP
because this approach is more secure (less prone to SQL injection) than EXEC.
See: sp_executesql
The IN operator in SQLServer expect a list of values, your variable is a single string, the query parsed will be different
SELECT * FROM TABLEA WHERE FIELD1 IN ('aaa','bbb','ccc')
SELECT * FROM TABLEA WHERE FIELD1 IN ("'aaa','bbb','ccc'")
Attention: the double quotes are there only for readability, to get the string with single quote in it.
if you know a programming language the first one is like searching in an array, the second is a string.
To store a list in your variable it need to a table
DECLARE #varTable TABLE (field1 varchar())
So that you can use it in your IN
SELECT * FROM TABLEA WHERE FIELD1 IN (SELECT field1 FROM #varTable)
To add values to the table variable use an INSERT statament like usual for tables.

How to concatenate variables into SQL strings

I need to concatenate a variable table name into my SQL query such as the following...
ALTER FUNCTION fn_myfunction(#KeyValue text)
BEGIN
INSERT INTO #tmpTbl1
SELECT #KeyValue AS fld1
FROM tbl + #KeyValue + KeyValue.fld1
I also attempted the following but it told me I had to declare the table variable?
ALTER FUNCTION fn_myfunction(#KeyValue text, #KeyTable text)
FROM #KeyTable.fld1
You can accomplish this (if I understand what you are trying to do) using dynamic SQL.
The trick is that you need to create a string containing the SQL statement. That's because the tablename has to specified in the actual SQL text, when you execute the statement. The table references and column references can't be supplied as parameters, those have to appear in the SQL text.
So you can use something like this approach:
SET #stmt = 'INSERT INTO #tmpTbl1 SELECT ' + #KeyValue
+ ' AS fld1 FROM tbl' + #KeyValue
EXEC (#stmt)
First, we create a SQL statement as a string. Given a #KeyValue of 'Foo', that would create a string containing:
'INSERT INTO #tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'
At this point, it's just a string. But we can execute the contents of the string, as a dynamic SQL statement, using EXECUTE (or EXEC for short).
The old-school sp_executesql procedure is an alternative to EXEC, another way to execute dymamic SQL, which also allows you to pass parameters, rather than specifying all values as literals in the text of the statement.
FOLLOWUP
EBarr points out (correctly and importantly) that this approach is susceptible to SQL Injection.
Consider what would happen if #KeyValue contained the string:
'1 AS foo; DROP TABLE students; -- '
The string we would produce as a SQL statement would be:
'INSERT INTO #tmpTbl1 SELECT 1 AS foo; DROP TABLE students; -- AS fld1 ...'
When we EXECUTE that string as a SQL statement:
INSERT INTO #tmpTbl1 SELECT 1 AS foo;
DROP TABLE students;
-- AS fld1 FROM tbl1 AS foo; DROP ...
And it's not just a DROP TABLE that could be injected. Any SQL could be injected, and it might be much more subtle and even more nefarious. (The first attacks can be attempts to retreive information about tables and columns, followed by attempts to retrieve data (email addresses, account numbers, etc.)
One way to address this vulnerability is to validate the contents of #KeyValue, say it should contain only alphabetic and numeric characters (e.g. check for any characters not in those ranges using LIKE '%[^A-Za-z0-9]%'. If an illegal character is found, then reject the value, and exit without executing any SQL.
You could make use of Prepared Stements like this.
set #query = concat( "select name from " );
set #query = concat( "table_name"," [where condition] " );
prepare stmt from #like_q;
execute stmt;