TSQL varchar string manipulation - tsql

I have a variable which contains the following string: AL,CA,TN,VA,NY
I have no control over what I get in that variable (comes from reporting services)
I need to make it look like this: 'AL','CA','TN','VA','NY'
How do I do this?

declare #x varchar(50) = 'AL,CA,TN,VA,NY'
select '''' + REPLACE(#x, ',', ''',''') + ''''

I ended up doing something very similar that I thought I'd post. (I'll give credit to Mitch however)
This takes care of the middle:
SET #StateList = REPLACE(#StateList, ',', ''',''')
Then quote the edges:
SET #WhereClause1 = #WhereClause1 + 'AND customerState IN (''' + #StateList + ''') '

For a more generic answer, when you don't know what your output will look like exactly, use regular expressions.
This would let you you match on something like [A-Z]{2} and replace it with '$&'.
A commenter suggested this is overkill for this task - agreed, if you can guarantee you will always get a string like that. However, other people find these question pages later with similar, but not exact, problems, so other options are helpful to have.

Don't bother with dynamic sql.
You need to convert the string to a table
so
A,B,C,D
becomes
Value
A
B
C
D
using a function like
http://www.sqlusa.com/bestpractices/training/scripts/splitcommadelimited/
then you can use CROSS APPLY (which is like joining to a table, but a table created by a function) or you can just put it in a table variable and join to that

I want to know y does the following script run in SQL and not in T-SQL
DECLARE #tblName varchar(30)
SET #tblName = CONVERT(VARCHAR(20),GETDATE(),112) + 'Table'
DECLARE #sql nvarchar(4000)
SELECT #sql =
'CREATE TABLE "' + #tblName + '"
(
ID VARCHAR(15),
Name VARCHAR(15)
)'
EXEC(#sql)
go
it gives you the error
Msg 170, Sev 15: Line 1: Incorrect syntax near '20090714Table'. [SQLSTATE 42000]

Related

SSIS How to Use Parameters with IN Clause

emailVariable = john#example.com, sally#testing.com
SQL Query:
select *
from [table_1]
where email in (?);
Parameter set to use emailVariable.
This returns nothing, both emails are valid.
Am I doing something wrong?
I am using an OLE DB Source Editor.
You can also use string_split:
declare #stringToSplit varchar(255) = 'john#example.com, sally#testing.com'
select *
from [table_1]
where email in (
select ltrim(rtrim(value)) from string_split(?,',')
)
String_Split will return a table of values based on your input string and the delimiter. In your case you also need ltrim and rtrim because of extra spaces.
This is a classic mistake. Although the following works:
where email in ('john#example.com','sally#testing.com')
you cannot use one variable to put a multitude of values. The comma(s) is not part of the value string, it is considered code. What you can do is use dynamic sql:
declare #emailVariable nvarchar(max)=N'''john#example.com'',''sally#testing.com''' -- notice the escaped quotes
declare #sql nvarchar(max)
set #sql=N'select * from [Table_1] where email in (' + #emailVariable + ')'
exec(#sql)

Dynamic SQL used in Case Statement in Stored Procedure

I am developing a proof of concept application as requested by a client to act as a automation system that does an initial scrub of input data. One of the steps in this process is to look at a description field and determine how that maps to the clients provided description/code list to get a specific code. I initially thought of just using a giant case statement, however, due to the input data not always being the same, I figured I would incorporate dynamic SQL to pass the column name of the input description field. Below is a snippet of code thus far (the ellipses (...) represent code continuing for an unknown distance at this point and are not truly in the code.):
DECLARE #DESC VARCHAR(100)
SET #DESC = '<sourceDescrptionColumn>'
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = '
SELECT
<sourceDescrptionColumn>
,CASE WHEN( ' + #DESC + ' LIKE ''%club%'') THEN ''00''
WHEN( ' + #DESC + ' LIKE ''%ball%'' AND ' + #DESC + ' NOT LIKE ''%basket%'' AND ' + #DESC + ' NOT LIKE ''%base%'') THEN ''01''
WHEN( ' + #DESC + ' LIKE ''%glov%'' AND ' + #DESC + ' NOT LIKE ''%bat%'' AND ' + #DESC + ' NOT LIKE ''%golf%'' AND ...) THEN ''02''
...
ESLE ''99''
END AS DESC_CODE
FROM <someInputTable>'
This will work for roughly the first 30 or so "WHEN" statements and then it begins to fail. It appears to be an issue with my use of single quotes, but I cannot seem to locate the source.
Are there limits to the number of ANDs or WHENs that can be used in this type of SQL usage? Is there a better alternative?
What could be happening is that your data is being truncated as others have mentioned. Now unless you are using Unicode characters, I'd recommend sticking with only Varchar. Either way, just set all your variables to max and that should fix your truncation errors. And the reason you would think it was your quotes, is because if truncate the end quotes, of course you'll have unclosed quotes!
DECLARE #Desc VARCHAR(MAX) = '<sourceDescrptionColumn>';
DECLARE #SQL VARCHAR(MAX);

T-SQL: issue with string concat

I have a set of audio files with names GreenLine1.mp3, GreenLine2.mp3 e.t.c. I'm going to write them into a table as BLOB (I use MS SQL Server'08), here's my sql request:
DECLARE #aud AS VARBINARY(MAX)
DECLARE #num AS INT
-- Load the audio data
SET #num=1
WHILE (#num<38)
BEGIN;
SELECT #aud = CAST(bulkcolumn AS VARBINARY(MAX))
FROM OPENROWSET(
BULK
'C:\Users\Ilya\folder\GreenLine' + CAST(#num AS VARCHAR) + '.mp3',
SINGLE_BLOB ) AS x
-- Insert the data to the table
INSERT INTO Mb2.dbo.Audios (Id, [Content])
SELECT NEWID(), #aud
SET #num = #num + 1
END;
I have an error: Incorrect syntax near '+', expecting ',' or ')'.
If I try to write
'C:\Users\Ilya\folder\GreenLine' +
CAST(#num AS VARCHAR) + '.mp3'
into a variable and put it after BULK, I get Incorrect syntax near #variable, expected STRING, or TEXT_LEX
You can't parametrise or concatenate the parameters of OPENROWSET. It is constant values only.
You'll have to use dynamic SQL and a temp table, or consider using SSIS for example
This article pointed me in the right direction when I had the same issue with OPENQUERY:
https://web.archive.org/web/20120724073530/http://consultingblogs.emc.com/jamespipe/archive/2007/06/28/SQL-Server-2005_3A00_-Passing-variables-into-an-OPENQUERY-argument.aspx
Basically, you can wrap the entire statement in a variable (nvarchar), including the openrowset, and run exec sp_executesql #sql. It gets a little ugly to read around the 's though, because you'll have to escape them with ''.

Why does concatenating strings in the argument of EXEC sometimes cause a syntax error in T-SQL?

In MS SQL Server Management Studio 2005, running this code
EXEC('SELECT * FROM employees WHERE employeeID = ' + CAST(3 AS VARCHAR))
gives this error: Incorrect syntax near 'CAST'
However, if I do this, it works:
DECLARE #temp VARCHAR(4000)
SET #temp = 'SELECT * FROM employees WHERE employeeID = ' + CAST(3 AS VARCHAR)
EXEC(#temp)
I found an explanation here: T-SQL: Cannot pass concatenated string as argument to stored procedure
According to the accepted answer, EXEC can take a local variable or a value as its argument, but not an expression.
However, if that's the case, why does this work:
DECLARE #temp VARCHAR(4000)
SET #temp = CAST(3 AS VARCHAR)
EXEC('SELECT * FROM employees WHERE employeeID = ' + #temp)
'SELECT * FROM employees WHERE employeeID = ' + #temp sure looks like an expression to me, but the code executes with no errors.
The documentation states that EXEC can take either a string variable, a constant T-SQL string, or combinations/concatenations of both of them.
Your "why does this work" example uses a concatenation of a constant T-SQL string and a string variable, and so is perfectly legal.

sql variables

Can somebody help me figure out why the sql statement doesn't like the following line
' and ' + #SearchCat + 'like '%'+#Keywords+'%''. It has to do with the number of single quotes but I can't figure out. How do the quotes work. What's the logic?
DECLARE #strStatement varchar(550)
declare #state as varchar(50)
declare #district as varchar(50)
declare #courttype as varchar(50)
declare #SearchCat as varchar(50)
declare #KeyWords as varchar (50)
select #State ='FL'
select #district = '11'
select #courtType = '1'
select #SearchCat='CaseNumber'
select #KeyWords='File'
select #strStatement= 'SELECT CaseNumber FROM app_Case
where State ='''+ #State+
''' and District='''+ #District+
' and ' + #SearchCat + 'like '%'+#Keywords+'%''
exec (#strStatement)
I was missing a space before 'like'
You've also got the wrong number of single-quotes around your ‘%’ characters, which will confuse it.
Incidentally, you've made yourself a nice little SQL injection security hole there, from inside SQL itself! If one of the parameters contains an apostrophe your sqlStatement will break and any rogue SQL in the parameter name would be executed.
You can use the REPLACE function to double up single quotes to prevent this attack:
' AND '+QUOTENAME(#SearchCat)+' LIKE ''%'+REPLACE(#Keywords, '''', '''''')+'%''...'
(The QUOTENAME is needed if the column name contains out-of-band characters or is a reserved word.)
A cleaner (but quite verbose) approach to generating the SQL than tediously REPLACEing every string literal yourself is to use sp_executesql. For example:
SELECT #strStatement= N'
SELECT #Number= CaseNumber FROM app_Case
WHERE State=#State AND District=#District
AND '+QUOTENAME(#SearchCat)+N' LIKE ''%''+#Keywords+''%''
';
SELECT #params= N'#State varchar(50), #District varchar(50), #Keywords varchar(50), #Number int OUTPUT';
EXECUTE sp_executesql #strStatement, #params, #State, #District, #Keywords, #Number OUTPUT;
Incidentally if #searchCat can only have a small number of different values, you can use a workaround to avoid having to do any of this laborious dynamic-SQL nonsense at all:
SELECT CaseNumber FROM app_Case
WHERE State=#State AND District=#District
AND CASE #searchCat
WHEN 'searchableColumnA' THEN searchableColumnA
WHEN 'searchableColumnB' THEN searchableColumnB
END LIKE '%'+#Keywords+'%';
See this rather good exploration of dynamically-created SQL statements in T-SQL for more background and some of the risks you face.
I figure it out. I was missing a space before 'like'