4

Voici une version simplifiée de ma requête sql qui utilise CONTAINSTABLE pour la recherche de texte intégral.SQL Server - Recherche de texte libre avec mot-clé vide

DECLARE @pSearchFor AS NVARCHAR(100); 
SET @pSearchFor = 'SomeKeyword'; 

SELECT MS.[ModuleScreenID] AS ScreenID 
    ,MS.[ModuleScreenCode] AS ScreenCode 
    ,M.[Description] AS ModuleDescription 
    ,M.[ModuleCode] AS ModuleCode   
    ,FT.[Rank] 
FROM ModuleScreen MS 
    JOIN Module M ON MS.ModuleID = M.ModuleID 
    JOIN CONTAINSTABLE(ModuleScreen, *, @pSearchFor) FT ON MS.ModuleScreenID = FT.[KEY] 

Je veux passer la valeur vide ou nulle pour le paramètre @pSearchFor de telle sorte que tous les enregistrements sont retournés par la recherche en texte intégral. Mais j'obtiens une erreur "Null ou un prédicat de texte intégral vide" lorsque je passe une valeur vide ou nulle. Après googling, j'ai trouvé que CONTAINSTABLE ne peut pas prendre un paramètre vide pour les mots-clés. J'ai aussi vu cela question dans SO mais ça ne m'a pas aidé. Puis-je effectuer une jointure conditionnelle avec CONTAINSTABLE (uniquement lorsqu'une valeur est spécifiée pour le paramètre @pSearchFor)?. Je ne suis pas sûr de savoir comment y parvenir. Apprécierait n'importe quel pointeur.

Répondre

0

Qu'attendez-vous lorsque vous recherchez une valeur vide ou nulle? est-ce que vous vous attendez à ce que la requête ne renvoie rien ou vous attendez-vous à ce qu'elle renvoie quelque chose d'autre?

Si vous voulez revenir rien, alors vous êtes mieux de faire quelque chose comme ceci:

DECLARE @pSearchFor AS NVARCHAR(100); 
SET @pSearchFor = 'SomeKeyword'; 

IF @pSearchFor IS NOT NULL AND @pSearchFor <> '' 
BEGIN 
    SELECT MS.[ModuleScreenID] AS ScreenID 
     ,MS.[ModuleScreenCode] AS ScreenCode 
     ,M.[Description] AS ModuleDescription 
     ,M.[ModuleCode] AS ModuleCode   
     ,FT.[Rank] 
    FROM ModuleScreen MS 
     JOIN Module M ON MS.ModuleID = M.ModuleID 
     JOIN CONTAINSTABLE(ModuleScreen, *, @pSearchFor) FT ON MS.ModuleScreenID = FT.[KEY] 
END 
ELSE 
BEGIN 
    SELECT MS.[ModuleScreenID] AS ScreenID 
     ,MS.[ModuleScreenCode] AS ScreenCode 
     ,M.[Description] AS ModuleDescription 
     ,M.[ModuleCode] AS ModuleCode   
     ,FT.[Rank] 
    FROM ModuleScreen MS 
     JOIN Module M ON MS.ModuleID = M.ModuleID 
END 

modifier: fixe revenir maintenant tous les enregistrements lorsque la chaîne nulle ou vide est fourni.

Si vous avez plus de 2 CONTIENT requêtes de table avec les chaînes de recherche différentes, alors je vous suggère de générer la requête en utilisant SQL dynamique car il serait beaucoup plus facile à entretenir que la chaîne 2^n de près les mêmes requêtes

Edit: après avoir examiné un moyen de le faire sans utiliser plusieurs copies en utilisant une table temporaire comme ceci:

DECLARE @pSearchFor AS NVARCHAR(100); 
SET @pSearchFor = 'SomeKeyword'; 

SELECT * INTO #temp FROM CONTAINSTABLE(ModuleScreen, *, @pSearchFor) 

SELECT MS.[ModuleScreenID] AS ScreenID 
    ,MS.[ModuleScreenCode] AS ScreenCode 
    ,M.[Description] AS ModuleDescription 
    ,M.[ModuleCode] AS ModuleCode   
    ,FT.[Rank] 
FROM Module M 
    JOIN ModuleScreen MS ON MS.ModuleID = M.ModuleID AND (
     (1 = CASE WHEN ISNULL(@pSearchFor, '') = '' THEN 1 ELSE 0 END 
     OR CONTAINS(MS.*, @pSearchFor) 
    LEFT OUTER JOIN #temp FT ON MS.ModuleScreenID = FT.[Key] 

cela devrait vous donner ce que vous voulez sans avoir à dupliquer les choses, mais vous pouvez limiter le résultat qui est introduit dans la table #temp plus car il devient lent pour les tables plus grandes.

+0

Je veux que tous les enregistrements soient retournés lorsque les mots-clés sont vides ou nuls. J'ai également mentionné cela dans ma question initiale. – muruge

+0

Voir la mise à jour, espérons que cela vous aide. – Seph

+0

Merci pour votre suggestion. J'ai pensé à cette réponse mais je n'ai pas voulu utiliser la même requête deux fois que vous l'avez mentionné dans votre réponse éditée. En outre, je dois utiliser cette requête dans une procédure stockée et ne peut pas utiliser un SQL dynamique. Existe-t-il un moyen de joindre ** conditionnellement à CONTAINSTABLE **? – muruge

3
DECLARE @pSearchFor AS NVARCHAR(100); 

SET @pSearchFor = 'SomeKeyword'; 
--if @pSearch comes as parameter then -- 
set @pSearch = ISNULL(@pSearch,'*') 

SELECT MS.[ModuleScreenID] AS ScreenID 
    ,MS.[ModuleScreenCode] AS ScreenCode 
    ,M.[Description] AS ModuleDescription 
    ,M.[ModuleCode] AS ModuleCode   
    ,FT.[Rank] 
FROM ModuleScreen MS 
    JOIN Module M ON MS.ModuleID = M.ModuleID 
    JOIN CONTAINSTABLE(ModuleScreen, *, @pSearchFor) FT ON MS.ModuleScreenID = FT.[KEY] 
where @pSearchFor = '*' OR FT.[KEY] is not null 

Je viens de résoudre exactement le même problème et pensé à vous aider.

+0

Rock, ça a marché pour moi. Merci. – Jeremy

-1

J'ai également eu le même problème et l'ai résolu en ajoutant/ajoutant un mot clé factice 'fts' à la colonne indexée de recherche pour tous les enregistrements.

if(nullif(@pSearchFor,'') is null) 
begin 
    set @pSearchFor= 'fts';     
end 
Questions connexes