39 votes

7645 Prédicat plein texte nul ou vide

J'ai une requête qui fonctionnait bien sous SQL2005 mais qui, en déplaçant la base de données vers SQL2008, me donne l'erreur du titre.

Le code qui pose problème est un appel à CONTAINS, CONTAINSTABLE ou FREETEXT avec un paramètre vide. Cependant, j'essaie d'appeler ou de joindre uniquement lorsqu'il y a une valeur, comme suit

where (@search_term = '' or (FREETEXT(lst.search_text, @search_term)))

o

left join containstable (listing_search_text, search_text,  @search_term) ftb on l.listing_id = ftb.[key] 
    and len(@search_term) > 0

Cependant, je ne trouve aucune solution pour que cela fonctionne avec SQL2008. Avez-vous une idée ?

Je sais que je peux faire du SQL dynamique ou avoir une instruction if avec deux cas différents (select avec FT join, select sans FT join). Existe-t-il une meilleure solution de contournement qui ne nécessite pas de faire cela ?

57voto

Chris Lively Points 59564

J'ai trouvé la réponse à cette question aujourd'hui en convertissant ma propre base de données de SQL 2005 à SQL 2008.

Passez "" pour votre terme de recherche et changer le @search_term = '' le test pour être @search_term = '""' Le serveur SQL ignorera les guillemets doubles et ne lancera pas d'erreur.

Par exemple, la commande suivante renvoie tous les enregistrements de la table Utilisateurs :

declare  @SearchTerm nvarchar(250)

SET @SearchTerm = '""'

select UserId, U.Description, U.UserName
from dbo.Users U
WHERE ((@SearchTerm = '""') OR CONTAINS( (U.Description, U.UserName), @SearchTerm))

Si vous utilisez .Net, vous pouvez vous procurer une copie de la classe FullTextSearch de E. W. Bachtal. Son site est très instructif : http://ewbi.blogs.com/develops/

3 votes

(@SearchTerm = '""') ajoute une quantité extrême de lectures et la requête perd parfois du temps (comme l'a noté whiplashtony).

14voto

whiplashtony Points 121

Cette solution n'a pas fonctionné pour moi sur SQL 2008. La réponse semblait assez claire et était jugée utile, mais j'obtenais des délais d'attente sur une table contenant 2 millions d'enregistrements. En fait, la simple exécution de la requête dans SSMS a bloqué un serveur.

Il ne semblait pas aimer le OU dans la clause where, mais je pouvais exécuter la requête sans problème en séparant les conditions.

J'ai fini par utiliser un UNION avec succès comme solution de rechange.

declare  @SearchTerm nvarchar(250)

SET @SearchTerm = '""'

select UserId, U.Description, U.UserName
from dbo.Users U
WHERE ((@SearchTerm = '""') 

UNION 

select UserId, U.Description, U.UserName
from dbo.Users U
WHERE CONTAINS( (U.Description, U.UserName), @SearchTerm))

3 votes

Le problème que vous avez rencontré est probablement dû au fait que celui que j'ai n'est en aucun cas optimisé. Dernièrement, j'ai constaté que l'utilisation de UNIONs au lieu de ORs dans les clauses WHERE est plusieurs fois plus rapide. Donc +1

0 votes

J'avais une requête avec des tonnes de LIKE et de caractères génériques qui fonctionnait comme un chien. J'avais essayé l'indexation en texte intégral, ce qui n'a pas aidé du tout. En utilisant les UNIONs au lieu des ORs, ma requête est passée de ~15 secondes à moins de 1. +1 !!!!

0 votes

Que se passe-t-il si j'ai une jointure interne entre deux tables et que je veux faire une recherche en texte intégral sur les deux tables ? cela signifie que j'aurai besoin d'environ 3-4 unions ?

3voto

Ajoutez simplement des guillemets. Vous pouvez vérifier si la chaîne est vide et y ajouter des guillemets.

Set @search_term = case when @search_term = '' then '""' else @Address End

Voilà -

where (@search_term = '""' or (FREETEXT(lst.search_text, @search_term)))

1voto

user3038470 Points 11

Le problème avec FTS et l'opérande OR a été corrigé dans SP2 CU4. Si vous êtes à ce niveau ou à un niveau ultérieur, la condition OR devrait fonctionner sans avoir besoin d'UNION. Nous avons essayé une mise à jour très récente de SP2 CU8 et FTS fonctionne maintenant avec OR. De même, les recherches telles que 3.12, qui échouaient auparavant, fonctionnent parfaitement.

1voto

FloverOwe Points 63

J'ai constaté que l'utilisation de "a" comme valeur par défaut fonctionne si SQL-Server est configuré pour ignorer les "mots parasites".

SET @SearchPhrase = coalesce(@SearchPhrase, 'a'); /* replace with 'a' if null parameter */ 
SELECT ... WHERE 
    (@SearchPhrase = 'a' OR contains(Search_Text, @SearchPhrase))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X