This should ideally be done with the help of SQL Server full text search if using that.
However, if you can’t get that working on your DB for some reason, here is a performance-intensive solution:
-- table to search in
CREATE TABLE dbo.myTable
(
myTableId int NOT NULL IDENTITY (1, 1),
code varchar(200) NOT NULL,
description varchar(200) NOT NULL -- this column contains the values we are going to search in
) ON [PRIMARY]
GO
-- function to split space separated search string into individual words
CREATE FUNCTION [dbo].[fnSplit] (@StringInput nvarchar(max),
@Delimiter nvarchar(1))
RETURNS @OutputTable TABLE (
id nvarchar(1000)
)
AS
BEGIN
DECLARE @String nvarchar(100);
WHILE LEN(@StringInput) > 0
BEGIN
SET @String = LEFT(@StringInput, ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput) - 1, -1),
LEN(@StringInput)));
SET @StringInput = SUBSTRING(@StringInput, ISNULL(NULLIF(CHARINDEX
(
@Delimiter, @StringInput
),
0
), LEN
(
@StringInput)
)
+ 1, LEN(@StringInput));
INSERT INTO @OutputTable (id)
VALUES (@String);
END;
RETURN;
END;
GO
-- this is the search script which can be optionally converted to a stored procedure /function
declare @search varchar(max) = 'infection upper acute genito'; -- enter your search string here
-- the searched string above should give rows containing the following
-- infection in upper side with acute genitointestinal tract
-- acute infection in upper teeth
-- acute genitointestinal pain
if (len(trim(@search)) = 0) -- if search string is empty, just return records ordered alphabetically
begin
select 1 as Priority ,myTableid, code, Description from myTable order by Description
return;
end
declare @splitTable Table(
wordRank int Identity(1,1), -- individual words are assinged priority order (in order of occurence/position)
word varchar(200)
)
declare @nonWordTable Table( -- table to trim out auxiliary verbs, prepositions etc. from the search
id varchar(200)
)
insert into @nonWordTable values
('of'),
('with'),
('at'),
('in'),
('for'),
('on'),
('by'),
('like'),
('up'),
('off'),
('near'),
('is'),
('are'),
(','),
(':'),
(';')
insert into @splitTable
select id from dbo.fnSplit(@search,' '); -- this function gives you a table with rows containing all the space separated words of the search like in this e.g., the output will be -
-- id
-------------
-- infection
-- upper
-- acute
-- genito
delete s from @splitTable s join @nonWordTable n on s.word = n.id; -- trimming out non-words here
declare @countOfSearchStrings int = (select count(word) from @splitTable); -- count of space separated words for search
declare @highestPriority int = POWER(@countOfSearchStrings,3);
with plainMatches as
(
select myTableid, @highestPriority as Priority from myTable where Description like @search -- exact matches have highest priority
union
select myTableid, @highestPriority-1 as Priority from myTable where Description like @search + '%' -- then with something at the end
union
select myTableid, @highestPriority-2 as Priority from myTable where Description like '%' + @search -- then with something at the beginning
union
select myTableid, @highestPriority-3 as Priority from myTable where Description like '%' + @search + '%' -- then if the word falls somewhere in between
),
splitWordMatches as( -- give each searched word a rank based on its position in the searched string
-- and calculate its char index in the field to search
select myTable.myTableid, (@countOfSearchStrings - s.wordRank) as Priority, s.word,
wordIndex = CHARINDEX(s.word, myTable.Description) from myTable join @splitTable s on myTable.Description like '%'+ s.word + '%'
-- and not exists(select myTableid from plainMatches p where p.myTableId = myTable.myTableId) -- need not look into myTables that have already been found in plainmatches as they are highest ranked
-- this one takes a long time though, so commenting it, will have no impact on the result
),
matchingRowsWithAllWords as (
select myTableid, count(myTableid) as myTableCount from splitWordMatches group by(myTableid) having count(myTableid) = @countOfSearchStrings
)
, -- trim off the CTE here if you don't care about the ordering of words to be considered for priority
wordIndexRatings as( -- reverse the char indexes retrived above so that words occuring earlier have higher weightage
-- and then normalize them to sequential values
select s.myTableid, Priority, word, ROW_NUMBER() over (partition by s.myTableid order by wordindex desc) as comparativeWordIndex
from splitWordMatches s join matchingRowsWithAllWords m on s.myTableId = m.myTableId
)
,
wordIndexSequenceRatings as ( -- need to do this to ensure that if the same set of words from search string is found in two rows,
-- their sequence in the field value is taken into account for higher priority
select w.myTableid, w.word, (w.Priority + w.comparativeWordIndex + coalesce(sequncedPriority ,0)) as Priority
from wordIndexRatings w left join
(
select w1.myTableid, w1.priority, w1.word, w1.comparativeWordIndex, count(w1.myTableid) as sequncedPriority
from wordIndexRatings w1 join wordIndexRatings w2 on w1.myTableId = w2.myTableId and w1.Priority > w2.Priority and w1.comparativeWordIndex>w2.comparativeWordIndex
group by w1.myTableid, w1.priority,w1.word, w1.comparativeWordIndex
)
sequencedPriority on w.myTableId = sequencedPriority.myTableId and w.Priority = sequencedPriority.Priority
),
prioritizedSplitWordMatches as ( -- this calculates the cumulative priority for a field value
select w1.myTableId, sum(w1.Priority) as OverallPriority from wordIndexSequenceRatings w1 join wordIndexSequenceRatings w2 on w1.myTableId = w2.myTableId
where w1.word <> w2.word group by w1.myTableid
),
completeSet as (
select myTableid, priority from plainMatches -- get plain matches which should be highest ranked
union
select myTableid, OverallPriority as priority from prioritizedSplitWordMatches -- get ranked split word matches (which are ordered based on word rank in search string and sequence)
),
maximizedCompleteSet as( -- set the priority of a field value = maximum priority for that field value
select myTableid, max(priority) as Priority from completeSet group by myTableId
)
select priority, myTable.myTableid , code, Description from maximizedCompleteSet m join myTable on m.myTableId = myTable.myTableId
order by Priority desc, Description -- order by priority desc to get highest rated items on top
--offset 0 rows fetch next 50 rows only -- optional paging
Being able to do complex queries can be really useful in SQL.
In this article, we’ll look at how you can use the Contains String
query.
SQL Patterns
SQL patterns are useful for pattern matching, instead of using literal comparisons. They have a more limited syntax than RegEx, but they’re more universal through the various SQL versions.
SQL patterns use the LIKE
and NOT LIKE
operators and the metacharacters (characters that stand for something other than themselves) %
and _
.
The operators are used like this: column_name LIKE pattern
.
Character | Meaning |
---|---|
% |
Any sequence of characters |
_ |
Exactly one character |
You can use these characters in a wide variety of use-cases. Here are some examples:
example pattern | usage |
---|---|
re% |
Strings that begin with a specific substring |
%re |
Strings that end with a specific substring |
%re% |
Strings that have a specific substring anywhere in the string |
%re_ |
Strings that have a specific substring at a specific position from the end¹ |
__re% |
Strings that have a specific substring at a specific position from the beginning² |
¹ (in the example, second to last and third to last characters are determined)
² (in the example, third and fourth characters are determined)
SELECT name FROM planets
WHERE name LIKE "%us";
Where planets
is a table with the data of the solar system’s planets.
With this query you would get the below names of the planets that end with «us».
name |
---|
Venus |
Uranus |
The NOT LIKE
operator finds all strings that do not match the pattern.
Let’s use it in an example too.
SELECT name FROM planets
WHERE name NOT LIKE "%u%";
With this query you get all planets whose names don’t contain the letter u
, like below.
name |
---|
Earth |
Mars |
Alternative to the LIKE
operator in SQL
Depending on the SQL flavour you are using, you might also be able to use the SIMILAR TO
operator. You can use it in addition to or in place of LIKE
.
The SQL SIMILAR TO
operator
The SIMILAR TO
operator works in a pretty similar way to the LIKE
operator, including which metacharacters are available. You can use the %
operator for any number of characters, and the _
operator for exactly one character.
Let’s take the example used with LIKE
and let’s use it here too.
SELECT name FROM planets
WHERE name SIMILAR TO "%us";
You can use this operator with NOT
in front to have the opposite effect. This is how you would write the example we used before using SIMILAR TO
instead:
SELECT name FROM planets
WHERE name NOT SIMILAR TO "%u%";
RegEx in SQL
What about if you need more complex pattern matching? Well, for that you need to use Regular Expressions.
What is RegEx?
RegEx on its own is a powerful tool that allows for flexible pattern recognition. You can use RegEx in many languages like PHP, Python, and also SQL.
RegEx lets you match patterns by character class (like all letters, or just vowels, or all digits), between alternatives, and other really flexible options. You will see them below.
What you can do with RegEx
You can do a lot of different things with RegEx patterns. To see a good variety, let’s use some of the examples presented in the RegEx freeCodeCamp Curriculum.
Keep in mind that the freeCodeCamp curriculum presents RegEx for JavaScript, so there is not a perfect match, and we need to convert the syntax. Still, it gives you a good overview of basic RegEx features, so let’s follow this curriculum so you can get a good idea of what RegEx can do.
Match Literal Strings
The easiest way to use RegEx it’s to use it to match an exact sequence of characters.
For example the regex "Kevin"
will match all strings that contains those letters in that exact sequence, as «Kevin«, «Kevin is great», «this is my friend Kevin» and so on.
Match a Literal String with Different Possibilities
A regular expression can be used to match different possibilities using the character |
. For example "yes|no|maybe"
would match any string that contains one of the three sequence of characters, such as «maybe I will do it», «maybelline», «monologue», «yes, I will do it», «no, I don’t like it», and so on.
Match Anything with the Wildcard Period
The wildcard period .
matches any character, for example "hu."
would match anything that contains an h
followed by an u
followed by any character, such as «hug«, «hum«, «hub«, «huh«, but also «husband», «churros», «thumb», «shuttle» and so on.
Match Single Character with Multiple Possibilities
You can use a character class (or character set) to match a group of characters, for example "b[aiu]g"
would match any string that contains a b
, then one letter between a
, i
and u
, and then a g
, such as «bug«, «big«, «bag«, but also «cabbage», «ambigous», «ladybug«, and so on.
Match Letters of the Alphabet
You have seen above how you can match a group of characters with character classes, but if you want to match a long list of letters that is a lot of typing.
To avoid all that typing, you can define a range. For example you can match all letters between a
and e
with "[a-e]"
.
A regex like "[a-e]at"
would match all strings that have in order one letter between a
and e
, then an a
and then a t
, such as «cat«, «bat» and «eat«, but also «birdbath», «bucatini», «date», and so on.
Match Numbers and Letters of the Alphabet
You can also use the hyphen to match numbers. For example "[0-5]"
would match any number between 0
and 5
, including 0
and 5
.
You can also combine different ranges together in a single character set. For example "[a-z0-9]"
would match all letters from a
to z
and all numbers from 0
to 5
.
Match Single Characters Not Specified
You can also use a character set to exclude some characters from a match, these sets are called negated character sets.
You can create a negated character set by placing a caret character (^
) after the opening bracket of the character class.
For example "[^aeiou]"
matches all characters that are not vowels. It would match strings like «rythm» where no character is a vowel, or also «87 + 14».
Match Characters that Occur One or More Times
If you need to match a specific character or group of characters that can appear one or more times, you can use the character +
after this character.
For example, "as+i"
would match strings that contain one a
followed by one or more s
followed by one i
, such as «occasional», «assiduous» and so on.
Match Characters that Occur Zero or More Times
If you can use +
to match a character one or more times, there is also *
to match a character zero or more times.
A regular expression such as "as*i"
would match, other than «occasional» and «assiduous» also strings such as «aide».
Match Beginning String Patterns
Until now you have seen ways to match anywhere in the string, without the option to say where the match must be.
We use the character ^
to match the beginning of a string, for example a regex such as "^Ricky"
would match «Ricky is my friend», but not «This is Ricky».
Match Ending String Patterns
Just as there’s a way to match the beginning of a string, there is also a way to match the end of a string.
You can use the character $
to match the end of a string, so for example "story$"
would match any string that ends with «story», such as «This is a never ending story«, but not a string such a «Sometimes a story will have to end».
Match the Whole String
You can combine the two characters ^
and $
to match a whole string.
So, taking one of the previous examples, writing "b[aiu]g"
can match both «big» and «bigger», but if instead you want to match only «big», «bag» and «bug», adding the two beginning and ending string characters ensures that there can’t be other characters in the string: "^b[aiu]g$"
. This pattern would match only «big», «bag» and «bug», and it doesn’t match «bigger» or «ambiguous».
Match All Letters and Numbers
You have seen before how to match characters with a character class.
There are a few predefined classes, called POSIX classes, that you can use instead. So if you want to match all letters and numbers like with "[0-9a-zA-Z]"
you can instead write "[[:alphanum:]]"
.
Match Everything But Letters and Numbers
If instead you want to match anything that is not a letter of a number, you can use the alphanum
POSIX class together with a negated character set: "[^[:alphanum:]]
.
Match All Numbers
You can also use a POSIX class to match all numbers instead of using "[0-9]"
, like so: "[[:digit:]]"
.
Match All Non-Numbers
You can use the digit
POSIX class with a negated character set to match anything that is not a number, like so: "[^[:digit:]]"
.
Match Whitespace
You can match whitespace with the POSIX class "[[:blank:]]"
or "[[:space:]]"
. The difference between these two classes is that the class blank
matches only spaces and tabs, while space
matches all blank characters, including carriage returns, new lines, form feeds, and vertical tabs.
Match Non-Whitespace Characters
You can match anything that is not a space or tab with "[^[:blank:]]"
.
And you can match anything that is not a whitespace, carriage return, tab, form feed, space, or vertical tab with "[^[:space:]]"
.
Specify Upper and Lower Number of Matches
You have seen before how to match one or more or zero or more characters. But sometimes you want to match a certain range of patterns.
For this you can use quantity specifiers.
Quantity specifiers are written with curly brackets ({
and }
). You put two numbers separated by a comma in the curly bracket. The first is the lower number of patterns, the second is the upper number of patterns.
For example, if your pattern is "Oh{2,4} yes"
, then it would match strings like «Ohh yes» or «Ohhhh yes», but not «Oh yes» or «Ohhhhh yes».
Specify Exact Number of Matches
You can also use the quantity specifier other than for a range to specify an exact number of matches. You can do this by writing a single number inside the curly brackets.
So, if your pattern is "Oh{3} yes"
, then it would match only «Ohhh yes».
Check For Mixed Grouping of Characters
If you want to check for groups of characters using regular expressions you can do so using parenthesis.
For example, you may want to match both «Penguin» and «Pumpkin», you can do so with a regular expression like this: "P(engu|umpk)in"
.
Summary of RegEx patterns
You have seen a lot of regex options here. So now let’s put all of these, along with a few others, into easily consultable tables.
RegEx patterns
pattern | description |
---|---|
^ |
beginning of string |
$ |
end of string |
. |
any character |
( ) |
grouping characters |
[abc] |
any character inside the square brackets |
[^abc] |
any character not inside the square brackets |
a|b|c |
a OR b OR c |
* |
zero or more of the preceding element |
+ |
one or more of the preceding element |
{n} |
n times the preceding element |
{n,m} |
between n and m times the preceding element |
Posix classes
In the table below you can see the posix classes we saw above, as well as some others that you can use to create patterns.
Posix class | similar to | description |
---|---|---|
[:alnum:] |
[a-zA-Z0-9] |
Aphanumeric character |
[:alpha:] |
[a-zA-Z] |
Alphabetic characters |
[:blank:] |
Spaces or tab characters | |
[:cntrl:] |
[^[:print:]] |
Control characters |
[:digit:] |
[0-9] |
Numeric characters |
[:graph:] |
[^ [:ctrl:]] |
All characters that have graphic rapresentation |
[:lower:] |
[a-z] |
Lowercase alphabetic characters |
[:print:] |
[[:graph:][:space:]] |
Graphic or spaces characters |
[:punct:] |
All graphic characters except letters and digits | |
[:space:] |
Space, new line, tab, carriage return | |
[:upper:] |
[A-Z] |
Uppercase alphabetic characters |
[:xdigit:] |
[0-9a-fA-F] |
Hexadecimal digits |
Remember that when using a POSIX class, you always need to put it inside the square brackets of a character class (so you’ll have two pair of square brackets). For example, "a[[:digit:]]b"
matches a0b
, a1b
and so on.
How to use RegEx patterns
Here you will see two kind of operators, REGEXP
operators and POSIX operators. Just be aware that which operators you can use depends on the flavour of SQL you are using.
RegEx operators
RegEx operators are usually case insensitive, meaning that they don’t distinguish between uppercase and lowercase letters. So for them, a
is equivalent to A
. But you can change this default behaviour, so don’t take it for granted.
Operator | Description |
---|---|
REGEXP |
Gives true if it matches the given pattern |
NOT REGEXP |
Gives true if the string doesn’t contain the given pattern |
Posix operators
The other kind of operators you could have available are POSIX operators. Instead of being keywords, these are represented with punctuation, and can be case sensitive or insensitive.
operator | description |
---|---|
~ |
case sensitive, true if the pattern is contained in the string |
!~ |
case sensitive, true if the pattern is not contained in the string |
~* |
case insensitive, true if the pattern is contained in the string |
!~* |
case insensitive, true if the pattern is not contained in the string |
RegEx and Posix Examples
Let’s see how to use these operators and RegEx patterns in a query.
Example query 1
For this first example, you want to match a string in which the first character is an «s» or «p» and the second character is a vowel.
To do this, you can use the character class [sp]
to match the first letter, and you can use the character class [aeiou]
for the second letter in the string.
You also need to use the character to match the start of the string, ^
, so all together you’ll write "^[sp][aeiou]"
.
You write the query below to get back the list of users whose names match the pattern.
SELECT name FROM users
WHERE name REGEXP '^[sp][aeiou]';
And if the default case insensitive behaviour was changed, you would need to write a pattern that allows both uppercase and lowercase letters, like "^[spSP][aeiouAEIOU]"
and use it in the query as below:
SELECT name FROM users
WHERE name REGEXP '^[spSP][aeiouAEIOU]';
Or with the POSIX operator, in this case you could use the case insensitive operator, ~*
and you would not need to write both upper case and lower case letters inside a character class. You could write the query as below.
SELECT name FROM users
WHERE name ~* '^[sp][aeiou]';
As the operator is by definition case insensitive, you don’t need to worry about specifying both uppercase and lowercase letters in the character class.
These queries would give back a table with results similar to below:
name |
---|
Sergio |
PAUL |
samantha |
Seraphina |
Example query 2
As a second example, let’s say you want to find a hexadecimal color. You can use the POSIX class [:xdigit:]
for this – it does the same as the character class [0-9a-fA-F]
.
Writing #[[:xdigit:]]{3}
or #[[:xdigit:]]{6}
would match a hexadecimal color in its shorthand or longhand form: the first one would match colors like #398
and the second one colors like #00F5C4
.
You could combine them using character grouping and |
to have one single RegEx pattern that matches both, and use it in the query as below:
SELECR color FROM styles
WHERE color REGEXP '#([[:xdigit:]]{3}|[[:xdigit:]]{6})';
SELECR color FROM styles
WHERE color ~ '#([[:xdigit:]]{3}|[[:xdigit:]]{6})';
This would give back something like below:
color |
---|
#341 |
#00fa67 |
#FF00AB |
The POSIX class [:xdigit:]
already includes both uppercase and lowercase letters, so you would not need to worry about if the operator is case sensitive or not.
Note on resource use
Depending on the size of your tables, a Contains String query can be really resource-intensive. Be careful when you’re using them in production databases, as you don’t want to have your app stop working.
Conclusion
The Contains String queries are really useful. You have learned how to use them in this article, and you’ve seen a few examples.
Hopefully you have added a new tool to your arsenal, and you enjoy using it! Just be careful not to crash your app.
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started
If you’re working with a database, whether large or small, there might be occasions when you need to search for some entries containing strings.
In this article, I’ll show you how to locate strings and substrings in MySQL and SQL Server.
I‘ll be using a table I call products_data
in a products_schema
database. Running SELECT * FROM products_data
shows me all the entries in the table:
Since I’ll be showing you how to search for a string in SQL Server too, I have the products_data
table in a products
database:
What We’ll Cover
- How to Query for Strings in SQL with the
WHERE
Clause andLIKE
Operator - How to Query for Strings in SQL Server with the
CHARINDEX
Function - How to Query for Strings in SQL Server with the
PATINDEX
Function - How to Query for Strings in MySQL with the
SUBSTRING_INDEX()
Function - Conclusion
How to Query for Strings in SQL with the WHERE
Clause and LIKE
Operator
The WHERE
clause lets you get only the records that meet a particular condition. The LIKE
operator, on the other hand, lets you find a particular pattern in a column. You can combine these two to search for a string or a substring of a string.
I was able to get all the products that have the word “computer” in them by combining the WHERE
clause and LIKE
operator by running the query below:
SELECT * FROM products_data
WHERE product_name LIKE '%computer%'
The percentage sign before and after the word “computer” means, find the word “computer” whether it’s in the end, middle, or start.
So, if you put the percentage sign at the start of a substring you’re searching by, it means, find that substring at the end of a string. For Example, I got every product that ends with “er” by running this query:
SELECT * FROM products_data
WHERE product_name LIKE '%er'
And if it’s at the end of a string, it means, find that substring at the start of a string. For example, I was able to get the product that starts with “lap” with this query:
SELECT * FROM products_data
WHERE product_name LIKE 'lap%'
This method also works fine in SQL Server:
How to Query for Strings in SQL Server with the CHARINDEX
Function
CHARINDEX() is an SQL server function for finding the index of a substring in a string.
The CHARINDEX()
function takes 3 arguments – the substring, the string, and the starting position. The syntax looks like this:
CHARINDEX(substring, string, start_position)
If it finds a match, it returns the index where it finds the match, but if it doesn’t find a match, it returns 0. Unlike many other languages, counting in SQL is 1-based.
Here’s an example:
SELECT CHARINDEX('free', 'free is the watchword of freeCodeCamp') position;
You can see the word free was found in position 1. That’s because ‘f’ itself is at position 1:
If I specify 25 as the position, SQL Server would find a match starting from the “freeCodeCamp” text:
SELECT CHARINDEX('free', 'free is the watchword of freeCodeCamp', 25);
I was able to use the CHARINDEX
function to search for all products that have the word “computer” in them by running this query:
SELECT * FROM products_data WHERE CHARINDEX('computer', product_name, 0) > 0
That query is saying, start from index 0, as long as they’re more than 0, get me every product that has the word “computer” in them in the product_name
column. This is the result:
How to Query for Strings in SQL Server with the PATINDEX
Function
PATINDEX
stands for “pattern index”. So, with this function, you can search for a substring with regular expressions.
PATINDEX
takes two arguments – the pattern and the string. The syntax looks like this:
PATINDEX(pattern, string)
If PATINDEX
finds a match, it returns the position of that match. If it doesn’t find a match, it returns 0. Here’s an example:
SELECT PATINDEX('%ava%', 'JavaScript is a Jack of all trades');
To apply PATINDEX
to the example table, I ran this query:
SELECT product_name, PATINDEX('%ann%', product_name) position
FROM products_data
But it only listed every product and returned the index where it found the match:
You can see it found the word “ann” at index 3 of the product Scanner. On many occasions, you might not want this behavior because you would want it to show only the item matched.
I made it return only what gets matched by using the WHERE
clause and LIKE
operator:
SELECT product_name, PATINDEX('%ann%', product_name) position
FROM products_data
WHERE product_name LIKE '%ann%'
Now it’s behaving as you would want.
How to Query for Strings in MySQL with the SUBSTRING_INDEX()
Function
Apart from the solutions I’ve already shown you, MySQL has an inbuilt SUBSTRING_INDEX()
function with which you can find a part of a string.
The SUBSTRING_INDEX()
function takes 3 compulsory arguments – the string, the substring to search for, and a delimiter. The delimiter has to be a number.
When you specify the compulsory arguments, the SUBSTRING_INDEX()
function will get you every part of the string that occurs before the delimiter you specify. Here’s an example:
SELECT SUBSTRING_INDEX("Learn on freeCodeCamp with me", "with", 1);
In the query above, «Learn on freeCodeCamp with me» is the string, «with» is the substring and 1 is the delimiter. In this case, the query will get you “Learn on freeCodeCamp”:
The delimiter can also be a negative number. If it’s a negative number, it gets you each part of the string that occurs after the delimiter you specify. Here’s an example:
SELECT SUBSTRING_INDEX("Learn on freeCodeCamp with me", "with", -1);
Conclusion
This article showed you how to locate a substring in a string in SQL using both MySQL and SQL Server.
CHARINDEX()
and PATINDEX()
are the functions with which you can search for a substring in a string inside SQL Server. PATINDEX()
is more powerful because it lets you use regular expressions.
Since CHARINDEX()
and PATINDEX()
don’t exist in MySQL, the first example showed you how you can find a substring in a string with the WHERE
clause and LIKE
operator.
Thank you for reading!
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started
The SQL contains is the SQL predicate Boolean function used with WHERE clause in the SQL Select statement to perform full-text search operations like search for a word, the prefix of a word, a word near another word, synonym of a word, etc… On full-text indexed columns containing character-based data types like string, char, and so on
Although SQL contains is not a standard SQL function, many of the database SQL Contains function argument depending on which database system we are using with,
For Microsoft SQL Server, SQL Contains function used to searches a text search in text column value-based criteria that are specified in a search argument and returns a number with either a true or false result, it will be 1 (true) if it finds a match and 0 (false) if it doesn’t. The first argument is the name of the table column you want to be searched; the second argument is the substring you want to find in the first argument column value
SQL Contains | SQL LIKE |
---|---|
SQL Contains is a predicate that can be used to search for a word, the prefix of a word, a word near another word, synonym of a word, etc. | SQL LIKE is an operator which is used to find whether a text string matches with a specified pattern or substring |
SQL Contains performs full-text search only on full-text indexed columns. | SQL LIKE search by matching regular expression Patten in the text column |
SQL Contains supports only wildcard character asterisk (*) | SQL LIKE supports all regular characters or wildcard characters like %, _, [] and [^] in a pattern |
SQL Contain operator searched in the expression or condition in nvarchar datatype | SQL LIKE perform the matching operation with a string that can have a maximum of eight thousand bytes |
Consider an eCommerce shopping system with three tables’ product, customer, and order for performing practical examples of SQL contains
Customer Table
productid | productname | category | tags | price | attribute |
---|---|---|---|---|---|
10001 | bluetooth | electronic | electronic,wired | 600 | blur color,wired,intel |
10002 | television | electronic | electronic,colored | 30000 | LED screen,unbrealable,balck |
10003 | iphone | electronic | electronic,apple | 25000 | 5.4-inch(13.7 cm diagonal) |
10004 | smart watch | electronic,watch | electronic, apple | 5000 | Apple Watch Series 7 |
orderid | orderdate | productid | custid | quntity | shippingaddress | shippingdate | amount |
---|---|---|---|---|---|---|---|
111 | 02-02-1990 | 10001 | 101 | 2 | althan,canal road,surat | 12-02-1990 | 1500 |
112 | 03-03-1991 | 10002 | 102 | 1 | ambe nagar,delhi | 20-03-1991 | 28000 |
113 | 05-05-2000 | 10001 | 102 | 3 | bhatar,surat | 15-05-2000 | 2000 |
114 | 04-04-2000 | 10002 | 103 | 1 | bandra,mumbai | 10-04-2000 | 28000 |
115 | 05-04-2000 | 10003 | 104 | 2 | bhatar,mumbai | 10-04-2000 | 20000 |
Search for a single word in a single column
Example 1: Write SQL query to display those customer data whose address contains ‘surat’
select custid as 'Customer ID' , custname as 'Customer Name',custaddress as 'Address' , custcity as 'City',custpincode as 'Pincode',custemail as 'Email',custcontactno as 'Customer Contact No' from tblcustomer
where contains(custaddress,'surat');
- In the above query, SQL Contains is used to search for the word ‘surat’ in the full-text index column custaddress
- The first argument in contains function is the columnname custadress and the second argument is the word to be search
ALSO READ: SQL NOT IN Operator Explained [8 Practical Examples]
OUTPUT:
Search for a single word in multiple columns
Example 2: Write a SQL query to display all customer data that has the ‘surat’ word in the address or city column
select custid as 'Customer ID' , custname as 'Customer Name',custaddress as 'Address' , custcity as 'City',custpincode as 'Pincode',custemail as 'Email',custcontactno as 'Customer Contact No' from tblcustomer
where contains((custaddress,custcity),'surat');
- In the above query, SQL Contains is used to search for a word ‘surat’ in two columns custaddress and custcity
- The first argument in contains operator is two column names in the small bracket and the second argument is a word to be searched, SQL will search for a word in both columns and if found in either of the column value, it will be in the resulting recordset
OUTPUT:
Search for a word in all full-text indexed columns
Example 3: Write a SQL query to display products details which has a word ‘electronic’ in any of the column value
select productid as'ID',productname as 'Product Name',category as 'Product Category', tags as 'Product Tags',price as 'Price',attribute as 'Product Attribute' from tblproduct
where contains(*,'electronic');
- In the above query, SQL contains is used to search for a word ‘electronic’ in all column values
- The first argument of SQL Contain operator is the asterisk (*), it specified all searches in all full-text index columns, and the second argument is the ‘electronic’ word to be search
ALSO READ: SQL BETWEEN Explained with Practical Examples
OUTPUT:
Search for two conditions with logical OR
Example 4: Write SQL query to display customer details who has ‘bharat’ or ‘surat’ word in the address value
select custid as 'Customer ID' , custname as 'Customer Name',custaddress as 'Address' , custcity as 'City',custpincode as 'Pincode',custemail as 'Email',custcontactno as 'Customer Contact No' from tblcustomer
where contains(custaddress,'"surat" or "bhatar"');
- In the above query, SQL contains is used to search for two words ‘surat’ and ‘bhatar’ in the custaddress column
- The First argument in the contains operator is the name of full-text indexed column name custaddress and the second argument is two words to be searched separated by logical operator OR, both words are enclosed in the double quotation mark
OUTPUT:
Search for two conditions with logical AND
Example 5: Write SQL query to display products information which are having ‘black’ and ‘LED’ as attribute value
select productid as'ID',productname as 'Product Name',category as 'Product Category', tags as 'Product Tags',price as 'Price',attribute as 'Product Attribute' from tblproduct
where contains(attribute,'"black" AND "LED"');
- In the above query, SQL Contains is used to search for two words with logical AND operator
- The first argument is full-text index column name attribute and the second argument is the two words ‘black’ and ‘LED’ enclosed in double quotation separated with AND, that means if any records have both words in the attribute column value then it will in the result set
ALSO READ: SQL Server COALESCE Function with Practical Examples
OUTPUT:
Search for two conditions with logical AND NOT
Example 6: Write SQL query to display customer information whose address contains ‘surat’ word but not contains ‘pal’ word
select custid as 'Customer ID' , custname as 'Customer Name',custaddress as 'Address' , custcity as 'City',custpincode as 'Pincode',custemail as 'Email',custcontactno as 'Customer Contact No' from tblcustomer
where contains(custaddress,'"surat" and not "pal"');
OUTPUT:
SQL Contains with NEAR | ~
The NEAR|~ is the operator used with SQL Contains to predicate for the search text with a WHERE clause or the CONTAINSTABLE function, it is also used for exact or fuzzy searches of a search term in the text, a search term can be either a single word or a phrase delimited by double quotation marks
We must specify two search terms with NEAR, the word or phrase on each side of the NEAR or ~ operator must occur in a document for a match to be returned, A given search term can be either a single word or a phrase that is delimited by double quotation marks
Example 6: Write SQL query to search for a word electronic in all columns near around the word wired
select productid as'ID',productname as 'Product Name',category as 'Product Category', tags as 'Product Tags',price as 'Price',attribute as 'Product Attribute' from tblproduct
where contains(*,'NEAR((electronic, wired))');
- In the above query, SQL contains is used to find word electronic in any of the column values near to the word wired either before word wired or after the word wired
- The first argument in the SQL contains function is the * which indicated search in the all column values, the second argument is the NEAR operator with two arguments words to be search column and the second is the word which around the given word is to be searched
ALSO READ: SQL FULL OUTER JOIN Explained [Practical Examples]
OUTPUT:
Summary
In this article, we have covered the SQL Contains which is used to do the searching operation for a word or phrase or nearby word on a full-text index, we have started with an overview of SQL Contains, the difference between SQL LIKE and SQL Contains, define the syntax of SQL Contains with an explanation of syntax argument, also covered practical examples of SQL Contains with the search of a word in a single column and multiple columns, a search of more than one word in single, multiple and all columns values, also covered example of more than one search condition combined with logical operators, and in the ending section we have covered the SQL NEAR operator used with SQL Contains
References
CONTAINS (Transact-SQL)
LIKE SQL — это оператор, который используется для поиска строк, содержащих определённый шаблон символов. Подробнее о нём читайте в нашей статье.
- Синтаксис LIKE SQL
- Примеры использования LIKE SQL
Использовать оператор LIKE в SQL очень просто: достаточно прописать стандартную команду выбора SELECT * FROM и задать условие через WHERE, где и будет использован оператор LIKE.
Шаблон LIKE SQL:
SELECT column1, column2, ...FROM table_nameWHERE columnN LIKE pattern;
Существует два подстановочных знака, которые используются в сочетании с оператором LIKE SQL:
- % — знак процента представляет собой ноль, один или несколько символов;
- _ — подчёркивание представляет собой один символ.
Примеры использования LIKE SQL
Рассмотрим SQL LIKE примеры. Представим, что вы хотите найти все имена, начинающиеся с буквы J. Для этого достаточно использовать следующий запрос:
SELECT * FROM table_name WHERE name LIKE 'J%';
В данном случае символ % используется для указания любого количества символов после J. Таким образом, запрос найдёт все имена, которые начинаются с буквы J, независимо от того, какие символы следуют за ней.
Ещё один пример — поиск всех адресов электронной почты, содержащих слово gmail. Для этого можно использовать следующий запрос:
SELECT * FROM table_name WHERE email LIKE '%gmail%';
Здесь символы % используются для указания, что слово gmail может быть в любом месте в адресе электронной почты.
Также можно использовать символ _ для указания одного символа. Например, запрос ниже найдет все имена, состоящие из шести символов. Эти имена должны начинаться с буквы J и заканчиваться буквой n:
SELECT * FROM table_name WHERE name LIKE 'J____n';
Здесь каждый символ _ указывает на любой один символ.
Иногда символы % и _ сами могут быть частью искомой строки. В таких случаях их нужно экранировать. Например, запрос ниже найдет все имена, содержащие символ %:
SELECT * FROM table_name WHERE name LIKE '%%%';
Это было короткое руководство по работе с SQL LIKE. Также вы можете почитать о других основных командах SQL.