Like operator on input parameters in stored procedure - sql

I've just begun to add writing stored procedures to my SQL repertoire and I'm sure this is a noob question. Can someone point me in the right direction about how to use the like operator instead of the = operator in this scenario? The object of this is to find the first 3 common numbers out of a potential 5 digit number
stored procedure:
create proc dbo.MultipleDrugs (#condition varchar(50))
as
SELECT *, 100.0 * round(SUM(numwithanxiety) OVER (partition BY sex) / cast(TotalSexCounts AS float), 4) overAllPercentByGender
FROM (SELECT x.sex, injurylevel, SUM(sexandlevelcounts) OVER (partition BY x.sex) numByInjury, sum(sexandlevelcounts) AS numWithAnxiety,
100.0 * round(cast(sexandlevelcounts AS float) / SUM(sexandlevelcounts) OVER (partition BY x.sex), 4) AS percentWith, y.TotalSexCounts
FROM (SELECT sex, injurylevel, COUNT(*) AS sexAndLevelCounts
FROM (SELECT DISTINCT m.patid, m.sex, m.injurylevel
FROM members AS m INNER JOIN
icdClm AS ic ON ic.patid = m.PATID
--*****when I leave this operator as like and use
--*****equals in the exec statement it works
WHERE ic.icd LIKE #condition) t
GROUP BY sex, injurylevel) x INNER JOIN
(SELECT m.sex, COUNT(DISTINCT patid) TotalSexCounts
FROM members m
GROUP BY m.sex) y ON y.sex = x.sex
GROUP BY x.sex, x.injuryLevel, x.sexAndLevelCounts, y.TotalSexCounts) rr
go
This runs, but I cannot use the like operator
exec dbo.MultipleDrugs N'70700'
This is what I'd like to do
exec dbo.MultipleDrugs like '707%'

exec dbo.MultipleDrugs N'707%'

You don't need to provide the LIKE operator in your exec call - you've already got like in your SPROC. Consider instead a simpler case:
create proc FindObjects #Name NVARCHAR(50)
as
select *
from sys.objects
where name like #Name
And then calling this:
exec FindObjects 'sys%'
returns
sysrscols
sysrowsets
sysallocunits
sysfiles1
syspriorities
sysfgfrag
etc.

Change your SP so that the following occurs:
LIKE '%' + #condition + '%'

You Can also use like this in the procedure .
set #SearchString='%'+ #SearchString + '%'

Related

How to match an array of substrings to db [duplicate]

In SQL I (sadly) often have to use "LIKE" conditions due to databases that violate nearly every rule of normalization. I can't change that right now. But that's irrelevant to the question.
Further, I often use conditions like WHERE something in (1,1,2,3,5,8,13,21) for better readability and flexibility of my SQL statements.
Is there any possible way to combine these two things without writing complicated sub-selects?
I want something as easy as WHERE something LIKE ('bla%', '%foo%', 'batz%') instead of this:
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
I'm working with SQl Server and Oracle here but I'm interested if this is possible in any RDBMS at all.
There is no combination of LIKE & IN in SQL, much less in TSQL (SQL Server) or PLSQL (Oracle). Part of the reason for that is because Full Text Search (FTS) is the recommended alternative.
Both Oracle and SQL Server FTS implementations support the CONTAINS keyword, but the syntax is still slightly different:
Oracle:
WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0
SQL Server:
WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')
The column you are querying must be full-text indexed.
Reference:
Building Full-Text Search Applications with Oracle Text
Understanding SQL Server Full-Text
If you want to make your statement easily readable, then you can use REGEXP_LIKE (available from Oracle version 10 onwards).
An example table:
SQL> create table mytable (something)
2 as
3 select 'blabla' from dual union all
4 select 'notbla' from dual union all
5 select 'ofooof' from dual union all
6 select 'ofofof' from dual union all
7 select 'batzzz' from dual
8 /
Table created.
The original syntax:
SQL> select something
2 from mytable
3 where something like 'bla%'
4 or something like '%foo%'
5 or something like 'batz%'
6 /
SOMETH
------
blabla
ofooof
batzzz
3 rows selected.
And a simple looking query with REGEXP_LIKE
SQL> select something
2 from mytable
3 where regexp_like (something,'^bla|foo|^batz')
4 /
SOMETH
------
blabla
ofooof
batzzz
3 rows selected.
BUT ...
I would not recommend it myself due to the not-so-good performance. I'd stick with the several LIKE predicates. So the examples were just for fun.
you're stuck with the
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
unless you populate a temp table (include the wild cards in with the data) and join like this:
FROM YourTable y
INNER JOIN YourTempTable t On y.something LIKE t.something
try it out (using SQL Server syntax):
declare #x table (x varchar(10))
declare #y table (y varchar(10))
insert #x values ('abcdefg')
insert #x values ('abc')
insert #x values ('mnop')
insert #y values ('%abc%')
insert #y values ('%b%')
select distinct *
FROM #x x
WHERE x.x LIKE '%abc%'
or x.x LIKE '%b%'
select distinct x.*
FROM #x x
INNER JOIN #y y On x.x LIKE y.y
OUTPUT:
x
----------
abcdefg
abc
(2 row(s) affected)
x
----------
abc
abcdefg
(2 row(s) affected)
With PostgreSQL there is the ANY or ALL form:
WHERE col LIKE ANY( subselect )
or
WHERE col LIKE ALL( subselect )
where the subselect returns exactly one column of data.
Another solution, should work on any RDBMS:
WHERE EXISTS (SELECT 1
FROM (SELECT 'bla%' pattern FROM dual UNION ALL
SELECT '%foo%' FROM dual UNION ALL
SELECT 'batz%' FROM dual)
WHERE something LIKE pattern)
The inner select can be replaced by another source of patterns like a table (or a view) in this way:
WHERE EXISTS (SELECT 1
FROM table_of_patterns t
WHERE something LIKE t.pattern)
table_of_patterns should contain at least a column pattern, and can be populated like this:
INSERT INTO table_of_patterns(pattern) VALUES ('bla%');
INSERT INTO table_of_patterns(pattern) VALUES ('%foo%');
INSERT INTO table_of_patterns(pattern) VALUES ('batz%');
I would suggest using a TableValue user function if you'd like to encapsulate the Inner Join or temp table techniques shown above. This would allow it to read a bit more clearly.
After using the split function defined at: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx
we can write the following based on a table I created called "Fish" (int id, varchar(50) Name)
SELECT Fish.* from Fish
JOIN dbo.Split('%ass,%e%',',') as Splits
on Name like Splits.items //items is the name of the output column from the split function.
Outputs
1 Bass
2 Pike
7 Angler
8 Walleye
I'm working with SQl Server and Oracle here but I'm interested if this is possible in any RDBMS at all.
Teradata supports LIKE ALL/ANY syntax:
ALL every string in the list.
ANY any string in the list.
┌──────────────────────────────┬────────────────────────────────────┐
│ THIS expression … │ IS equivalent to this expression … │
├──────────────────────────────┼────────────────────────────────────┤
│ x LIKE ALL ('A%','%B','%C%') │ x LIKE 'A%' │
│ │ AND x LIKE '%B' │
│ │ AND x LIKE '%C%' │
│ │ │
│ x LIKE ANY ('A%','%B','%C%') │ x LIKE 'A%' │
│ │ OR x LIKE '%B' │
│ │ OR x LIKE '%C%' │
└──────────────────────────────┴────────────────────────────────────┘
EDIT:
jOOQ version 3.12.0 supports that syntax:
Add synthetic [NOT] LIKE ANY and [NOT] LIKE ALL operators
A lot of times, SQL users would like to be able to combine LIKE and IN predicates, as in:
SELECT *
FROM customer
WHERE last_name [ NOT ] LIKE ANY ('A%', 'E%') [ ESCAPE '!' ]
The workaround is to manually expand the predicate to the equivalent
SELECT *
FROM customer
WHERE last_name LIKE 'A%'
OR last_name LIKE 'E%'
jOOQ could support such a synthetic predicate out of the box.
PostgreSQL LIKE/ILIKE ANY (ARRAY[]):
SELECT *
FROM t
WHERE c LIKE ANY (ARRAY['A%', '%B']);
SELECT *
FROM t
WHERE c LIKE ANY ('{"Do%", "%at"}');
db<>fiddle demo
Snowflake also supports LIKE ANY/LIKE ALL matching:
LIKE ANY/ALL
Allows case-sensitive matching of strings based on comparison with one or more patterns.
<subject> LIKE ANY (<pattern1> [, <pattern2> ... ] ) [ ESCAPE <escape_char> ]
Example:
SELECT *
FROM like_example
WHERE subject LIKE ANY ('%Jo%oe%','T%e')
-- WHERE subject LIKE ALL ('%Jo%oe%','J%e')
Use an inner join instead:
SELECT ...
FROM SomeTable
JOIN
(SELECT 'bla%' AS Pattern
UNION ALL SELECT '%foo%'
UNION ALL SELECT 'batz%'
UNION ALL SELECT 'abc'
) AS Patterns
ON SomeTable.SomeColumn LIKE Patterns.Pattern
One approach would be to store the conditions in a temp table (or table variable in SQL Server) and join to that like this:
SELECT t.SomeField
FROM YourTable t
JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue
I have a simple solution, that works in postgresql at least, using like any followed by the list of regex. Here is an example, looking at identifying some antibiotics in a list:
select *
from database.table
where lower(drug_name) like any ('{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}')
u can even try this
Function
CREATE FUNCTION [dbo].[fn_Split](#text varchar(8000), #delimiter varchar(20))
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
Query
select * from my_table inner join (select value from fn_split('ABC,MOP',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';
Starting with 2016, SQL Server includes a STRING_SPLIT function. I'm using SQL Server v17.4 and I got this to work for me:
DECLARE #dashboard nvarchar(50)
SET #dashboard = 'P1%,P7%'
SELECT * from Project p
JOIN STRING_SPLIT(#dashboard, ',') AS sp ON p.ProjectNumber LIKE sp.value
May be you think the combination like this:
SELECT *
FROM table t INNER JOIN
(
SELECT * FROM (VALUES('bla'),('foo'),('batz')) AS list(col)
) l ON t.column LIKE '%'+l.Col+'%'
If you have defined full text index for your target table then you may use this alternative:
SELECT *
FROM table t
WHERE CONTAINS(t.column, '"bla*" OR "foo*" OR "batz*"')
I was also wondering for something like that. I just tested using a combination of SUBSTRING and IN and it is an effective solution for this kind of problem. Try the below query :
Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN ('bla', 'foo', 'batz')
In Oracle you can use a collection in the following way:
WHERE EXISTS (SELECT 1
FROM TABLE(ku$_vcnt('bla%', '%foo%', 'batz%'))
WHERE something LIKE column_value)
Here I have used a predefined collection type ku$_vcnt, but you can declare your own one like this:
CREATE TYPE my_collection AS TABLE OF VARCHAR2(4000);
I may have a solution for this, although it will only work in SQL Server 2008 as far as I know. I discovered that you can use the row-constructor described in https://stackoverflow.com/a/7285095/894974 to join a 'fictional' table using a like clause.
It sounds more complex then it is, look:
SELECT [name]
,[userID]
,[name]
,[town]
,[email]
FROM usr
join (values ('hotmail'),('gmail'),('live')) as myTable(myColumn) on email like '%'+myTable.myColumn+'%'
This will result in all users with an e-mail adres like the ones provided in the list.
Hope it's of use to anyone. The problem had been bothering me a while.
For Sql Server you can resort to Dynamic SQL.
Most of the time in such situations you have the parameter of IN clause based on some data from database.
The example below is a little "forced", but this can match various real cases found in legacy databases.
Suppose you have table Persons where person names are stored in a single field PersonName as FirstName + ' ' + LastName.
You need to select all persons from a list of first names, stored in field NameToSelect in table NamesToSelect, plus some additional criteria (like filtered on gender, birth date, etc)
You can do it as follows
-- #gender is nchar(1), #birthDate is date
declare
#sql nvarchar(MAX),
#subWhere nvarchar(MAX)
#params nvarchar(MAX)
-- prepare the where sub-clause to cover LIKE IN (...)
-- it will actually generate where clause PersonName Like 'param1%' or PersonName Like 'param2%' or ...
set #subWhere = STUFF(
(
SELECT ' OR PersonName like ''' + [NameToSelect] + '%'''
FROM [NamesToSelect] t FOR XML PATH('')
), 1, 4, '')
-- create the dynamic SQL
set #sql ='select
PersonName
,Gender
,BirstDate -- and other field here
from [Persons]
where
Gender = #gender
AND BirthDate = #birthDate
AND (' + #subWhere + ')'
set #params = ' #gender nchar(1),
#birthDate Date'
EXECUTE sp_executesql #sql, #params,
#gender,
#birthDate
If you are using MySQL the closest you can get is full-text search:
Full-Text Search, MySQL Documentation
This works for comma separated values
DECLARE #ARC_CHECKNUM VARCHAR(MAX)
SET #ARC_CHECKNUM = 'ABC,135,MED,ASFSDFSF,AXX'
SELECT ' AND (a.arc_checknum LIKE ''%' + REPLACE(#arc_checknum,',','%'' OR a.arc_checknum LIKE ''%') + '%'')''
Evaluates to:
AND (a.arc_checknum LIKE '%ABC%' OR a.arc_checknum LIKE '%135%' OR a.arc_checknum LIKE '%MED%' OR a.arc_checknum LIKE '%ASFSDFSF%' OR a.arc_checknum LIKE '%AXX%')
If you want it to use indexes, you must omit the first '%' character.
In Oracle RBDMS you can achieve this behavior using REGEXP_LIKE function.
The following code will test if the string three is present in the list expression one|two|three|four|five (in which the pipe "|" symbol means OR logic operation).
SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('three', 'one|two|three|four|five');
RESULT
---------------------------------
Success !!!
1 row selected.
Preceding expression is equivalent to:
three=one OR three=two OR three=three OR three=four OR three=five
So it will succeed.
On the other hand, the following test will fail.
SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('ten', 'one|two|three|four|five');
no rows selected
There are several functions related to regular expressions (REGEXP_*) available in Oracle since 10g version. If you are an Oracle developer and interested this topic this should be a good beginning Using Regular Expressions with Oracle Database.
No answer like this:
SELECT * FROM table WHERE something LIKE ('bla% %foo% batz%')
In oracle no problem.
In Teradata you can use LIKE ANY ('%ABC%','%PQR%','%XYZ%'). Below is an example which has produced the same results for me
--===========
-- CHECK ONE
--===========
SELECT *
FROM Random_Table A
WHERE (Lower(A.TRAN_1_DSC) LIKE ('%american%express%centurion%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%bofi%federal%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%american%express%bank%fsb%'))
;
--===========
-- CHECK TWO
--===========
SELECT *
FROM Random_Table A
WHERE Lower(A.TRAN_1_DSC) LIKE ANY
('%american%express%centurion%bank%',
'%bofi%federal%bank%',
'%american%express%bank%fsb%')
Sorry for dredging up an old post, but it has a lot of views. I faced a similar problem this week and came up with this pattern:
declare #example table ( sampletext varchar( 50 ) );
insert #example values
( 'The quick brown fox jumped over the lazy dog.' ),
( 'Ask not what your country can do for you.' ),
( 'Cupcakes are the new hotness.' );
declare #filter table ( searchtext varchar( 50 ) );
insert #filter values
( 'lazy' ),
( 'hotness' ),
( 'cupcakes' );
-- Expect to get rows 1 and 3, but no duplication from Cupcakes and Hotness
select *
from #example e
where exists ( select * from #filter f where e.sampletext like '%' + searchtext + '%' )
Exists() works a little better than join, IMO, because it just tests each record in the set, but doesn't cause duplication if there are multiple matches.
This is possible in Postgres using like or ilike and any or all with array. This is an example that worked for me using Postgres 9:
select id, name from tb_organisation where name ilike any (array['%wembley%', '%south%']);
And this prints out:
id | name
-----+------------------------
433 | South Tampa Center
613 | South Pole
365 | Bromley South
796 | Wembley Special Events
202 | Southall
111 | Wembley Inner Space
In T-SQL, this option works but it is not very fast:
CREATE FUNCTION FN_LIKE_IN (#PROC NVARCHAR(MAX), #ITENS NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS BEGIN
--Search an item with LIKE inside a list delimited by "," Vathaire 11/06/2019
DECLARE #ITEM NVARCHAR(MAX)
WHILE CHARINDEX(',', #ITENS) > 0 BEGIN
SET #ITEM = LEFT(#ITENS, CHARINDEX(',', #ITENS) - 1)
--IF #ITEM LIKE #PROC
IF #PROC LIKE #ITEM
RETURN #PROC --#ITEM --1
ELSE
SET #ITENS = STUFF(#ITENS, 1, LEN(#ITEM) + 1, '')
END
IF #PROC LIKE #ITENS RETURN #PROC --#ITEM --1
RETURN NULL --0
END
Query:
SELECT * FROM SYS.PROCEDURES
WHERE DBO.FN_LIKE_IN(NAME, 'PRC%,SP%') IS NOT NULL
you can do this dynamically for a large number of elements, at the expense of performance, but it works.
DECLARE #val nvarchar(256),
#list nvarchar(max) = 'one,two,three,ten,five';
CREATE table #table (FIRST_NAME nvarchar(512), LAST_NAME nvarchar(512));
CREATE table #student (FIRST_NAME nvarchar(512), LAST_NAME nvarchar(512), EMAIL
nvarchar(512));
INSERT INTO #student (FIRST_NAME, LAST_NAME, EMAIL)
SELECT 'TEST', ' redOne' ,'test.redOne#toto.com' UNION ALL
SELECT 'student', ' student' ,'student#toto.com' UNION ALL
SELECT 'student', ' two' ,'student.two#toto.com' UNION ALL
SELECT 'hello', ' ONE TWO THREE' ,'student.two#toto.com'
DECLARE check_cursor CURSOR FOR select value from STRING_SPLIT(#list,',')
OPEN check_cursor
FETCH NEXT FROM check_cursor INTO #val
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #val
IF EXISTS (select * from #student where REPLACE(FIRST_NAME, ' ','')
like '%' + #val + '%' OR REPLACE(LAST_NAME, ' ','') like '%' + #val + '%')
BEGIN
INSERT INTO #table (FIRST_NAME, LAST_NAME )
SELECT TOP 1 FIRST_NAME, LAST_NAME VALUE from #student where
REPLACE(FIRST_NAME, ' ','') like '%' + #val + '%' OR REPLACE(LAST_NAME, ' ','')
like '%' + #val + '%'
END;
FETCH NEXT FROM check_cursor INTO #val
END
CLOSE check_cursor;
DEALLOCATE check_cursor;
SELECT * FROM #table;
DROP TABLE #table;
DROP TABLE #student;
use cursor in SQL SERVER and execute for every value:
table sample:
create table Gastos_ConciliacionExcluida(IdRegistro int identity(1,1), MascaraTexto nvarchar(50), Activa bit default 1, Primary key (IDRegistro))
insert into Gastos_ConciliacionExcluida(MascaraTexto) Values ('%Reembolso%')
alter procedure SP_Gastos_ConciliacionExcluidaProcesar
as
declare cur cursor for select MascaraTexto From Gastos_ConciliacionExcluida where Activa=1
declare #Txt nvarchar(50)
open cur
fetch next from cur into #Txt
while ##Fetch_Status = 0
begin
update Gastos_BancoRegistro set PresumibleNoConciliable = 1
where Concepto like #txt
fetch next from cur into #Txt
end
close cur
deallocate cur
do this
WHERE something + '%' in ('bla', 'foo', 'batz')
OR '%' + something + '%' in ('tra', 'la', 'la')
or
WHERE something + '%' in (select col from table where ....)

How to write if exist statement that would run a different select depending if it exists or not

I am trying to convert a sql if exists statement into a SSRS valid format to run a report on CRM.
CRM report doesn't accept the report on upload if I have a if exists method, I'm having troubles figuring out what I can use in its place.
IF EXISTS(select * from dbo.FC where dbo.FC.ContactID in (select dbo.AV.so_contactid from dbo.AV))
begin
select [STATEMENT 1]
from dbo.AV CRMAF_so_AV join
dbo.FC c
on CRMAF_so_AV.so_contactid = c.ContactID;
end
else
begin
select [STATEMENT 2]
from dbo.AV CRMAF_so_AV join
dbo.FA c
on CRMAF_so_AV.so_contactid = c.AccountID;
end;
I want to be able to either run the select [STATEMENT 1] if the condition is true else I want to run select [STATEMENT 2]
I have managed to get this to work by doing a LEFT JOIN instead of a JOIN.
select [STATEMENT 1 + 2 all columns needed]
from dbo.AV CRMAF_so_AV
left join dbo.FC c on CRMAF_so_AV.so_contactid = c.ContactID;
left join dbo.FA a on CRMAF_so_AV.so_contactid = a.AccountID;
This now runs if its an account or a contact.
Try this -
You have to put your entire statement in #select1 and #select1.
declare #statement1 as varchar(max);
declare #statement2 as varchar(max);
SET #statement1 = 'SELECT 1'
SET #statement2 = 'SELECT 2'
IF EXISTS(select * from dbo.FC where dbo.FC.ContactID in (select dbo.AV.so_contactid from dbo.AV))
BEGIN
EXEC (#statement1)
END
ELSE
BEGIN
EXEC (#statement2)
END
Instead of using if exists can you not get a count of records that meet the criteria and then if its 1 or greater run a different query as apposed to if it was equal to 0.
let me know if I am missing something what you are trying to achieve.
sorry i am unable to put comments due to having a new account so my reputation is low.
I think you need something like this:
WITH PreSelection AS (
SELECT
AV.ID AS AVID,
(SELECT TOP(1) c.ContactID FROM dbo.FC c WHERE c.ContactID = AV.so_contactid) AS ContactID,
(SELECT TOP(1) c.ContactID FROM dbo.FA c WHERE c.AccountID = AV.so_contactid) AS AccountID
FROM dbo.AV
)
SELECT
AVID,
ISNULL(
CASE WHEN ContactID IS NULL
THEN (SELECT TOP(1) AccountName FROM dbo.FA WHERE FA.AccountID = AccountID)
ELSE (SELECT TOP(1) LTRIM(RTRIM(ISNULL(FirstName, '') + ' ' + ISNULL(LastName, ''))) FROM dbo.FC WHERE FC.ContactID = ContactID)
END, '') AS ContactName
FROM PreSelection
A few things to note:
When SSRS evaluates query it expects the resluts to always have the same structure in terms of column names and types.
So you CANNOT do something like this..
IF #x=#y
BEGIN
SELECT Name, Age FROM employees
END
ELSE
BEGIN
SELECT DeptID, DeptName, DeptEMpCOunt FROM departments
END
... as this will return different types and column names and column counts.
What you CAN DO is this..
DECLARE #t TABLE(resultType int, colA varchar(128), colB int, colC varchar(128), colD int)
IF #x=#y
BEGIN
INSERT INTO #t(resultType, colA, ColB)
SELECT 1 as resultType, Name, Age FROM employees
END
ELSE
BEGIN
INSERT INTO #t(resultType, colB, colC, colD)
SELECT 2 AS resultType, DeptID, DeptName, DeptEmpCount FROM departments
END
SELECT * FROM #t
Al we are doing is creating a table that can handle all variations of the data and putting the results into whatever columns can accommodate that data type.
This will always return the same data structure so SSRS will be happy, then you will need to handle which columns to display your data from based on what gets returned, hence why I added the result type to the results so you can test that from within the report.

Is there a possibility to Avoid multiple "OR" statement in Microsoft SQL?

I have a query that has to filter our results from a text field based on certain keywords used in the textline .. currently the SQL statement looks like the below.
and (name like '%Abc%') or (name like '%XYZ%') or (name like '%CSV%')...
Is there a way to avoid multiple or statements and achieve the same results?
You could put your filter keywords into a table or temp table and query them like this:
select a.*
from table_you_are_searching a
inner join temp_filter_table b
on charindex(b.filtercolumn,a.searchcolumn) <> 0
A slightly more shorthand way of doing this if you have a large amount of different patterns is to use EXISTS and a table value constructor:
SELECT *
FROM T
WHERE EXISTS
( SELECT 1
FROM (VALUES ('abc'), ('xyz'), ('csv')) m (match)
WHERE T.Name LIKE '%' + m.Match + '%'
);
A similar approach can be applied with table valued parameters. Since this is usually a requirement where people want to pass a variable number of search terms for a match it can be quite a useful approach:
CREATE TYPE dbo.ListOfString TABLE (value VARCHAR(MAX));
Then a procedure can take this type:
CREATE PROCEDURE dbo.GetMatches #List dbo.ListOfString READONLY
AS
BEGIN
SELECT *
FROM T
WHERE EXISTS
( SELECT 1
FROM #List AS l
WHERE T.Name LIKE '%' + l.value + '%'
);
END
Then you can call this procedure:
DECLARE #T dbo.ListOfString;
INSERT #T VALUES ('abc'), ('xyz'), ('csv');
EXECUTE dbo.GetMatches #T;
Just to give you another option you could also try this, an IN statement mixed with a PATINDEX:
Select *
from tbl
Where 0 not in (PATINDEX('%Abc%', name), PATINDEX('%XYZ%', name), PATINDEX('%CSV%', name))

How to use wildcards correctly in Stored Procedures

I have stored procedure where is 1 variable as input.
CREATE PROCEDURE spExample
#name NVARCHAR(60) = ''
AS
BEGIN
SELECT [name], [dom]
FROM [DomName]
INNER JOIN [Domain]
ON LEFT([name], 1)+'%' LIKE #name +'%'
END
For now It returning records from table if first letter of the record is as input. For example if record in table is "Test", excecuting following procedure : EXEC spExample 'T' It returns correct record.
But It should return record even If I type T, Te, Tes, or Test as procedure inputs. Any ideas?
I am not sure why you trying to join two tables using variable.
SELECT [name], [dom]
FROM [DomName]
INNER JOIN [Domain] ON [name] LIKE +'%' + #var +'%'
I believe this should go to the where condition
SELECT [name], [dom]
FROM [DomName]
INNER JOIN [Domain] ON [[[Some condition here based on two table relationship]]]
Where [name] LIKE +'%' + #var +'%'
Try This:
Select column1,column2 from Table1 where column1 like '''+'%'+ #var +'%'+'''

SQL syntax issue using "IN" keyword with dynamic data

I am using SQL Server 2000 and having a wierd issue with a SQL code block (below):
A user can enter "GM" as a possible parameter or "F". If the user enters "GM" as a parameter in the stored proc query string, I need the AutoDivision to include GMC, CAD, CHE,SAT
declare #AutoDivision as varchar(15)
set #AutoDivision = 'GM'
if #AutoDivision = 'GM'
Begin
Select #AutoDivision = '''Cad'', ''GMC'', ''Sat'', ''Che'''
End
SELECT
oh.OrderNumber, lg.[lgh_number]
FROM
[dbo].[OrderHeader] oh (NOLOCK)
INNER JOIN
[dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
INNER JOIN
[dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
INNER JOIN
[dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE
oh.ord_number = '113-889257'
AND x.AutoDivision IN (#AutoDivision)
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
AND lg.[lgh_outstatus] IN ('AVAIL', 'PLAN', 'DISP', 'STRTD', 'PEND','COMP')
However, when I run the code below, I don't get back any records.
When I uncomment the code line
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
it works (I get a record returned).
When I do a print 'AND x.AutoDivision IN (' + cast(#AutoDivision as varchar) + ')'
I get back AND x.AutoDivision IN ('Cad', 'GMC', 'Sat', 'Che')
What am I missing here?
You can't use a single variable to represent a comma separated list of IN parameters in SQL - Oracle, MySQL, SQL Server... doesn't matter.
To get this variable method to work, you need to use dynamic SQL so you are able to create the query as a string first (using concatenation to get the IN parameters from your variable), and the query statement is executed afterwards:
DECLARE #cmd VARCHAR(1000)
SET #cmd = 'SELECT oh.OrderNumber,
lg.[lgh_number]
FROM [dbo].[OrderHeader] oh (NOLOCK)
JOIN [dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
JOIN [dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
JOIN [dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE oh.ord_number = '113-889257'
AND x.AutoDivision IN ('+ #AutoDivision +')
AND lg.[lgh_outstatus] IN (''AVL'', ''PLN'', ''DSP'', ''STD'', ''PND'',''CMP'') '
EXEC(#cmd)
I recommend reading The Curse and Blessings of Dynamic SQL before implementing a dynamic SQL solution.
Table Valued Function
A table valued function would allow you do what you want without using dynamic SQL -- there's more info in this article.
To avoid this, you can create a temp table, fill it in, then use
IN (SELECT myField from #myTable)
Even though you concatenate what looks like a few different arguments your IN clause is actually testing it as a single string (you did declare it as a varchar) and it's no surprise that no records match that predicate.
Looks like you're trying to mix dynamic sql and a standard query. That won't work. Your query either has to be all dynamically created and then specially executed or your IN clause has to be inputed with individual arguments which can be done by subqery.
You could do something like:
... AND x.AutoDivision IN
(SELECT Division WHERE Corp = 'GM') ...
OR
... AND x.AutoDivision IN
(SELECT 'Cad' UNION SELECT 'GMC' UNION SELECT 'Sat' UNION SELECT 'Che') ...
Try this:
SELECT
oh.OrderNumber, lg.[lgh_number]
FROM
[dbo].[OrderHeader] oh (NOLOCK)
INNER JOIN
[dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
INNER JOIN
[dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
INNER JOIN
[dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE
oh.ord_number = '113-889257'
AND x.AutoDivision IN
(SELECT 'Cad' UNION SELECT 'GMC' UNION SELECT 'Sat' UNION SELECT 'Che')
AND lg.[lgh_outstatus] IN ('AVL', 'PLN', 'DSP', 'STD', 'PND','CMP')
That is an inline subquery that UNIONs arbitrary strings into a result set. (Take with a grain of salt. I am a long way from a Sql Server interface.)
AND x.AutoDivision IN (#AutoDivision)
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
Can you clarify these two lines of code, are they not doing the same thing?
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO
DECLARE #AutoDivision varchar(50) = NULL
SET #AutoDivision ='Cad, Sat, GMC, Che'
SELECT * FROM divisionXREF P INNER JOIN dbo.SPLIT(ISNULL(#AutoDivision,''),',') as T ON P.lgh_outstatus = CASE T.strval WHEN '' THEN P.PG_CODE ELSE T.strval END