How Do I Use a Variable in a Select Statement? - sql-server

When I run the following code I get the error : Incorrect syntax near '#num_to_remove'.
Any idea why this doesn't work?
Thanks in advance,
Matt
DECLARE #num_to_remove INT
SET #num_to_remove = 2
-- get em_ids for records to delete
WITH em_ids
AS (SELECT TOP #num_to_remove em_id
FROM irs_self_cert_em sc
WHERE sc.date_cert_loc IS NULL
AND sc.date_first_cert_email_sent < '2014-10-03')
SELECT * FROM em_ids

In regular tSQL, you can only use variables to represent values, not column names or other objects. I know the numeric value for a "TOP" clause seems like it should qualify but it doesn't.
To use a variable in this way, you have to do Dynamic SQL.

Try this (Note: I haven't tested it. You can try similar this)
DECLARE #num_to_remove INT
SET #num_to_remove = 2
-- get em_ids for records to delete
EXEC
(
'WITH em_ids
AS (SELECT TOP ' + CAST(#num_to_remove AS varchar(10) + 'em_id
FROM irs_self_cert_em sc
WHERE sc.date_cert_loc IS NULL
AND sc.date_first_cert_email_sent < ''2014-10-03'')
'
)

Related

Searching for multiple patterns in a string in T-SQL

In t-sql my dilemma is that I have to parse a potentially long string (up to 500 characters) for any of over 230 possible values and remove them from the string for reporting purposes. These values are a column in another table and they're all upper case and 4 characters long with the exception of two that are 5 characters long.
Examples of these values are:
USFRI
PROME
AZCH
TXJS
NYDS
XVIV. . . . .
Example of string before:
"Offered to XVIV and USFRI as back ups. No response as of yet."
Example of string after:
"Offered to and as back ups. No response as of yet."
Pretty sure it will have to be a UDF but I'm unable to come up with anything other than stripping ALL the upper case characters out of the string with PATINDEX which is not the objective.
This is unavoidably cludgy but one way is to split your string into rows, once you have a set of words the rest is easy; Simply re-aggregate while ignoring the matching values*:
with t as (
select 'Offered to XVIV and USFRI as back ups. No response as of yet.' s
union select 'Another row AZCH and TXJS words.'
), v as (
select * from (values('USFRI'),('PROME'),('AZCH'),('TXJS'),('NYDS'),('XVIV'))v(v)
)
select t.s OriginalString, s.Removed
from t
cross apply (
select String_Agg(j.[value], ' ') within group(order by Convert(tinyint,j.[key])) Removed
from OpenJson(Concat('["',replace(s, ' ', '","'),'"]')) j
where not exists (select * from v where v.v = j.[value])
)s;
* Requires a fully-supported version of SQL Server.
build a function to do the cleaning of one sentence, then call that function from your query, something like this SELECT Col1, dbo.fn_ReplaceValue(Col1) AS cleanValue, * FROM MySentencesTable. Your fn_ReplaceValue will be something like the code below, you could also create the table variable outside the function and pass it as parameter to speed up the process, but this way is all self contained.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION fn_ReplaceValue(#sentence VARCHAR(500))
RETURNS VARCHAR(500)
AS
BEGIN
DECLARE #ResultVar VARCHAR(500)
DECLARE #allValues TABLE (rowID int, sValues VARCHAR(15))
DECLARE #id INT = 0
DECLARE #ReplaceVal VARCHAR(10)
DECLARE #numberOfValues INT = (SELECT COUNT(*) FROM MyValuesTable)
--Populate table variable with all values
INSERT #allValues
SELECT ROW_NUMBER() OVER(ORDER BY MyValuesCol) AS rowID, MyValuesCol
FROM MyValuesTable
SET #ResultVar = #sentence
WHILE (#id <= #numberOfValues)
BEGIN
SET #id = #id + 1
SET #ReplaceVal = (SELECT sValue FROM #allValues WHERE rowID = #id)
SET #ResultVar = REPLACE(#ResultVar, #ReplaceVal, SPACE(0))
END
RETURN #ResultVar
END
GO
I suggest creating a table (either temporary or permanent), and loading these 230 string values into this table. Then use it in the following delete:
DELETE
FROM yourTable
WHERE col IN (SELECT col FROM tempTable);
If you just want to view your data sans these values, then use:
SELECT *
FROM yourTable
WHERE col NOT IN (SELECT col FROM tempTable);

Converting nvarchar to numeric

I have variable called #prmclientcode which is nvarchar. The input to this variable can be a single client code or multiple client codes separated by comma. For e.g.
#prmclientcode='1'
or
#prmclientcode='1,2,3'.
I am comparing this variable to a client code column in of the tables. The data type of this column is numeric(6,0). I tried converting the variable data type like below
SNCA_CLIENT_CODE IN ('''+convert(numeric(6,0),#prmclientcode+''')) (The query is inside a dynamic sql).
But when I try executing this I get the error
Arithmetic overflow error converting nvarchar to data type numeric.
Can anyone please help me here!
Thanks!
You need to convert the numeric(6,0) column to nvarchar data type. You can use below scrip to convert it to nvarchar, before processing:
SNCA_CLIENT_CODE IN ('''+convert(cast( numeric(6,0) as nvarchar(max) ),#prmclientcode+'''))
Please try with the below code snippet.
DECLARE #ProductTotals TABLE
(
ProductID int
)
INSERT INTO #ProductTotals VALUES(1)
INSERT INTO #ProductTotals VALUES(11)
INSERT INTO #ProductTotals VALUES(3)
DECLARE #prmclientcode VARCHAR(MAX)='1'
SELECT * FROM #ProductTotals
SELECT * FROM #ProductTotals WHERE CHARINDEX(',' + CAST(ProductID AS VARCHAR(MAX)) + ',' , ',' + ISNULL(#prmclientcode,ProductID) + ',') > 0
Let me know if any concern.
use following code in order to separate your variable:
DECLARE
#T VARCHAR(100) = '1,2,3,23,342',
#I int = 1
;WITH x(I, num) AS (
SELECT 1, CHARINDEX(',',#T,#I)
UNION ALL
SELECT num+1,CHARINDEX(',',#T,num+1)
FROM x
WHERE num+1<LEN(#T)
AND num<>0
)
SELECT SUBSTRING(#T,I,CASE WHEN num=0 THEN LEN(#T)+1 ELSE num END -I)
FROM x
Use can use either table function or dynamic sql query, both options will work.
Let me know if you need more help

how to check particular ID is present in string

I want to check if a ID is present or not in a set of multiple ID.
Example
if id 5 is present in multiple id list like '1,2,3,4,5'
use CHARINDEX to return the index of the searched value.
Declare #MyString varchar(50)
Set #MyString = '1,2,3,4,5'
IF CHARINDEX('5',ContactName) > 0
Begin
Print '5 Exists'
End
Else
Begin
Print '5 Does not exists'
End
select count(*) FROM table where id = '5';
If it returns more than 0 means it's present.
If you are talking about sql this query will work for you, if you get nothing it means searching id is not there in the list else there.
SELECT * FROM journal_pulses WHERE mood_credentials in (2,27)
SELECT column FROM table WHERE CHARINDEX(',5,',(',' + column + ',')) > 0
Fiddle
One good solution in this context could be to store the values with leading and trailing comma, as:
',1,2,3,4,5,'
So, even if you store one value, store it as:
',5,'
This will help you look for required value as:
SELECT column FROM table WHERE column like '%,5,%';
Or
SELECT column FROM table WHERE CHARINDEX(',5,',(',' + column + ',')) > 0
Also, using this solution you can uniquely identify different values, given that the string does not contain duplicate values.
So, it is easy to identify 5, 50 and 350 from:
',5,50,150,250,350,450,500,'
I am not sure if you can change how the values can be stored. Please read this answer in light of the context of the question - as a starting point and not as a copy-paste solution.
I have tried something like this
DECLARE #item VARCHAR(50)
SET #ExpressionToSearch = '23,12'
SET #item = '23'
SELECT COUNT(*) from dbo.Split(#ExpressionToSearch,',')
WHERE ',' + (#ExpressionToSearch) + ','
LIKE '%'+#item +'%'
This scenario will return output greater than 0

How to add column dynamically in where clause

I want to include column in where clause depending on the condition.
e.g
select * From emp
where id=7,
and if(code is not null) then code=8;
how can i do this in sql server
If I understand you correct, you could make use of COALESCE.
COALESCE()
Returns the first nonnull expression
among its arguments.
SQL Statement
SELECT *
FROM emp
WHERE id=7
AND code = COALESCE(#code, code)
If code is a column rather than a variable the query in your question would be rewritten as follows.
SELECT *
FROM emp
WHERE id=7 AND (code IS NULL OR code=8)
You'll probably have to create a query dynamically, as a string, and then use the Execute method to actually execute it. This approach has some potentially optimization issues, but it's commonly done. You might wan to Google T-SQL Dynamic Query, or something like that.
Also use this in case of Null value in #var1.
Select * from ABC where Column1 = isNull(#var1, Column1)
here is the example:
declare #SQL varchar(500)
declare #var1 int
set int = 1
set #SQL = 'Select * from ABC Where 1 = 1'
if(#var1 = 1)
set #SQL + #SQL ' And column1 = ' #var1
exec(#SQL)
You can use COALESCE function.
Well,
I don't know if i understood your question, but i guess that you want to include the value of the code column in the results.
If i'm right it can be done in the select part instead of the where clause. i. e.
Select ..., case when code is not null then 8 else code end as code from emp where id = 7
The other interpretation is that you want to filter rows where code <> 8,that would be
Select * from emp where id = 7 and (code is null OR code = 8)

SQL - ORDER BY in IF-ELSE CLAUSE

I have ONE table A and if the parameters #x is 0 i want to ordering A by date, else by Name.
This is an example:
declare #x int set #x = 0
if(#x=0)(
SELECT * FROM A
order by DATE
)
else
(
SELECT * FROM A
order by Name
)
When try to do it SQL Server return 2 egual error as
Incorrect syntax near the keyword 'order'.
What could i do?
Try this instead
SELECT * FROM A
order by
Case #x When 0 Then Cast(DATE as sql_variant) Else Name End
The casting is required for the dynamic sort to work with a date - I'm trying to find a reference, but you need a type that can be casted automatically to a common type, and date can't be done. Hence casting yourself.
Here's a link to some options. Note the section on mixed datatypes.
https://web.archive.org/web/20211029044050/https://www.4guysfromrolla.com/webtech/010704-1.shtml
declare #x int set #x = 0
if(#x=0)
begin
SELECT * FROM A
order by DATE
end
else
begin
SELECT * FROM A
order by Name
end
SELECT
*
FROM
A
ORDER BY
CASE WHEN #x = 0 THEN Date ELSE Name END
declare #x int
set #x = 0
IF (#x=0)
BEGIN
SELECT * FROM A order by DATE
END
ELSE
SELECT * FROM A order by Name
END
http://msdn.microsoft.com/en-us/library/aa933214(SQL.80).aspx
If your query becomes reasonably complex, then copying it into both sides of an IF/ELSE can becomes rather onerous. You can instead use a CASE expression in your ORDER BY. In this case, you might do:
SELECT * FROM A ORDER BY CASE WHEN #x=0 THEN DATE END, CASE WHEN #x<>0 THEN Name END
This can be expanded up to more conditions/columns. You just need to ensure that each CASE expression is returning a sensible data type.
Parentheses ( and ) are wrong. Use BEGIN and END instead.
DECLARE #x INT
SET #x = 0
IF (#x = 0) BEGIN
SELECT * FROM A ORDER BY DATE
END
ELSE BEGIN
SELECT * FROM A ORDER BY Name
END
Also, in my opinion, DATE as column name is not good idea.
As noted in the answers but not explained.
SQL uses BEGIN - END syntax instead of () or {} for block of commands

Resources