Adding Dyanmic In() Conditions in Sql Server - sql-server

Facing problem for generating SQL Server Query
In the Following query dynamic conditions are added to check whether value is null or not
Select *
From tblEmployees
where EmployeeName = Case
When #EmployeeName Is Not Null
Then #EmployeeName
Else EmployeeName
End
But I need to add IN () Conditions and the parameter with in the IN () could be null or blank also ,if the parameter /string which is passed to the IN condition is blank then i donot want to add that condition in the query.
So how can i Achieve this.A helping hand will be very useful for me.
Thanks and Regards,
D.Mahesh

Depending on value of your parameter (blank of not), you can create SQL string accordingly.
DECLARE #sqlCommand VARCHAR(1000)
IF(ISNULL(#YourParameter,'')='')
#sqlCommand = 'your query goes here'
ELSE
#sqlCommand = 'your query goes here'
and then, run it using dynamic query execution
EXEC (#sqlCommand)
If not dynamic query then,
SELECT ....
FROM ....
WHERE CASE WHEN ISNULL(#YourParameter,'')='' THEN '' ELSE EmployeeName END IN (ISNULL(#YourParameter,''))
See if this works...

I think the Dynamic query is the best solution, however you could put the "IS NULL" and "IS BLANK" condition in OR with your IN clause.
Something like that
Select *
From tblEmployees
where #EmployeeName is null or EmployeeName in (#EmployeeName)
When #EmployeeName is null, your IN clause will be ignored

If i get this right you have #EmployeeName = 'Name1,Name2,Name3' and you want to get the employees that is named Name1 or Name2 or Name3, also the variable #EmployeeName can be null or contain an empty string.
Instead of using IN you can split the string #EmployeeName on , and store it in a table variable or temporary table. Then you can use that table in a join against tblEmployees to get the rows you need.
There are a lot of posts in S.O. about how to split a string. Here is one recent variant.
Group by sql query on comma joined column
This will work for SQL Server 2005 or later.
declare #EmployeeName varchar(100) = 'Name2,Name3,Name5'
-- Null or empty will have a comma
set #EmployeeName = coalesce(#EmployeeName, '') + ','
-- cteNames splits the string to rows
;with cteNames
as
(
select
left(#EmployeeName, charindex(',', #EmployeeName)-1) as Name,
right(#EmployeeName, len(#EmployeeName)-charindex(',', #EmployeeName)) as EmployeeName
union all
select
left(EmployeeName, charindex(',', EmployeeName)-1) as Name,
right(EmployeeName, len(EmployeeName)-charindex(',', EmployeeName)) as EmployeeName
from cteNames
where charindex(',', EmployeeName) > 1
)
select E.*
from tblEmployees as E
inner join cteNames as N
on E.Name = N.Name or
#EmployeeName = ','
-- #EmployeeName = ',' will give you all names when #EmployeeName is null of empty

Related

Dynamic SQL - How to use a value from a result as a column name?

I am working on a dynamic SQL query for a MsSQL stored procedure.
There is a table search.ProfileFields that contains the actual column names in a table I need to query.
My goal is to have the SQL select the specific column in the table, dynamically from its parent query..
A little confusing, heres an example:
DECLARE #sql nvarchar(max)
SELECT #sql = '
SELECT
pfs.SectionID,
pfs.SectionName,
pfs.Link,
(
SELECT
pf.FieldID,
pf.FieldTitle,
pf.FieldSQL,
pf.Restricted,
pf.Optional,
(
SELECT
pf.FieldSQL
FROM
Resources.emp.EmployeeComplete as e
WHERE
e.QID = #QID
) as Value
FROM
search.ProfileFields as pf
WHERE
pf.SectionID = pfs.SectionID
ORDER BY
pf.[Order]
FOR XML PATH (''field''), ELEMENTS, TYPE, ROOT (''fields'')
)
FROM
search.ProfileFieldSections as pfs
WHERE
pfs.Status = 1
FOR XML PATH (''data''), ELEMENTS, TYPE, ROOT (''root'')'
PRINT #sql
EXECUTE sp_executesql #sql, N'#QID varchar(10)', #QID = #QID
In the inner most select. I am querying pf.FieldSQL. I am looking for the actual value that was received by the parent select.
search.ProfileFields has a column called FieldSQL with a few results such as Name, Age, Location.
That is what I am trying to get my inner most select to do.
SELECT Name FROM ... - Name in this case comes from the value of pf.FieldSQL.
How can I go about querying a dynamic column name in this situation?
Have a look at this answer for a couple of suggestions. If your table definition is complex or changes occasionally you probably should use pivot. Here's one that might work for you, so long as column names in the FieldSQL column are well defined, there are not too many of them, and they don't ever change or get added to:
DECLARE #sql nvarchar(max)
SELECT #sql = '
SELECT
pfs.SectionID,
pfs.SectionName,
pfs.Link,
(
SELECT
pf.FieldID,
pf.FieldTitle,
pf.FieldSQL,
pf.Restricted,
pf.Optional,
(
SELECT case pf.FieldSQL
when 'Name' then e.Name
when 'DOB' then convert(nvarchar(10), e.DOB, 126)
-- ... etc.
-- NOTE: may need to aggregated depending on uniqueness of QID:
-- when 'Name' then min(e.Name)
-- when 'DOB' then convert(nvarchar(10), min(e.DOB), 126)
end
FROM
Resources.emp.EmployeeComplete as e
WHERE
e.QID = #QID
) as Value
FROM
search.ProfileFields as pf
WHERE
pf.SectionID = pfs.SectionID
ORDER BY
pf.[Order]
FOR XML PATH (''field''), ELEMENTS, TYPE, ROOT (''fields'')
)
FROM
search.ProfileFieldSections as pfs
WHERE
pfs.Status = 1
FOR XML PATH (''data''), ELEMENTS, TYPE, ROOT (''root'')'
PRINT #sql
EXECUTE sp_executesql #sql, N'#QID varchar(10)', #QID = #QID
Take a look at "PIVOT" operators here PIVOT
Thisshould give you some ideas how to use them.

Most effective way to check sub-string exists in comma-separated string in SQL Server

I have a comma-separated list column available which has values like
Product1, Product2, Product3
I need to search whether the given product name exists in this column.
I used this SQL and it is working fine.
Select *
from ProductsList
where productname like '%Product1%'
This query is working very slowly. Is there a more efficient way I can search for a product name in the comma-separated list to improve the performance of the query?
Please note I have to search comma separated list before performing any other select statements.
user defined functions for comma separation of the string
Create FUNCTION [dbo].[BreakStringIntoRows] (#CommadelimitedString varchar(max))
RETURNS #Result TABLE (Column1 VARCHAR(max))
AS
BEGIN
DECLARE #IntLocation INT
WHILE (CHARINDEX(',', #CommadelimitedString, 0) > 0)
BEGIN
SET #IntLocation = CHARINDEX(',', #CommadelimitedString, 0)
INSERT INTO #Result (Column1)
--LTRIM and RTRIM to ensure blank spaces are removed
SELECT RTRIM(LTRIM(SUBSTRING(#CommadelimitedString, 0, #IntLocation)))
SET #CommadelimitedString = STUFF(#CommadelimitedString, 1, #IntLocation, '')
END
INSERT INTO #Result (Column1)
SELECT RTRIM(LTRIM(#CommadelimitedString))--LTRIM and RTRIM to ensure blank spaces are removed
RETURN
END
Declare #productname Nvarchar(max)
set #productname='Product1,Product2,Product3'
select * from product where [productname] in(select * from [dbo].[![enter image description here][1]][1][BreakStringIntoRows](#productname))
Felix is right and the 'right answer' is to normalize your table. Although, maybe you have 500k lines of code that expect this column to exist as it is. So your next best (non-destructive) answer is:
Create a table to hold normalize data:
CREATE TABLE ProductsList2 (ProductId INT, ProductName VARCHAR)
Create a TRIGGER that on UPDATE/INSERT/DELETE maintains ProductList2 by splitting the string 'Product1,Product2,Product3' into three records.
Index your new table.
Query against your new table:
SELECT *
FROM ProductsList
WHERE ProductId IN (SELECT x.ProductId
FROM ProductsList2 x
WHERE x.ProductName = 'Product1')

SQL Server : Verify a list of text from a table

Could you please help me with a query for the following requirements?
I have a list of Cities which I want to verify from a table. The query will have the Input List (below) in the where clause and gives me results like shown below in expected result.
Input list = ('City1','City2','City3','City4',.......'City100')
Expected result
1. City1 Exist
2. City2 Exist
3. City3 Not Exist
4. City4 Exist
5. City5 Not Exist
Thanks.
Try it like this: Just paste my code into an empty query window and execute. Adapt to your needs (most important is to replace the "#ExistingCities" with your actual table's name):
First I declare a "table" with some already existing cities (3 and 5 are missing). The input string misses City4.
DECLARE #ExistingCities TABLE(CityName VARCHAR(100));
INSERT INTO #ExistingCities VALUES('City1'),('City2'),('City4'),('City6');
DECLARE #Input VARCHAR(MAX)='City1,City2,City3,City5,City6';
WITH SplittedInput AS
(
SELECT CAST('<x>' + REPLACE(#input,',','</x><x>') + '</x>' AS XML) AS CitiesAsXml
)
SELECT oneCity.value('.','varchar(max)') AS InputName
,CASE WHEN exC.CityName IS NOT NULL THEN 'Exist' ELSE 'Not Exist' END AS ResultCode
FROM SplittedInput
CROSS APPLY CitiesAsXml.nodes('/x') AS InputCity(oneCity)
LEFT JOIN #ExistingCities AS exC ON exC.CityName=oneCity.value('.','varchar(max)')
Please check following SQL script,
For demo I created a sql CityList table with sample data
create table cityList (id int identity(1,1), city nvarchar(50),)
insert into cityList(city) values ('City1'),('City3')
declare #input nvarchar(max) = 'City1,City2,City3,City4,City100'
select
s.val,
case when c.city is not null then 'Exist' else 'Not Exist' end
from dbo.split(#input,',') s
left join cityList c on c.city = s.val
Please note that you need the SQL string Split function codes for dbo.split() function
I hope it helps

sql server stored proc dynamic select

I have a stored proc in the following format
create PROCEDURE [dbo].[test proc]
#identifier varchar(20),
#issuerName varchar(max),
#max_records int=1000
AS
BEGIN
declare #select nvarchar(30)
SELECT #identifier as '#identifier'
, (
SELECT
MoodysOrgID as '#MoodysOrgID'
,ReportDate as '#ReportDate'
,m.UpdateTime as '#UpdateTime'
,m.FileCreationDate as '#FileCreationDate'
from mfm_financial_ratios m
inner join mfm_financial_ratios_coa c on c.AcctNo = m.AcctNo
where ReportDate in (select distinct top (#max_records) reportdate from mfm_financial_ratios where MoodysOrgID = m.MoodysOrgID)
and m.MoodysOrgID=(select top 1 IssuerID_Moodys as id from loans where LIN=#identifier or LoanXID=#identifier
and ParentName_Moodys=#issuerName and IssuerID_Moodys is not null)
order by ReportDate desc
FOR XML PATH('FinRatios'), TYPE
)
FOR XML PATH('FinRatiosHistory')
END
but i would like to make by query execute as dynamic sql
and my stored proc looks like
create PROCEDURE [dbo].[test proc]
#identifier varchar(20),
#issuerName varchar(max),
#max_records int=1000
AS
BEGIN
declare #select nvarchar(30)
set #select = N'SELECT #identifier as '#identifier'
, (
SELECT
MoodysOrgID as '#MoodysOrgID'
,ReportDate as '#ReportDate'
,m.UpdateTime as '#UpdateTime'
,m.FileCreationDate as '#FileCreationDate'
from mfm_financial_ratios m
inner join mfm_financial_ratios_coa c on c.AcctNo = m.AcctNo
where ReportDate in (select distinct top (#max_records) reportdate from mfm_financial_ratios where MoodysOrgID = m.MoodysOrgID)
and m.MoodysOrgID=(select top 1 IssuerID_Moodys as id from loans where LIN=#identifier or LoanXID=#identifier
and ParentName_Moodys=#issuerName and IssuerID_Moodys is not null)
order by ReportDate desc
FOR XML PATH('FinRatios'), TYPE
)
FOR XML PATH('FinRatiosHistory')'
exec #select
END
The following stored proc gives issues because of the comma used in it .Can someone let me know what you be the correct way of doing it
The problem are not the commas. You mostly have two problems: one, you're not escaping the quotes correctly. And two, you're not concatenating your variables correctly. Here's an example of both:
For concatenating variables: In your first select line, you cannot do this:
SELECT #identifier as '#identifier'
because sql does not know what to do with #identifier that way. You should concatenate the variable this way:
SELECT #identifier as ' + #identifier + '.. everything else goes here
Also, when you will have to concatenate max_records, since it's an int variable you should cast it to varchar first, like this:
select distinct top (' + cast(#max_records as varchar(10) + ') ....
Whenever you're using a variable in the middle of the string (such as #max_records) you HAVE to concatenate it in order for SQL to know it's a variable and not just a string. You didn't do it with max_records, #issuerName, etc.
For escaping quotes: You need to escape your single quotes when you don't want your select string to unexpectedly end. For example here:
FOR XML PATH('FinRatiosHistory')'
You should escape them with double quotes (google escaping single quotes sql if you don't get it)
FOR XML PATH(''FinRatiosHistory'')'

How do I check if a SQL Server text column is empty?

I am using SQL Server 2005. I have a table with a text column and I have many rows in the table where the value of this column is not null, but it is empty. Trying to compare against '' yields this response:
The data types text and varchar are incompatible in the not equal to operator.
Is there a special function to determine whether the value of a text column is not null but empty?
where datalength(mytextfield)=0
ISNULL(
case textcolum1
WHEN '' THEN NULL
ELSE textcolum1
END
,textcolum2) textcolum1
Actually, you just have to use the LIKE operator.
SELECT * FROM mytable WHERE mytextfield LIKE ''
To get only empty values (and not null values):
SELECT * FROM myTable WHERE myColumn = ''
To get both null and empty values:
SELECT * FROM myTable WHERE myColumn IS NULL OR myColumn = ''
To get only null values:
SELECT * FROM myTable WHERE myColumn IS NULL
To get values other than null and empty:
SELECT * FROM myTable WHERE myColumn <> ''
And remember use LIKE phrases only when necessary because they will degrade performance compared to other types of searches.
SELECT * FROM TABLE
WHERE ISNULL(FIELD, '')=''
Use the IS NULL operator:
Select * from tb_Employee where ename is null
I know this post is ancient but, I found it useful.
It didn't resolve my issue of returning the record with a non empty text field so I thought I would add my solution.
This is the where clause that worked for me.
WHERE xyz LIKE CAST('% %' as text)
Use DATALENGTH method, for example:
SELECT length = DATALENGTH(myField)
FROM myTABLE
Instead of using isnull use a case, because of performance it is better the case.
case when campo is null then '' else campo end
In your issue you need to do this:
case when campo is null then '' else
case when len(campo) = 0 then '' else campo en
end
Code like this:
create table #tabla(
id int,
campo varchar(10)
)
insert into #tabla
values(1,null)
insert into #tabla
values(2,'')
insert into #tabla
values(3,null)
insert into #tabla
values(4,'dato4')
insert into #tabla
values(5,'dato5')
select id, case when campo is null then 'DATA NULL' else
case when len(campo) = 0 then 'DATA EMPTY' else campo end
end
from #tabla
drop table #tabla
I would test against SUBSTRING(textColumn, 0, 1)
Are null and an empty string equivalent? If they are, I would include logic in my application (or maybe a trigger if the app is "out-of-the-box"?) to force the field to be either null or '', but not the other. If you went with '', then you could set the column to NOT NULL as well. Just a data-cleanliness thing.
I wanted to have a predefined text("No Labs Available") to be displayed if the value was null or empty and my friend helped me with this:
StrengthInfo = CASE WHEN ((SELECT COUNT(UnitsOrdered) FROM [Data_Sub_orders].[dbo].[Snappy_Orders_Sub] WHERE IdPatient = #PatientId and IdDrugService = 226)> 0)
THEN cast((S.UnitsOrdered) as varchar(50))
ELSE 'No Labs Available'
END
You have to do both:
SELECT * FROM Table WHERE Text IS NULL or Text LIKE ''
I know there are plenty answers with alternatives to this problem, but I just would like to put together what I found as the best solution by #Eric Z Beard & #Tim Cooper with #Enrique Garcia & #Uli Köhler.
If needed to deal with the fact that space-only could be the same as empty in your use-case scenario, because the query below will return 1, not 0.
SELECT datalength(' ')
Therefore, I would go for something like:
SELECT datalength(RTRIM(LTRIM(ISNULL([TextColumn], ''))))
try this:
select * from mytable where convert(varchar, mycolumn) = ''
i hope help u!
DECLARE #temp as nvarchar(20)
SET #temp = NULL
--SET #temp = ''
--SET #temp = 'Test'
SELECT IIF(ISNULL(#temp,'')='','[Empty]',#temp)
It will do two things:
Null check and string null check
Replace empty value to default value eg NA.
SELECT coalesce(NULLIF(column_name,''),'NA') as 'desired_name') from table;

Resources