I'm having a problem rewriting an existing process that uses CONTAINS
predicate. The existing process is working using a CURSOR
, but it's really slow, and getting slower as more data is inserted.
I have made up a simple example (code below) containing two tables - one is Full Text Indexed, and the other has a column which identifies a CONTAINS
condition to choose rows from the first.
The current stored procedure uses a CURSOR
to loop through the second table, setting a @filter
variable, then uses CONTAINS
to locate the rows from the first table that match. The problem is that it runs for hours, and it's getting worse.
To speed the process up, I tried to use the CONTAINS
predicate directly on the column value rather than going through the pain of a cursor... but I'm getting a syntax error. My example is below.
I've tried to implement a CROSS APPLY
and I've also tried to write a User-Defined Function (fnCONTAINS
) with no luck.
IF ( object_id('Players') IS NOT NULL )
DROP TABLE Players
go
IF ( object_id('TeamNeeds') IS NOT NULL )
DROP TABLE TeamNeeds
go
-- create fulltext catalog ft as default
go
CREATE TABLE Players
(
PlayerID INT IDENTITY(1, 1),
PlayerName VARCHAR(20),
PlayerPositions VARCHAR(60)
)
go
CREATE UNIQUE INDEX IXPlayerID
ON Players( PlayerID )
go
CREATE fulltext INDEX ON Players(PlayerPositions) KEY INDEX IXPlayerID
go
INSERT Players
(PlayerName,
PlayerPositions)
VALUES( 'Patrick Travers',
'Pitcher,Left Field,Center Field,Right Field,Shortstop' )
go
CREATE TABLE TeamNeeds
(
TeamID INT,
Keywords VARCHAR(50)
)
go
INSERT TeamNeeds
(TeamID,
Keywords)
VALUES( 1,
'"Center Field" and "Shortstop" and "Pitcher"' )
go
WAITFOR delay '00:00:05'
go -- Give the Full Text Index process time to populate the catalog
SELECT PlayerID,
PlayerName,
PlayerPositions
FROM Player,
TeamNeeds
WHERE CONTAINS(PlayerPositions, Keywords)
go -- Syntax error on Keywords...
SELECT PlayerID,
PlayerName,
PlayerPositions
FROM Players,
TeamNeeds
WHERE CONTAINS(PlayerPositions, '"Center Field" and "Shortstop" and "Pitcher"')
go -- Works just fine, but requires setting an explicit search expression for every search, which is terribly slow
A predicate is an expression that evaluates to TRUE, FALSE, or UNKNOWN. Predicates are used in the search condition of WHERE clauses and HAVING clauses, the join conditions of FROM clauses, and other constructs where a Boolean value is required.
Predicate: It is the value returned by the WHERE clause of the SQL statement. Object: Defines the Table on which we have performed that query or operation.
What Is a Predicate? A predicate is simply an expression that evaluates to TRUE, FALSE, or UNKNOWN. Predicates are typically employed in the search condition of WHERE and HAVING clauses, the join conditions of FROM clauses, as well as any other part of a query where a boolean value is required.
All predicates perform their comparisons using Logical (internal storage) data values. However, some predicates can perform format mode conversion on the predicate value(s), converting it from ODBC or Display format to Logical format.
This is only possible with a multi statement TVF as far as I can see.
Creating the following function
CREATE FUNCTION [dbo].[ft_test] (@Keywords VARCHAR(50))
RETURNS @ReturnTable TABLE (
PlayerID INT,
PlayerName VARCHAR(20),
PlayerPositions VARCHAR(60))
AS
BEGIN
INSERT INTO @ReturnTable
SELECT PlayerID,
PlayerName,
PlayerPositions
FROM Players
WHERE CONTAINS(PlayerPositions, @Keywords)
RETURN
END
Then the following works fine
SELECT *
FROM TeamNeeds
CROSS APPLY [dbo].[ft_test] (Keywords) CA
Though the inline version fails with "The inline function "x" cannot take correlated parameters or subqueries because it uses a full-text operator."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With