问题
I have a requirement from a client to have a search-field where he wants to input any text and search for every word in that text field in multiple full-text indexed columns which contain customer information, from a customer information table.
So, for example, if he inputs FL Diana Brooks Miami 90210, he wants all of these terms (FL, Diana, Brooks, Miami, 90210) to each be searched into the State, FirstName, LastName, City and Zip columns.
Now, this seems totally a bad idea to begin with and as an alternative I suggested using multiple fields where to input this information separately. Nonetheless, the point I am at is having to make a proof of concept as to why this won't work, from a performance perspective, and that it's better to have multiple fields where you input the term you want to search for.
So, getting to my query, I'm trying to write a Full-Text query to do what the client has asked for in order to get a benchmark for performance.
What I have so far doesn't seem to work, so I guess I am asking if it's even possible to do this?
declare
@zip varchar(10) = 90210
, @lastName varchar(50) = 'Brooks'
, @firstName varchar(50) = 'Diana'
, @city varchar(50) = 'Miami'
, @state char(2) = 'FL'
, @searchTerm varchar(250) = ''
, @s varchar(1) = ' '
set @searchTerm = @state + ' ' + @firstName + ' ' + @lastName + ' ' + @city
select *
from freetexttable(contacts, (zip, lastName, FirstName, city, state), @searchTerm) ftTbl
inner join contacts c on ftTbl.[key] = c.ContactID
The query I have above seems to work, but is not restrictive enough in order to find only the single record I'm looking for and is returning a whole lot more (which I'm guessing that it's because I'm using FREETEXTTABLE).
I've also tried replacing it with CONTAINSTABLE, but I get an error saying:
Msg 7630, Level 15, State 3, Line 26
Syntax error near 'Diana' in the full-text search condition 'FL Diana Brooks Miami'.
With using regular indexes I have been able to solve this, but I'm curious if it's even possible to do the same thing with Full-Text.
Using regular indexes I have a query with a adaptable WHERE clause, like below:
WHERE C.FirstName like coalesce(@FirstName + '%' , C.FirstName)
AND C.LastName like coalesce(@LastName + '%' , C.LastName)
etc.
回答1:
You can create a view WITH SCHEMABINDING with id and concatinated columns:
CREATE VIEW dbo.SearchView WITH SCHEMABINDING
AS
SELECT id,
[State]+' ',
[FirstName]+' ',
[LastName]+' ',
[City]+' ',
[Zip] as search_string
FROM YourTable
Create index
CREATE UNIQUE CLUSTERED INDEX UCI_SearchView ON dbo.SearchView (id ASC)
Then create full-text index on search_string field.
USE YourDB
GO
--Enable Full-text search on the DB
IF (SELECT DATABASEPROPERTY(DB_NAME(), N'IsFullTextEnabled')) <> 1
EXEC sp_fulltext_database N'enable'
GO
--Create a full-text catalog
IF NOT EXISTS (SELECT * FROM dbo.sysfulltextcatalogs WHERE [name] = N'CatalogName')
EXEC sp_fulltext_catalog N'CatalogName', N'create'
GO
EXEC sp_fulltext_table N'dbo.SearchView', N'create', N'CatalogName', N'IndexName'
GO
--Add a column to catalog
EXEC sp_fulltext_column N'dbo.SearchView', N'search_string', N'add', 0 /* neutral */
GO
--Activate full-text for table/view
EXEC sp_fulltext_table N'dbo.SearchView', N'activate'
GO
--Full-text index update
exec sp_fulltext_catalog 'CatalogName', 'start_full'
GO
After that you need to write some function to construct a search condition. F.e.
FL Diana Brooks Miami 90210
Became:
"FL*" AND "Diana*" AND "Brooks*" AND "Miami*" AND "90210*"
And use it in FREETEXT or CONTAINS searches:
DECLARE @search nvarchar(4000) = '"FL*" AND "Diana*" AND "Brooks*" AND "Miami*" AND "90210*"'
SELECT sv.*
FROM dbo.SearchView sv
INNER JOIN CONTAINSTABLE (dbo.SearchView, search_string, @search) as c
ON c.[KEY] = sv.id
来源:https://stackoverflow.com/questions/40378070/fulltext-search-multiple-columns-for-multiple-search-terms