CONTAINS (Transact-SQL)

Prédicat utilisé dans une clause WHERE pour effectuer une recherche dans des colonnes contenant des données de type caractère. Il peut s'agir de correspondances exactes ou floues (moins précises) de mots ou d'expressions, de mots à proximité les uns des autres, ou encore de correspondances pondérées.

Dans SQL Server, vous pouvez utiliser des noms en quatre parties dans les prédicats de texte intégral CONTAINS ou FREETEXT pour exécuter des requêtes sur des serveurs liés.

CONTAINS peut rechercher :

  • un mot ou une expression ;

  • le préfixe d'un mot ou d'une expression ;

  • un mot proche d'un autre mot ;

  • un mot dérivant d'un autre mot par inflexion (par exemple, le radical « part » a généré par inflexion les formes dérivées partir, départ, partant ou partie) ;

  • un mot synonyme d'un autre mot d'après un dictionnaire des synonymes (par exemple, le mot métal peut avoir des synonymes comme aluminium et acier).

Icône Lien de rubriqueConventions de syntaxe Transact-SQL

Syntaxe

CONTAINS
      ( { column_name | ( column_list ) | * } 
          , '<contains_search_condition>'     
   [ , LANGUAGE language_term ]
      ) 

<contains_search_condition> ::= 
    { <simple_term> 
    | <prefix_term> 
    | <generation_term> 
    | <proximity_term> 
    | <weighted_term> 
    } 
    | { ( <contains_search_condition> ) 
    [ { <AND> | <AND NOT> | <OR> } ] 
        <contains_search_condition> [ ...n ] 
    } 

<simple_term> ::= 
          word | "phrase"

<prefix term> ::= 
     { "word *" | "phrase *" }

<generation_term> ::= 
     FORMSOF ( { INFLECTIONAL | THESAURUS } , <simple_term> [ ,...n ] ) 

<proximity_term> ::= 
     { <simple_term> | <prefix_term> } 
     { { NEAR | ~ }
     { <simple_term> | <prefix_term> } 
     } [ ...n ] 

<weighted_term> ::= 
     ISABOUT 
        ( { { 
    <simple_term> 
  | <prefix_term> 
  | <generation_term> 
  | <proximity_term> 
  } 
   [ WEIGHT ( weight_value ) ] 
   } [ ,...n ] 
        ) 

<AND> ::= 
     { AND | & }

<AND NOT> ::= 
     { AND NOT | &! }

<OR> ::= 
     { OR | | }

Arguments

  • column_name
    Nom d'une colonne d'index de recherche en texte intégral de la table spécifiée dans la clause FROM. Les colonnes peuvent être de type char, varchar, nchar, nvarchar, text, ntext, image, xml, varbinary ou varbinary(max).

  • column_list
    Spécifie deux colonnes ou plus, séparées par des virgules. column_list doit être mis entre parenthèses. À moins que la valeur de language_term soit définie, une seule et même langue doit être utilisée dans toutes les colonnes de column_list.

  • *
    Spécifie que la requête doit baser sa recherche sur toutes les colonnes d'index de recherche en texte intégral de la table spécifiée dans la clause FROM pour la condition de recherche donnée. Les colonnes de la clause CONTAINS doivent provenir d'une table unique qui possède un index de recherche en texte intégral. À moins que la valeur de language_term soit définie, une seule et même langue doit être utilisée dans toutes les colonnes de la table.

  • LANGUAGE language_term
    Langue à utiliser pour l'analyse lexicale, la recherche de radical, les extensions et remplacements du dictionnaire des synonymes, ainsi que le remplacement des mots parasites (ou mots vides) dans le cadre de la requête. Ce paramètre est optionnel.

    Si des documents de langues différentes sont stockés ensemble en tant qu'objets blob dans une colonne unique, l'identificateur de paramètres régionaux (LCID) d'un document donné détermine la langue à utiliser pour l'indexation de son contenu. Lors de l'interrogation d'une telle colonne, la spécification de LANGUAGE language_term permet d'augmenter la probabilité d'une correspondance correcte.

    language_term peut être spécifié en tant que chaîne, entier ou valeur hexadécimale correspondant à l'identificateur de paramètres régionaux (LCID) d'une langue. Si l'argument language_term est spécifié, la langue qu'il représente est appliquée à tous les éléments de la condition de recherche. Si aucune valeur n'est définie, la langue du texte intégral de la colonne est utilisée.

    Lorsqu'il est spécifié comme chaîne, l'argument language_term correspond à la valeur de la colonne alias dans la vue de compatibilité sys.syslanguages (Transact-SQL). La chaîne doit être placée entre guillemets simples, comme dans la chaîne 'language_term'. Lorsqu'il est spécifié comme entier, l'argument language_term est alors le LCID actif identifiant la langue. Quand il est spécifié comme valeur hexadécimale, l'argument language_term est 0x suivi de la valeur hexadécimale du LCID. La valeur hexadécimale ne doit pas dépasser huit caractères, y compris les zéros non significatifs.

    Si la valeur est au format DBCS (jeu de caractères codés sur deux octets), SQL Server la convertit au format Unicode.

    Si la langue spécifiée n'est pas valide ou si aucune ressource correspondant à cette langue n'est installée, SQL Server retourne une erreur. Pour utiliser des ressources linguistiques neutres, indiquez 0x0 pour language_term.

  • <contains_search_condition>
    Spécifie le texte à rechercher dans column_name et les conditions à satisfaire pour une correspondance.

    L'argument <contains_search_condition> est de type nvarchar. Une conversion implicite se produit lorsqu'un autre type de données character est utilisé comme entrée. Dans l'exemple suivant, la variable @SearchWord, à laquelle est attribuée la valeur varchar(30), provoque une conversion implicite dans le prédicat CONTAINS.

    USE AdventureWorks;
    GO
    DECLARE @SearchWord varchar(30)
    SET @SearchWord ='performance'
    SELECT Description 
    FROM Production.ProductDescription 
    WHERE CONTAINS(Description, @SearchWord);
    

    Étant donné que la détection des paramètres ne fonctionne pas lors de la conversion, utilisez nvarchar afin d'obtenir de meilleures performances. Dans l'exemple, déclarez @SearchWord en tant que nvarchar(30).

    USE AdventureWorks;
    GO
    DECLARE @SearchWord nvarchar(30)
    SET @SearchWord = N'performance'
    SELECT Description 
    FROM Production.ProductDescription 
    WHERE CONTAINS(Description, @SearchWord);
    

    Vous pouvez également utiliser l'indicateur de requête OPTIMIZE FOR lorsqu'un plan non optimal est généré.

  • word
    Chaîne de caractères sans espaces ni ponctuation.

  • phrase
    Un ou plusieurs mots séparés par des espaces.

    [!REMARQUE]

    Certaines langues, notamment certaines langues asiatiques, peuvent contenir des expressions composées d'un ou de plusieurs mots non séparés par des espaces.

  • <simple_term>
    Spécifie une correspondance pour un mot ou une expression exacts. Exemples de termes simples autorisés : « lieu dit », « lieudit » et « Microsoft SQL Server ». Les expressions doivent être mises entre des guillemets doubles (""). Les mots d'une expression doivent apparaître dans l'ordre spécifié dans <contains_search_condition>, tels qu'ils apparaissent dans la colonne de la base de données. La recherche de caractères dans un mot ou une expression ne respecte pas la casse. Dans des colonnes d'index de recherche en texte intégral, les mots parasites (ou mots vides) (par exemple un, et ou le) ne sont pas stockés dans l'index de recherche en texte intégral. Si un mot vide est utilisé dans la recherche d'un mot unique, SQL Server retourne un message d'erreur indiquant que la requête contient uniquement des mots vides. SQL Server contient une liste standard des mots vides dans le répertoire \Mssql\Binn\FTERef de chaque instance de SQL Server.

    La ponctuation est ignorée. Par conséquent, CONTAINS(testing, "computer failure") retourne la ligne ayant la valeur « Where is my computer? Failure to find it would be expensive. » Pour plus d'informations sur le comportement de la coupure des mots, consultez Analyseurs lexicaux et générateurs de formes dérivées.

  • <prefix_term>
    Précise une correspondance de mots ou d'expressions commençant par le texte spécifié. Placez un terme préfixe entre guillemets doubles ("") et ajoutez un astérisque (*) avant les guillemets doubles fermants afin que tout le texte commençant par le terme simple spécifié avant l'astérisque soit pris en compte. La clause doit être définie de la manière suivante : CONTAINS (column, '"text*"'). L'astérisque correspond à aucun, à un ou à plusieurs caractères (du ou des mots racine dans le mot ou l'expression). Si le texte et l'astérisque ne sont pas délimités par des guillemets doubles, comme dans CONTAINS (column, 'text*'), la recherche en texte intégral considère l'astérisque comme un caractère et recherche les correspondances exactes avec text*. Le moteur d'indexation et de recherche en texte intégral ne trouve aucun mot contenant l'astérisque (*) car les analyseurs lexicaux ignorent en général ces caractères.

    Lorsque <prefix_term> est une expression, chaque mot qui la compose est considéré comme un préfixe séparé. Ainsi, une recherche spécifiant le préfixe « contrôle des mots* » trouvera les lignes contenant le texte « contrôle des mots clés », « contrôleur des mots », etc.

  • <generation_term>
    Précise une correspondance de mots lorsque les termes simples qui s'y trouvent contiennent des variantes du mot initial à rechercher.

  • INFLECTIONAL
    Spécifie que le générateur de formes dérivées dépendant de la langue doit être utilisé sur le terme simple spécifié. Le comportement du générateur de formes dérivées est défini en fonction des règles de racine de chaque langue spécifique. La langue neutre ne possède pas de générateur de formes dérivées associé. La langue des colonnes interrogées est utilisée pour se reporter au générateur de formes dérivées souhaité. Si language_term est spécifié, le générateur de formes dérivées correspondant à cette langue est utilisé.

    Un paramètre <simple_term> donné inclus dans <generation_term> ne peut pas correspondre à la fois aux noms et aux verbes.

  • THESAURUS
    Spécifie l'utilisation du dictionnaire des synonymes correspondant à la langue de texte intégral de la colonne ou à la langue spécifiée dans la requête. Les motifs les plus longs de <simple_term> sont interprétés par rapport au dictionnaire des synonymes et des termes supplémentaires sont créés pour étendre ou pour remplacer le motif d'origine. Si aucune correspondance n'est trouvée pour tout ou partie de <simple_term>, la partie sans correspondance est traitée en tant que simple_term. Pour plus d'informations sur le dictionnaire des synonymes pour la recherche en texte intégral, consultez Configuration du dictionnaire des synonymes.

  • <proximity_term>
    Spécifie une correspondance de mots ou d'expressions qui doit figurer dans le document faisant l'objet d'une recherche. À l'instar de l'opérateur AND, <proximity_term> requiert que les deux termes à rechercher existent dans le document faisant l'objet d'une recherche.

    • NEAR | ~
      Indique que le mot ou l'expression qui se trouve de chaque côté de l'opérateur NEAR ou ~ doit figurer dans un document pour qu'une correspondance soit retournée. Plusieurs termes de proximité peuvent être enchaînés, par exemple a NEAR b NEAR c ou a ~ b ~ c. Les termes de proximité enchaînés doivent tous figurer dans le document pour qu'une correspondance soit retournée.

      En cas d'utilisation de la fonction CONTAINSTABLE, la proximité des termes à rechercher affecte le classement de chaque document. Plus les termes de recherche correspondants sont proches dans un document, plus le classement du document est élevé. Si les termes de recherche correspondants sont éloignés de 50 termes (> à 50), le classement retourné pour le document est égal à 0.

      Par exemple, CONTAINS (column_name, 'renard NEAR poulet') et CONTAINSTABLE (table_name, column_name, 'renard ~ poulet') retournent tous les documents de la colonne spécifiée qui contiennent à la fois « renard » et « poulet ». De plus, CONTAINSTABLE retourne un classement pour chaque document en fonction de la proximité de « renard » et de « poulet ». Par exemple, si un document contient la phrase « Le renard a mangé le poulet », son classement est élevé.

      NEAR indique la distance logique entre les termes et non la distance absolue qui les sépare. Par exemple, les termes des différentes expressions ou phrases d'un paragraphe sont considérés comme plus éloignés que les termes situés dans une même expression ou phrase, indépendamment de leur proximité réelle, en supposant que leur relation soit moins étroite. De même, les termes situés dans des paragraphes différents sont considérés comme étant encore plus éloignés.

  • <weighted_term>
    Précise que les lignes retournées par la requête correspondent à une liste de mots ou d'expressions auxquels une valeur de pondération peut être affectée.

  • ISABOUT
    Spécifie le mot clé <weighted_term>.

    • WEIGHT(weight_value)
      Définit une valeur de pondération qui est un nombre compris entre 0,0 et 1,0. Chaque élément de <weighted_term> peut inclure une valeur weight_value. Le paramètre weight_value permet de modifier l'influence de diverses parties d'une requête sur la valeur de classement affectée à chaque ligne correspondant à la requête. WEIGHT n'a pas d'incidence sur les résultats des requêtes CONTAINS, mais influe sur le classement des requêtes CONTAINSTABLE.

      [!REMARQUE]

      Le séparateur de décimale est toujours un point, quels que soient les paramètres régionaux du système d'exploitation.

  • { AND | & } | { AND NOT | &! } | { OR | | }
    Spécifie une opération logique entre deux conditions de recherche de contenu.

    • AND | &
      Indique que les deux conditions de recherche contains doivent être satisfaites pour obtenir une correspondance. Le symbole et commercial (&) peut être utilisé à la place du mot clé AND pour représenter l'opérateur AND.

    • AND NOT | &!
      Indique que la deuxième condition de recherche ne doit pas être satisfaite pour obtenir une correspondance. Le symbole et commercial suivi d'un point d'exclamation (&!) peut être utilisé à la place du mot clé AND NOT pour représenter l'opérateur AND NOT.

    • OR | |
      Indique que l'une des deux conditions de recherche contains doit être satisfaite pour obtenir une correspondance. Le symbole de barre verticale (|) peut être utilisé à la place du mot clé OR pour représenter l'opérateur OR.

      Lorsque <contains_search_condition> comporte des groupes placés entre parenthèses, ces groupes sont évalués en premier. Une fois ces groupes évalués, les règles suivantes sont appliquées lorsque ces opérateurs logiques sont utilisés dans les conditions de recherche de contenu :

      • NOT est appliqué avant AND.

      • NOT peut uniquement être utilisé après AND, comme dans AND NOT. L'opérateur OR NOT n'est pas autorisé. NOT ne peut pas être spécifié avant le premier terme. Par exemple, CONTAINS (mycolumn, 'NOT "phrase_to_search_for" ' ) est incorrect.

      • AND est appliqué avant OR.

      • Les opérateurs booléens de même type (AND, OR) sont associatifs et peuvent donc être utilisés dans un ordre quelconque.

      • n
        Espace réservé indiquant que plusieurs conditions de recherche CONTAINS peuvent être spécifiées, de même que plusieurs termes dans celles-ci.

Notes

Les prédicats et les fonctions de texte intégral s'appliquent à une table unique, ce qui est implicite dans le prédicat FROM. Pour effectuer des recherches sur plusieurs tables, utilisez une table jointe dans votre clause FROM afin de baser votre recherche sur un jeu de résultats qui est le produit de deux tables ou plus.

CONTAINS n'est pas reconnu en tant que mot clé si le niveau de compatibilité est inférieur à 70. Pour plus d'informations, consultez sp_dbcmptlevel (Transact-SQL).

Les prédicats de texte intégral ne sont pas autorisés dans la clause OUTPUT lorsque le niveau de compatibilité de la base de données a la valeur 100.

Comparaison entre LIKE et la recherche en texte intégral

Contrairement à la recherche en texte intégral, le prédicat Transact-SQLLIKE fonctionne uniquement sur les modèles de caractères. En outre, vous ne pouvez pas utiliser le prédicat LIKE pour interroger des données binaires mises en forme. De plus, une requête LIKE portant sur un important volume de données de texte non structurées est beaucoup plus lente qu'une requête de texte intégral équivalente exécutée sur les mêmes données. Une requête LIKE portant sur des millions de lignes de données de texte peut prendre plusieurs minutes pour retourner un résultat alors qu'une requête de texte intégral retourne en quelques secondes à peine le même résultat, en fonction du nombre de lignes retournées.

Exemples

A. Utilisation de CONTAINS avec <simple_term>

L'exemple ci-dessous recherche tous les produits qui contiennent le mot "Mountain" et qui coûtent $80.99.

USE AdventureWorks;
GO
SELECT Name, ListPrice
FROM Production.Product
WHERE ListPrice = 80.99
   AND CONTAINS(Name, 'Mountain');
GO

B. Utilisation de CONTAINS et d'une expression dans <simple_term>

L'exemple ci-dessous retourne tous les produits qui contiennent l'expression "Mountain" ou "Road".

USE AdventureWorks;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, ' "Mountain" OR "Road" ')
GO

C. Utilisation de CONTAINS avec <prefix_term>

L'exemple ci-dessous retourne tous les noms de produits comportant au moins un mot commençant par la chaîne de préfixe dans la colonne Name.

USE AdventureWorks;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, ' "Chain*" ');
GO

D. Utilisation de CONTAINS et OR avec <prefix_term>

L'exemple ci-dessous retourne toutes les descriptions de catégorie contenant les chaînes "chain" ou "full".

USE AdventureWorks;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, '"chain*" OR "full*"');
GO

E. Utilisation de CONTAINS avec <proximity_term>

L'exemple suivant retourne tous les noms de produits contenant le mot « bike » à proximité du mot « performance ».

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE CONTAINS(Description, 'bike NEAR performance');
GO

F. Utilisation de CONTAINS avec <generation_term>

L'exemple ci-dessous recherche tous les produits comportant des formes dérivées du mot ride : riding, ridden, etc.

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE CONTAINS(Description, ' FORMSOF (INFLECTIONAL, ride) ');
GO

G. Utilisation de CONTAINS avec <weighted_term>

L'exemple ci-dessous recherche tous les noms de produits contenant les mots « performance », « comfortable » ou « smooth ». Un poids différent est affecté à chacun des mots.

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE CONTAINS(Description, 'ISABOUT (performance weight (.8), 
comfortable weight (.4), smooth weight (.2) )' );
GO

H. Utilisation de CONTAINS avec des variables

L'exemple ci-dessous utilise une variable à la place d'un terme de recherche spécifique.

USE AdventureWorks;
GO
DECLARE @SearchWord nvarchar(30)
SET @SearchWord = N'Performance'
SELECT Description 
FROM Production.ProductDescription 
WHERE CONTAINS(Description, @SearchWord);
GO

I. Utilisation de CONTAINS avec un opérateur logique (AND)

L'exemple suivant utilise la table ProductDescription de la base de données AdventureWorks. La requête utilise le prédicat CONTAINS pour rechercher les descriptions dont l'ID de description n'est pas égal à 5 et la description contient les mots « Aluminum » et « spindle ». La condition de recherche utilise l'opérateur booléen AND.

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE ProductDescriptionID <> 5 AND
   CONTAINS(Description, ' Aluminum AND spindle');
GO

J. Utilisation de CONTAINS pour vérifier une insertion de ligne

L'exemple suivant utilise CONTAINS dans le cadre d'une sous-requête SELECT. À partir de la base de données AdventureWorks, la requête obtient la valeur de tous les commentaires de la table ProductReview pour un cycle particulier. La condition de recherche utilise l'opérateur booléen AND.

USE AdventureWorks;
GO
INSERT INTO Production.ProductReview 
(ProductID, ReviewerName, EmailAddress, Rating, Comments) 
VALUES
(780, 'John Smith', 'john@fourthcoffee.com', 5, 
'The Mountain-200 Silver from AdventureWorks Cycles meets and exceeds expectations. I enjoyed the smooth ride down the roads of Redmond')
 
-- Given the full-text catalog for these tables is Adv_ft_ctlg, 
-- with change_tracking on so that the full-text indexes are updated automatically.
WAITFOR DELAY '00:00:30'   
-- Wait 30 seconds to make sure that the full-text index gets updated.
 
SELECT r.Comments, p.Name
FROM Production.ProductReview r
JOIN Production.Product p 
ON
 r.ProductID = p.ProductID
 
AND r.ProductID = (SELECT ProductID
                  FROM Production.ProductReview
                  WHERE CONTAINS (Comments, 
                                 ' AdventureWorks AND 
                                   Redmond AND 
                                   "Mountain-200 Silver" '))

GO