I have a problem using the sql server full text with parameter
Alter Procedure[dbo].[SelectFullName]
#fullname nvarchar(45)
As
Select*from [dbo][NamePersonTB]
Where CONTAINS (fullname,'"*#fullname*"')
I want to use SAME LIKE to fullname
You are using the #Fullname as a literal string by wrapping it in single quotes. You need to pass a variable directly into the CONTAINS function if you want to use the actual value of #Fullname as your search criteria
Also note you cannot do the %SearchTerm% exactly the same way if you want to leverage your fulltext index. You can search for words that have a matching prefix, but not matching suffix/middle. For more info on wildcard(*) usage with CONTAINS, see <prefix_term> section in the MS doc
Below I've created two ways I might set up the fulltext search, a simple version and a more advanced. Not sure your business needs, but the more advanced fully leverages the fulltext index and has a "smart" ranking option that is pretty neat
Table Setup
CREATE TABLE NamePersonTB (ID INT IDENTITY(1,1) CONSTRAINT PK_NamePersonTB Primary Key,FullName NVARCHAR(100))
INSERT INTO NamePersonTB
VALUES ('John Smith')
,('Jane Smith')
,('Bill Gates')
,('Satya Nadella')
CREATE FULLTEXT CATALOG ct_test AS DEFAULT;
CREATE FULLTEXT INDEX ON NamePersonTB(FullName) KEY INDEX PK_NamePersonTB;
Fulltext Search Script
DECLARE #FullName NVARCHAR(45);
/*Sample searches*/
SET #FullName = 'John Smith' /*Notice John Smith appears first in ranked search*/
--SET #FullName = 'Smith'
--SET #FullName = 'Sm'
--SET #FullName = 'Bill'
DECLARE #SimpleContainsSearchCriteria NVARCHAR(1000)
,#RankedContainsSearchCriteria NVARCHAR(1000)
/*
Below will
1. Parses the words into rows
2. Adds wildcard to end(cannot add wildcard to prefix according to MS doc on CONTAINS)
3. Combines all words back into single row with separator to create CONTAINS search criteria
*/
SELECT #SimpleContainsSearchCriteria = STRING_AGG(CONCAT('"',A.[Value],'*"'),' AND ')
FROM STRING_SPLIT(REPLACE(#Fullname,'"',''),' ') AS A /*REPLACE() removes any double quotes as they will break your search*/
/*Same as above, but uses OR to include more results and will utilize [Rank] so better matches appear first*/
SELECT #RankedContainsSearchCriteria = STRING_AGG(CONCAT('"',A.[Value],'*"'),' OR ')
FROM STRING_SPLIT(REPLACE(#Fullname,'"',''),' ') AS A
/*Included so you can see the search critieria. Should remove in final proc*/
SELECT #Fullname AS FullNameInput
,#SimpleContainsSearchCriteria AS SimpleSearchCriteria
,#RankedContainsSearchCriteria AS RankedContainsSearchCriteria
/*Simple AND match*/
SELECT *
FROM NamePersonTB AS A
WHERE CONTAINS(FullName,#SimpleContainsSearchCriteria)
/*CONTAINSTABLE match alternative. Uses OR criteria and then ranks so best matches appear at the top*/
SELECT *
FROM CONTAINSTABLE(NamePersonTB,FullName,#RankedContainsSearchCriteria) AS A
INNER JOIN NamePersonTB AS B
ON A.[Key] = B.ID
ORDER BY A.[Rank] DESC
Sample Search Criteria
FullNameInput
SimpleSearchCriteria
RankedContainsSearchCriteria
John Smith
"John*" AND "Smith*"
"John*" OR "Smith*"
Output of Simple Search
ID
FullName
1
John Smith
Output of Ranked Search
KEY
RANK
ID
FullName
1
48
1
John Smith
2
32
2
Jane Smith
Related
Ok so I have a table with three columns:
Id, Key, Value
I would like to delete all rows where Value is empty (''). Therefore I wrote the query to select before I delete which was:
Select * from [Imaging.ImageTag] where [Value] = ''
all pretty standard so far...
Now heres the strange part. This query returned two rows shown below with commas seperating columns:
CE7C367C-5C4A-4531-9C8C-8F2A26B1B980, ObjectType, 🎃
F5B2F8A8-C4A8-4799-8824-E5FFEEDAB887, Caption, 🍰
Why are these two rows matching on ''?
Extra Info
I am using Sql-Server, The [Value] column is of type NVARCHAR(300) and yes the table name really is [Imaging.ImageTag]
This is collation dependant.
Matches empty string
SELECT 1 where N'' = N'🍰' COLLATE latin1_general_ci_as
Doesn't match empty string
SELECT 1 WHERE N'' = N'🍰' COLLATE latin1_general_100_ci_as
The 100 collations are more up-to-date (though still not bleeding edge, they have been available since 2008) and you should use more modern collations unless you have some specific reason not to. The BOL entry for 100 collations specifically calls out
Weighting has been added to previously non-weighted characters that
would have compared equally.
It's not an answer to your "why", but in terms of your overall goal, perhaps you should alter your strategy for searching for empty values:
Select * from [Imaging.ImageTag] where LEN([Value]) = 0
As per the comments (thanks Martin Smith for providing some copy/pastable emoji):
SELECT CASE WHEN N'' = N'🍰' then 1 else 0 end --returns 1, no good for checking
SELECT LEN(N'🍰') --returns 2, can be used to check for zero length values?
Complementing this answers
When you need use 'like' at sql
WHERE
N'' + COLUMNS like N'%'+ #WordSearch +'%' COLLATE latin1_general_100_ci_as
Google send me here looking for a way filter all rows with an emoji on a varchar column.
In case that your looking for something similar:
SELECT mycolumn
FROM mytable
WHERE REGEXP_EXTRACT(mycolumn,'\x{1f600}') <> ''
--sqlserver WHERE SUBSTRING(MyCol, (PATINDEX( '\x{1f600}', MyCol ))) <> ''
the \x{1f600} is the char code for the searched emoji, you can find the emoji codes here
Ok so I have a table with three columns:
Id, Key, Value
I would like to delete all rows where Value is empty (''). Therefore I wrote the query to select before I delete which was:
Select * from [Imaging.ImageTag] where [Value] = ''
all pretty standard so far...
Now heres the strange part. This query returned two rows shown below with commas seperating columns:
CE7C367C-5C4A-4531-9C8C-8F2A26B1B980, ObjectType, 🎃
F5B2F8A8-C4A8-4799-8824-E5FFEEDAB887, Caption, 🍰
Why are these two rows matching on ''?
Extra Info
I am using Sql-Server, The [Value] column is of type NVARCHAR(300) and yes the table name really is [Imaging.ImageTag]
This is collation dependant.
Matches empty string
SELECT 1 where N'' = N'🍰' COLLATE latin1_general_ci_as
Doesn't match empty string
SELECT 1 WHERE N'' = N'🍰' COLLATE latin1_general_100_ci_as
The 100 collations are more up-to-date (though still not bleeding edge, they have been available since 2008) and you should use more modern collations unless you have some specific reason not to. The BOL entry for 100 collations specifically calls out
Weighting has been added to previously non-weighted characters that
would have compared equally.
It's not an answer to your "why", but in terms of your overall goal, perhaps you should alter your strategy for searching for empty values:
Select * from [Imaging.ImageTag] where LEN([Value]) = 0
As per the comments (thanks Martin Smith for providing some copy/pastable emoji):
SELECT CASE WHEN N'' = N'🍰' then 1 else 0 end --returns 1, no good for checking
SELECT LEN(N'🍰') --returns 2, can be used to check for zero length values?
Complementing this answers
When you need use 'like' at sql
WHERE
N'' + COLUMNS like N'%'+ #WordSearch +'%' COLLATE latin1_general_100_ci_as
Google send me here looking for a way filter all rows with an emoji on a varchar column.
In case that your looking for something similar:
SELECT mycolumn
FROM mytable
WHERE REGEXP_EXTRACT(mycolumn,'\x{1f600}') <> ''
--sqlserver WHERE SUBSTRING(MyCol, (PATINDEX( '\x{1f600}', MyCol ))) <> ''
the \x{1f600} is the char code for the searched emoji, you can find the emoji codes here
I use CONTAINSTABLE for my searching algorithm. I want to search column value with ignoring dash in particular column value. for example, column contains '12345-67' then it should search with '1234567' as below query.
SELECT *
FROM table1 AS FT_Table
INNER JOIN CONTAINSTABLE(table2, columnname, '1234567') AS Key_Table ON FT_Table.ID = Key_Table.[Key]
Is there any way to ignore dash (-) while searching with string that doesn't contain a dash (-)?
I did some digging and spent a few hours time :)
Unfortunately, there is no way to perform it. Looks like Sql Server FTS populate the words by breaking words (except whitespaces) also special characters( -, {, ( etc.)
But it doesn't populate complete word and my understanding there is no way to provide some population rules for satisfy the need. (I mean, telling to population service, If the word contains "-" replace it with "".)
I provided an example for clarify the situation.
Firstly, create table, FTS catalog, Full text index and insert sample row for table.
CREATE TABLE [dbo].[SampleTextData]
(
[Id] int identity(1,1) not null,
[Text] varchar(max) not null,
CONSTRAINT [PK_SampleTextData] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
);
CREATE FULLTEXT CATALOG ftCatalog AS DEFAULT;
CREATE FULLTEXT INDEX ON SampleTextData
(Text)
KEY INDEX PK_SampleTextData
ON ft
INSERT INTO [SampleTextData] values ('samp-le text')
Then, provide sample queries;
select * from containstable(SampleTextData,Text,'samp-le') --Success
select * from containstable(SampleTextData,Text,'samp') --Success
select * from containstable(SampleTextData,Text,'le') --Success
select * from containstable(SampleTextData,Text,'sample') -- Fail
These samples are successfully except one 'Samp-le'. For investigating the situtation, execute this query;
SELECT display_term, column_id, document_count
FROM sys.dm_fts_index_keywords (DB_ID('YourDatabase'), OBJECT_ID('SampleTextData'))
Output :
le 2 1
samp 2 1
samp-le 2 1
text 2 1
END OF FILE 2 1
The query gives us word results which are populated by FTS population service. As you see, the population results contain 'le', 'samp', 'samp-le' but not 'sample'. This is the reason how sample query getting failed.
Ok so I have a table with three columns:
Id, Key, Value
I would like to delete all rows where Value is empty (''). Therefore I wrote the query to select before I delete which was:
Select * from [Imaging.ImageTag] where [Value] = ''
all pretty standard so far...
Now heres the strange part. This query returned two rows shown below with commas seperating columns:
CE7C367C-5C4A-4531-9C8C-8F2A26B1B980, ObjectType, 🎃
F5B2F8A8-C4A8-4799-8824-E5FFEEDAB887, Caption, 🍰
Why are these two rows matching on ''?
Extra Info
I am using Sql-Server, The [Value] column is of type NVARCHAR(300) and yes the table name really is [Imaging.ImageTag]
This is collation dependant.
Matches empty string
SELECT 1 where N'' = N'🍰' COLLATE latin1_general_ci_as
Doesn't match empty string
SELECT 1 WHERE N'' = N'🍰' COLLATE latin1_general_100_ci_as
The 100 collations are more up-to-date (though still not bleeding edge, they have been available since 2008) and you should use more modern collations unless you have some specific reason not to. The BOL entry for 100 collations specifically calls out
Weighting has been added to previously non-weighted characters that
would have compared equally.
It's not an answer to your "why", but in terms of your overall goal, perhaps you should alter your strategy for searching for empty values:
Select * from [Imaging.ImageTag] where LEN([Value]) = 0
As per the comments (thanks Martin Smith for providing some copy/pastable emoji):
SELECT CASE WHEN N'' = N'🍰' then 1 else 0 end --returns 1, no good for checking
SELECT LEN(N'🍰') --returns 2, can be used to check for zero length values?
Complementing this answers
When you need use 'like' at sql
WHERE
N'' + COLUMNS like N'%'+ #WordSearch +'%' COLLATE latin1_general_100_ci_as
Google send me here looking for a way filter all rows with an emoji on a varchar column.
In case that your looking for something similar:
SELECT mycolumn
FROM mytable
WHERE REGEXP_EXTRACT(mycolumn,'\x{1f600}') <> ''
--sqlserver WHERE SUBSTRING(MyCol, (PATINDEX( '\x{1f600}', MyCol ))) <> ''
the \x{1f600} is the char code for the searched emoji, you can find the emoji codes here
I'm currently working on an application where we have a SQL-Server database and I need to get a full text search working that allows us to search people's names.
Currently the user can enter a into a name field that searches 3 different varchar cols. First, Last, Middle names
So say I have 3 rows with the following info.
1 - Phillip - J - Fry
2 - Amy - NULL - Wong
3 - Leo - NULL - Wong
If the user enters a name such as 'Fry' it will return row 1. However if they enter Phillip Fry, or Fr, or Phil they get nothing.. and I don't understand why its doing this. If they search for Wong they get rows 2 and 3 if they search for Amy Wong they again get nothing.
Currently the query is using CONTAINSTABLE but I have switched that with FREETEXTTABLE, CONTAINS, and FREETEXT without any noticeable differences in the results. The table methods are be preferred because they return the same results but with ranking.
Here is the query.
....
#Name nvarchar(100),
....
--""s added to prevent crash if searching on more then one word.
DECLARE #SearchString varchar(100)
SET #SearchString = '"'+#Name+'"'
SELECT Per.Lastname, Per.Firstname, Per.MiddleName
FROM Person as Per
INNER JOIN CONTAINSTABLE(Person, (LastName, Firstname, MiddleName), #SearchString)
AS KEYTBL
ON Per.Person_ID = KEYTBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEYTBL.RANK DESC;
....
Any Ideas...? Why this full text search is not working correctly ?
If you're just searching people's names, it might be in your best interest to not even use the full text index. Full text index makes sense when you have large text fields, but if you're mostly dealing with one word per field, I'm not sure how much extra you would get out of full text indexes. Waiting for the full text index to reindex itself before you can search for new records can be one of the many problems.
You could just make a query such as the following. Split your searchstring on spaces, and create a list of the search terms.
Select FirstName,MiddleName,LastName
From person
WHERE
Firstname like #searchterm1 + '%'
or MiddleName like #searchterm1 + '%'
or LastName like #searchterm1 + '%'
or Firstname like #searchterm2 + '%'
etc....
FreeTextTable should work.
INNER JOIN FREETEXTTABLE(Person, (LastName, Firstname, MiddleName), #SearchString)
#SearchString should contain the values like 'Phillip Fry' (one long string containing all of the lookup strings separated by spaces).
If you would like to search for Fr or Phil, you should use asterisk: Phil* and Fr*
'Phil' is looking for exactly the word 'Phil'. 'Phil*' is looking for every word which is starting with 'Phil'
Thanks for the responses guys I finally was able to get it to work. With part of both Biri, and Kibbee's answers. I needed to add * to the string and break it up on spaces in order to work. So in the end I got
....
#Name nvarchar(100),
....
--""s added to prevent crash if searching on more then one word.
DECLARE #SearchString varchar(100)
--Added this line
SET #SearchString = REPLACE(#Name, ' ', '*" OR "*')
SET #SearchString = '"*'+#SearchString+'*"'
SELECT Per.Lastname, Per.Firstname, Per.MiddleName
FROM Person as Per
INNER JOIN CONTAINSTABLE(Person, (LastName, Firstname, MiddleName), #SearchString)
AS KEYTBL
ON Per.Person_ID = KEYTBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEYTBL.RANK DESC;
....
There are more fields being searched upon I just simplified it for the question, sorry about that, I didn't think it would effect the answer. It actually searches a column that has a csv of nicknames and a notes column as well.
Thanks for the help.
Another approach could be to abstract the searching away from the individual fields.
In other words create a view on your data which turns all the split fields like firstname lastname into concatenated fields i.e. full_name
Then search on the view. This would likely make the search query simpler.
You might want to check out Lucene.net as an alternative to Full Text.