Why does below Dynamic Query returns NULL? - sql-server

Why below Query Returns null instead of a dynamic query??
declare #Query Nvarchar(2000),
#IdentificationNo Nvarchar(255)=NULL
Set #Query='select VD.* from VWNROCDetail VD Where'
Set #Query=#Query+'((NROCApplicationId like ''%' + #IdentificationNo + '%'')OR (ISNULL('''+#IdentificationNo+''','''') = ''''))'
select #Query

Because #IdentificationNo is NULL. You need to use COALESCE(#IdentificationNo, '') or something like that.
'A' + NULL + 'B'
Returns Null
Whereas
'A' + '' + 'B'
returns 'AB'

The result ist null in String concatenation.Because your variable #IdentificationNo is null. If you append NULL to any String, the result is always NULL.
Not sure what you are trying to archive, but you should take a look at the sp_executesql procedure.
Example:
EXEC sp_executesql N'《your statement using #p1 as variable》', N'#p1 NVARCHAR(255)', #p1 = #IdentificationNo;
If you explain the Statement, i could offer some help.

I agree Alan. Now, it's really necessary to build a query with concantenation? In your case you can just do it :
declare #IdentificationNo Nvarchar(255)=NULL;
select VD.* from VWNROCDetail VD
Where VD.NROCApplicationId like '%' + #IdentificationNo + '%' or #IdentificationNo is null ;

Related

T-SQL Where clause with nvarchar composed by a string_agg in openquery

I'm creating a stored procedure where I have this openquery:
SELECT #MY_QUERY = 'SELECT * FROM OPENQUERY(HYPER_CONN, ''
SELECT COALESCE(SUM(QUANT_RIGA),0) FROM DDT_CLI_RIGHE WHERE DOC_RIGA_ID = ''''' + #THE_DDT + ''''' '')'
In the where clause I set this variable #THEDDT:
DECLARE #THE_DDT nvarchar(MAX) = (SELECT STRING_AGG(DOC_RIGA_ID,',') FROM ...
For example it will be like #THEDDT = test1,test2,test3
I want set this variable in my "where in" clause.
So in the openquery I'm trying to have something like this (but using the varaible):
WHERE DOC_RIGA_ID IN ('test1','test2','test3')
Is there a way to do this?
This is more of a stab in the dark, as we don't have all the information, however, as I mentioned, it seems all you need to do is change your DOC_RIGA_ID = {literal} clause to a DOC_RIGA_ID IN ({delimited List}) clause:
DECLARE #THE_DDT nvarchar(MAX) = (SELECT STRING_AGG(QUOTENAME(DOC_RIGA_ID,''''),',') --Assumes DOC_RIGA_ID can't have a value longer than 128 characters
FROM ...
SELECT #MY_QUERY = 'SELECT * FROM OPENQUERY(HYPER_CONN, ''
SELECT COALESCE(SUM(QUANT_RIGA),0) FROM DDT_CLI_RIGHE WHERE DOC_RIGA_ID IN (' + REPLACE(#THE_DDT,'''','''''') + ')'') OQ;';
This is, of course, untested as I have no way of testing this statement.

What is best way to search from optional parameter to SQL query in a stored procedure?

When it comes to search record with optional parameter in SQL stored procedure, out of these two queries. Both return the same results. Considering performance, which one will you use and why?
I have a stored procedure which has multiple search parameters and will be searching in multiple tables, with joins from a huge record set.
DECLARE #EventName VARCHAR(100)
--SET #EventName = ''
--SET #EventName = NULL
SET #EventName = 'Coffee in Coffee Bean'
-- Query - 1
SELECT *
FROM EventDetails
WHERE
1 = CASE
WHEN #EventName IS NULL OR #EventName = '' THEN 1
WHEN EventName LIKE '%'+ #EventName +'%' THEN 1 ELSE 0
END
-- Query - 2
SELECT *
FROM EventDetails
WHERE
EventName LIKE '%' + CASE
WHEN LEN(LTRIM(#EventName)) > 0
THEN #EventName
ELSE EventName
END + '%'
You can try this by writing a single query
SELECT *
FROM EventDetails
WHERE ((#EventName IS NULL OR #EventName) OR (EventName LIKE '%'+ #EventName +'%'))
My money is on this:
IF ISNULL(#EventName), '') = ''
SELECT * FROM EventDetails
ELSE
SELECT * FROM EventDetails WHERE EventName = '%' + #EventName + '%'
If you can't consider dynamic SQL, then try to use as less functions and data tampering as possible. The most common approach for this would be something like the following:
DECLARE #OptionalFilter1 INT
DECLARE #OptionalFilter2 VARCHAR(100)
-- ...
DECLARE #OptionalFilterN BIT
SELECT
YourColumns
FROM
YourTable AS T
WHERE
(#OptionalFilter1 IS NULL OR #OptionalFilter1 = T.Filter1Column) AND
(#OptionalFilter2 IS NULL OR #OptionalFilter2 = T.Filter2Column) AND
-- ...
(#OptionalFilterN IS NULL OR #OptionalFilterN = T.FilterNColumn)
For your example would be:
DECLARE #EventName VARCHAR(100) = 'Coffee in Coffee Bean'
SELECT
*
FROM
EventDetails AS E
WHERE
(#EventName IS NULL OR E.Event LIKE '%' + #EventName + '%')
If this is gonna end in a procedure, consider using OPTION (RECOMPILE) on the query with many filters and/or assigning the stored procedure parameters to new local scope variables to prevent parameter sniffing. You can read about parameter sniffing problem (with an example similar to yours) in this post.

Find strings in non alphabetic strings

I have to find all occurence of alphabetic strings in table. To do it, I use below algorithm (I iterate through another table in loop to get this #TableName value):
UPPER(rows_value) like '%' + #TableName + '%')
This condition is wrong because it's also shows me string contained in another string.
Let's assume that #TableName = test. I would like to find records in table, which contains this string (also surrended by non alphabetical characters). My algorithm returns me rows contained:
test
(test)
test0x
test02
_test_2222
pretest <---
uptest <----
...
I don't need last two, because these are different words. How to modify my condition to exclude non needed results?
Try next query:
DECLARE #TableName VARCHAR(128) = 'test' -- Replace with propper data type and max length
SELECT *
FROM (VALUES
('test'),
('(test)'),
('test0x'),
('test02'),
('_test_2222'),
('pretest '),
('uptest'),
('testAlpha'),
('13223 tes3432')
) t(Col1)
WHERE t.Col1 LIKE '%' + #TableName + '%'
AND NOT(t.Col1 LIKE '%[a-z]' + #TableName + '%' OR t.Col1 LIKE '%' + #TableName + '[a-z]%')

sql isnull with string as option

I have this portion of the query where I'm doing this.
FROM #Table2 WHERE Attribute = ISNULL('+#Attrb+', Attribute)) AS D
Obviously this isn't working for me as #Attr can bring in a string or can be empty. is there a better way to handle this?
What I need is, this a parameter that is passed to this stored procedure. There are two possible choices (or a third one is empty). I'm allowing the users to type it in. How would you tackle this?
Thanks.
FROM #Table2 ' + ISNULL('WHERE Attribute = ''' + NULLIF(#Attrb,'') + '''', '') + ') AS D
Example
CREATE TABLE #Table2 (Attribute VARCHAR(MAX))
INSERT INTO #Table2 VALUES
('Id'),('Class'),('Name')
DECLARE #Attrb VARCHAR(MAX),
#SQL VARCHAR(MAX)
--Attrb is NULL
SET #SQL = ' SELECT * FROM #Table2 ' + ISNULL('WHERE Attribute = ''' + NULLIF(#Attrb,'') + '''', '')
EXEC(#SQL)
/*Result
Attribute
---------
Id
Class
Name
*/
--Give Attrb a value
SET #Attrb = 'Class'
SET #SQL = ' SELECT * FROM #Table2 ' + ISNULL('WHERE Attribute = ''' + NULLIF(#Attrb,'') + '''', '')
EXEC(#SQL)
/*Result
Attribute
---------
Class
*/
You haven't indicated what version of SQL server you are using, but if you are using 2012 or later, you might want to check iif
Example for testing:
declare #Attrib varchar(20)
set #Attrib = NULL
select iif(#Attrib is null,'Null Result',#Attrib)
I am not sure what the string literals are doing in there. I am pretty sure you want something like this.
WHERE Attribute = ISNULL(#Attrb, Attribute)
Or if you are trying to deal with NULL or an empty string you can use NULLIF
WHERE Attribute = ISNULL(NULLIF(#Attrb, ''), Attribute)
--EDIT--
Modifying this to work with dynamic sql is pretty straight forward.
'WHERE Attribute = ISNULL(NULLIF(' + ISNULL(#Attrb, Attribute) + ', ''''), Attribute)'

How to pass SQL stored procedure NVARCHAR parameter with Hebrew?

I'm trying to pass an NVARCHAR parameter to my store procedure. The stored procedure is supposed to find all suppliers that match the specified criteria. The only problem I have is that I am trying to pass criteria that contains Hebrew.
ALTER PROCEDURE [dbo].[FindSupplier]
-- Add the parameters for the stored procedure here
#search_criteria nvarchar(100) = ''
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #hebrew as bit = 0
IF #search_criteria LIKE '%[אבגדהוזחטיחכךילמנפףערקשת]%'
BEGIN
SET #hebrew = 1
END
IF #hebrew = 0
BEGIN
SELECT comn020.t_suno 'Supplier Code'
, hebcom020.t_nama 'Supplier Name1'
, hebcom020.t_namb 'Supplier Name2'
FROM com020 WITH (NOLOCK)
INNER JOIN hebcom020 WITH (NOLOCK)
ON hebcom020.t_suno = com020.t_suno
WHERE (LTRIM(RTRIM(com020.t_suno)) LIKE N'%' + #search_criteria + '%')
OR (SOUNDEX(LTRIM(RTRIM(com020.t_suno))) LIKE N'%' + SOUNDEX(#search_criteria) + '%')
OR (LTRIM(RTRIM(hebcom020.t_nama)) LIKE N'%' + #search_criteria + '%')
OR (SOUNDEX(LTRIM(RTRIM(hebcom020.t_nama))) LIKE N'%' + SOUNDEX(#search_criteria) + '%')
OR (LTRIM(RTRIM(hebcom020.t_namb)) LIKE N'%' + #search_criteria + '%')
OR (SOUNDEX(LTRIM(RTRIM(hebcom020.t_namb))) LIKE N'%' + SOUNDEX(#search_criteria) + '%')
END
ELSE /* hebrew */
BEGIN
SELECT com020.t_suno 'Supplier Code'
, hebcom020.t_nama 'Supplier Name1'
, hebcom020.t_namb 'Supplier Name2'
FROM com020 WITH (NOLOCK)
INNER hebcom020 WITH (NOLOCK)
ON hebcom020.t_suno = com020.t_suno
WHERE hebcom020.t_nama Collate Hebrew_CI_AI LIKE N'%' + #search_criteria + '%' Collate Hebrew_CI_AI
OR (LTRIM(RTRIM(hebcom020.t_namb)) LIKE N'%' + #search_criteria + '%')
END
END
When I'm trying to pass something like exec FindSupplier 'ב' the SQL server recognizes char 'ב' as '?'
Your help will be highly appreciated
UPD: exec FindSupplier N'ב' worked
UPD2: In Visual Studio need to run sp with following string
="exec FindSupplier N'" & Parameters!search_criteria.Value & "'"
The problem is simply that the string literal used in the LIKE condition is not prefixed with an N to indicate that it is a Unicode string. The following example shows the difference:
DECLARE #search_criteria NVARCHAR(100) = N'ב';
IF #search_criteria LIKE '%[אבגדהוזחטיחכךילמנפףערקשת]%'
BEGIN
PRINT 'WithOUT "N"-prefix';
END;
IF #search_criteria LIKE N'%[אבגדהוזחטיחכךילמנפףערקשת]%'
BEGIN
PRINT 'WITH "N"-prefix';
END;
Returns:
WITH "N"-prefix
To more easily understand why there is this difference in behavior, consider the following:
-- when the DB has a default collation of Latin1_General_100_CI_AS_SC (code page 1252)
SELECT '%[אבגדהוזחטיחכךילמנפףערקשת]%'
-- %[????????????????????????]%
-- when the DB has a default collation of Hebrew_100_CI_AS_SC (code page 1255)
SELECT '%[אבגדהוזחטיחכךילמנפףערקשת]%'
-- %[אבגדהוזחטיחכךילמנפףערקשת]%
The string literals are parsed in the code page used by the default collation of the current database. If the code page can support these characters, then not prefixing with the upper-case "N" will work. But, if those characters do not exist in that code page, then they are converted into "?"s.

Resources