Skip to content
Advertisement

Find rows containing delimited words within nvarchar parameter

I have a procedure that selects an offset of rows from a table:

SELECT * --table contains ID and Name columns
FROM Names
ORDER BY ID
OFFSET @Start ROWS
FETCH NEXT @Length ROWS ONLY

In addition to @Start and @Length parameters, the procedure also receives @SearchValue NVARCHAR(255) parameter. @SearchValue contains a string of values delimited by a space, for example '1 ik mi' or 'Li 3'.

What I need is to query every record containing all of those values. So, if the @SearchValue is '1 ik mi', it should return any records that contain all three values: ‘1’, ‘mi’, and ‘ik’. Another way to understand this is by going here, searching the table (try searching 00 eer 7), and observing the filtered results.

I have the freedom to change the delimiter or run some function (in C#, in my case) that could format an array of those words.

Below are our FAILED attempts (we didn’t try implementing it with OFFSET yet):

Select ID, Name
From Names
Where Cast(ID as nvarchar(255)) in (Select value from string_split(@SearchValue, ' ')) AND 
Name in (Select value from string_split(@SearchValue, ' '))
SELECT ID, Name
FROM Names
WHERE @SearchValueLIKE '% ' + CAST(ID AS nvarchar(20)) + ' %' AND
@SearchValueLIKE '% ' + Name + ' %';

We used Microsoft docs on string_split for the ideas above.

Tomorrow, I will try to implement this solution, but I’m wondering if there’s another way to do this in case that one doesn’t work. Thank you!

Advertisement

Answer

Your best bet will be to use a FULL TEXT index. This is what they’re built for.

Having said that you can work around it.. BUT! You’re going to be building a query to do it. You can either build the query in C# and fire it at the database, or build it in the database. However, you’re never going to be able to optimise the query very well because users being users could fire all sorts of garbage into your search that you’ll need to watch out for, which is obviously a topic for another discussion.

The solution below makes use of sp_executesql, so you’re going to have to watch out for SQL injection (before someone else picks apart this whole answer just to point out SQL injection):

DROP TABLE #Cities;

CREATE TABLE #Cities(id INTEGER IDENTITY PRIMARY KEY, [Name] VARCHAR(100));

INSERT INTO #Cities ([Name]) VALUES
('Cooktown'),
('South Suzanne'),
('Newcastle'),
('Leeds'),
('Podunk'),
('Udaipur'),
('Delhi'),
('Murmansk');

DECLARE @SearchValue VARCHAR(20) = 'ur an rm';
DECLARE @query NVARCHAR(1000);

SELECT @query = COALESCE(@query + '%'' AND [Name] LIKE ''%', '') + value
FROM (Select value from string_split(@SearchValue, ' ')) a;

SELECT @query = 'SELECT * FROM #Cities WHERE [Name] LIKE ''%' + @query + '%''';

EXEC sp_executesql @query;
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement