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]%')
Related
How can I search in a letter in variable like this 馃斀
Where Name Like '%#Variable%'
Hello #ahmad_lababidi welcome to stackoverflow,
If it is not an ASCII character and generally requires a column of type NVARCHAR and a literal with string N '' (Except when the encoding accepts symbols)
for example, the UNICODE code of your character is 55357, so you can search for this character in your query, as in the following example.
CREATE TABLE #FIND (NAME nvarchar(10));
INSERT INTO #FIND VALUES (N'馃斀');
SELECT UNICODE(N'馃斀') --> 55357
SELECT *
FROM #FIND
WHERE NAME LIKE '%' + NCHAR(55357) + '%'
You need to use an nvarchar instead, and make sure you prefix your literal string with an N to denote that the literal string is an nvarchar:
DECLARE #variable varchar(1) = N'馃斀';
SELECT *
FROM YourTable
WHERE YourColumn LIKE N'%' + #variable + N'%';
So basically to explain my situation I have a program where a user can select code numbers, that are alpha numeric. These codes are stored in my SQL database as datatype char.
When they select all the codes they want, the program then sends a few parameters(the codes being one of them). The codes are strung together and look something like this:
',01,1,A3' etc. etc. with commas separating the codes. I have the comma in front, but changing the comma to the back does not change anything.
the #reasonCode variable is the reason codes strung together.
In my where clause I have a statement that is this:
(#reasonCode = 'ALL') OR
((#reasonCode <> 'ALL' AND (charindex(',' + ro_reason_code, #reasonCode) > 0)))
Basically I want to restrict my results to just those that have those specific reason codes the user selected(among other parameters). I am trying to achieve that by stringing together the codes, and then searching through them using charindex, seperated by commas.
However I am running into an issue. Here are the results using a few different variations of reason codes:
',1' = 625 records (correct number)
',01' = 1015(correct number)
',01,1 = 1640(correct number)
',1,01' = 1015(for whatever reason it isn't picking up the 1 reason codes)
That is my issue right there.
When I put the 1 in front of the 01, it doesn't pick up the 1 reason codes. But if I do it flip-flopped it works fine...
Any ideas as to why this happens?
(I have tried also using the concat function and get the same results, and also tried forcing everything to be char datatype.)
In the end I would like the same result, regardless if it is ,01,1 or ,1,01.
I'm pretty sure this is because you said you're using the char type instead of varchar. Try replacing your charindex expression with this:
charindex(',' + rtrim(ro_reason_code), #reasonCode)
When I used a type of char(2) in the table and char(16) for the #reasonCode, I could reproduce your result, and I found that adding the rtrim fixed the problem. But unfortunately I can't explain exactly what's going here, why having ',1' at the end of the string should work without the trim whereas having it at the beginning does not. Hopefully someone can provide a more in-depth answer that gets into the "why," but I thought I'd still post this for the time being to get you running.
Reproduction:
-- Forgive the "hackish" way of populating this table. I'm assuming sysobjects has >=1015 records.
declare #Code table (ro_reason_code char(2));
insert #Code select top 625 '1' from sysobjects;
insert #Code select top 1015 '01' from sysobjects;
declare #reasonCode char(16);
set #reasonCode = ',1,01';
select count(1) from #Code where #reasonCode = 'ALL' or charindex(',' + ro_reason_code, #reasonCode) > 0; -- Result: 1015
select count(1) from #Code where #reasonCode = 'ALL' or charindex(',' + rtrim(ro_reason_code), #reasonCode) > 0; -- Result: 1640
set #reasonCode = ',01,1';
select count(1) from #Code where #reasonCode = 'ALL' or charindex(',' + ro_reason_code, #reasonCode) > 0; -- Result: 1640
select count(1) from #Code where #reasonCode = 'ALL' or charindex(',' + rtrim(ro_reason_code), #reasonCode) > 0; -- Result: 1640
Because you are using char, which is a fixed length field, your data is stored padded out to the length of the field. So '1' is stored as '1 '
DECLARE #Code CHAR(2)
SET #Code = '1'
SELECT '''' + #Code + ''''
-- Printes '1 '
For that reason, when you add ',' to the value, you now have ',1 ' (notice the trailing whitespace)
DECLARE #Code CHAR(2)
SET #Code = '1'
SELECT '''' + ',' + #Code + ''''
-- prints ',1 '
Now if you're comparing off another char field, there will also be padded whitespace if the character data is less than the length of the field. So what appers to be ',11,1' is actually something like ',11,1 ' which does match the pattern of ',1 '
BUT, when you reverse the order, ',1,11' becomes ',1,11 ' which does not match the pattern of ',1 '
Unrelated
I just want to point out there is a subtle issue with the implementation. By only appending the leading comma, you may get false positives depending on your data. For example, ,2 will match the pattern ,25.
,2 does match 1,11,25,A01
You've gotta append the comma on both sides of each side of the evaluation.
CHARINDEX( ',' + RTRIM(ro_reason_code) + ',',
',' + RTRIM(#reasonCode) + ',') > 0
So to illustrate the difference it becomes
,2, does not match ,1,11,25,A01,
I've created a full-text indexed column on a table.
I have a stored procedure to which I may pass the value of a variable "search this text". I want to search for "search", "this" and "text" within the full-text column. The number of words to search would be variable.
I could use something like
WHERE column LIKE '%search%' OR column LIST '%this%' OR column LIKE '%text%'
But that would require me to use dynamic SQL, which I'm trying to avoid.
How can I use my full-text search to find each of the words, presumably using CONTAINS, and without converting the whole stored procedure to dynamic SQL?
If you say you definitely have SQL Table Full Text Search Enabled, Then you can use query like below.
select * from table where contains(columnname,'"text1" or "text2" or "text3"' )
See link below for details
Full-Text Indexing Workbench
So I think I came up with a solution. I created the following scalar function:
CREATE FUNCTION [dbo].[fn_Util_CONTAINS_SearchString]
(
#searchString NVARCHAR(MAX),
#delimiter NVARCHAR(1) = ' ',
#ANDOR NVARCHAR(3) = 'AND'
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
IF #searchString IS NULL OR LTRIM(RTRIM(#searchString)) = '' RETURN NULL
-- trim leading/trailing spaces
SET #searchString = LTRIM(RTRIM(#searchString))
-- remove double spaces (prevents empty search terms)
WHILE CHARINDEX(' ', #searchString) > 0
BEGIN
SET #searchString = REPLACE(#searchString,' ',' ')
END
-- reformat
SET #searchString = REPLACE(#searchString,' ','" ' + #ANDOR + ' "') -- replace spaces with " AND " (quote) AND (quote)
SET #searchString = ' "' + #searchString + '" ' -- surround string with quotes
RETURN #searchString
END
I can get my results:
DECLARE #ftName NVARCHAR (1024) = dbo.fn_Util_CONTAINS_SearchString('value1 value2',default,default)
SELECT * FROM Table WHERE CONTAINS(name,#ftName)
I would appreciate any comments/suggestions.
For your consideration.
I understand your Senior wants to avoid dynamic SQL, but it is my firm belief that Dynamic SQL is NOT evil.
In the example below, you can see that with a few parameters (or even defaults), and a 3 lines of code, you can:
1) Dynamically search any source
2) Return desired or all elements
3) Rank the Hit rate
The SQL
Declare #SearchFor varchar(max) ='Daily,Production,default' -- any comma delim string
Declare #SearchFrom varchar(150) ='OD' -- table or even a join statment
Declare #SearchExpr varchar(150) ='[OD-Title]+[OD-Class]' -- Any field or even expression
Declare #ReturnCols varchar(150) ='[OD-Nr],[OD-Title]' -- Any field(s) even with alias
Set #SearchFor = 'Sign(CharIndex('''+Replace(Replace(Replace(#SearchFor,' , ',','),', ',''),',',''','+#SearchExpr+'))+Sign(CharIndex(''')+''','+#SearchExpr+'))'
Declare #SQL varchar(Max) = 'Select * from (Select Distinct'+#ReturnCols+',Hits='+#SearchFor+' From '+#SearchFrom + ') A Where Hits>0 Order by Hits Desc'
Exec(#SQL)
Returns
OD-Nr OD-Title Hits
3 Daily Production Summary 2
6 Default Settings 1
I should add that my search string is comma delimited, but you can change to space.
Another note CharIndex can be substanitally faster that LIKE. Take a peek at
http://cc.davelozinski.com/sql/like-vs-substring-vs-leftright-vs-charindex
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.
I have a search functionality in my application which searches a string value of a particular column. The search text is passed as a parameter to the procedure. Now I have to search in another column which is an integer from another table. The input param is one but now I have to search in both the columns and return the result according to that.
//Query:
#SearchText VARCHAR(8000) = ''
SELECT DISTINCT Id, TransactionId, wfdFieldValue
where (wfdFieldValue LIKE '%' + #SearchText + '%' OR #SearchText = '')
In the above query I have to include the TransactionId in the where condition. So that if the user searched using the TransactionId or the Fieldvalue the query will return the result.
Note: The TransactionId is an Integer DataType.
If I understand you correctly, you'll want a hit in either column to make the row show up in search results. In that case, you'll need a simple OR;
SELECT DISTINCT Id, TransactionId, wfdFieldValue
FROM bop
WHERE #SearchText='' OR
wfdFieldValue LIKE '%' + #SearchText + '%' OR
TransactionId LIKE '%' + #SearchText + '%'
(You can just use LIKE on the integer column right away without manually converting.)
Of note though, this kind of wildcard search with a leading % does not use indexes in an optimal way, performance of this query will most likely not be great as the table grows.
SELECT DISTINCT Id, TransactionId, wfdFieldValue
where wfdFieldValue LIKE '%' + #SearchText + '%'
OR #SearchText = ''
OR CAST(TransactionId AS VARCHAR(50)) LIKE '%' + #SearchText + '%'
A cast should solve it, but I would first think about possible design improvements.