1
votes

Appliquer comme une fonction sur un tableau est SQL Server

Je reçois un tableau du front-end pour effectuer des filtres en fonction de cela à l'intérieur de la requête SQL.

Je veux appliquer un filtre LIKE sur le tableau. Comment ajouter un tableau dans la fonction LIKE ?

J'utilise Angular avec Html comme frontal et Node comme back-end.

Tableau transmis depuis le frontal:

SELECT *
FROM Skills
WHERE Description LIKE ('%Sports%')

SELECT *
FROM Skills
WHERE Description LIKE ('%Life%')

SELECT *
FROM Skills
WHERE Description LIKE ('%Relationship%')

La requête SQL est:

 [ "Sports", "Life", "Relationship", ...]

Mais j'obtiens un tableau du front-end - comment créer une requête pour cela?


5 commentaires

Passez un paramètre de table. docs.microsoft.com/en-us/sql/relational-databases/tables/... Cela devient alors trivial.


Quel langage de programmation utilisez-vous sur le backend. Je suis sûr que vous en utilisez un.


@SalmanA J'utilise Node JS comme backend.


Vous pouvez analyser le JSON dans Node et générer une requête qui utilise des paires de valeurs de table. Si vous utilisez SQL 2016+, il existe également une option plus simple.


Sachez également que puisque vous utilisez des caractères génériques de premier plan, vous avez rendu votre requête nonSARGable et tous les index sont infructueux dans la colonne Description.


3 Réponses :


0
votes

À titre d'exemple, pour SQL Server 2016+ et STRING_SPLIT():

 Select * from Skills 
 WHERE (
     Description Like '%Sports%' 
 OR  Description Like '%Life%' 
 OR  Description Like '%Life%' 
     )

Il convient de mentionner que les données d'entrée doivent être strictement contrôlées, car une telle méthode peut mener à une attaque par injection SQL

En tant qu'approche alternative, plus sûre et plus simple: SQL peut être généré côté application de cette façon:

DECLARE @Str NVARCHAR(100) = N'mast;mode'

SELECT name FROM sys.databases sd
INNER JOIN STRING_SPLIT(@Str, N';') val ON sd.name LIKE N'%' + val.value + N'%'

-- returns:

name
------
master
model


5 commentaires

STRING_SPLIT est un objet invalide dans mon cas. J'utilise SQL Server 2017


@AmandeepSingh, le niveau de compatibilité d'une base de données défini sur SQL 2014 ou inférieur, il doit être défini sur au moins SQL2016


pouvons-nous utiliser STRING_SPLIT sans jointure?


@AmandeepSingh, pas avec l'instruction LIKE . Veuillez noter que j'ai ajouté une approche alternative, qui n'utilise aucune jointure, peut-être que cela peut être une meilleure alternative pour votre cas


Pourquoi voulez-vous éviter d'utiliser une jointure? Vous pouvez le faire sans jointure, mais cela devient beaucoup plus ridicule.



1
votes

Dans SQL Server 2017, vous pouvez utiliser OPENJSON pour consommer la chaîne JSON telle quelle:

SELECT *
FROM skills
WHERE EXISTS (
    SELECT 1
    FROM OPENJSON('["Sports", "Life", "Relationship"]', '$') AS j
    WHERE skills.description LIKE '%' + j.value + '%'
)

Démo sur db fiddle


3 commentaires

Je fais aussi comme ça. Mais le problème est que le tableau provenant du front-end est ["Sports", "Life"] et l'erreur de SQL est que le texte JSON n'est pas correctement formaté. Le caractère inattendu '' 'est trouvé à la position 1.' ''


Vous passez évidemment des json invalides. Peut-être avez-vous des citations supplémentaires.


C'est impossible à dire. Mais peut-être que si vous utilisez des paramètres, vous feriez ... FROM OPENJSON (@ p1, '$') AS ... et la valeur de @ p1 serait < code> JSON.stringify (that_array)



0
votes

Un simple appel map () sur le tableau words vous permettra de générer les requêtes correspondantes, que vous pourrez ensuite exécuter (avec ou sans les joindre d'abord dans une seule chaîne).

Démo:

var words = ["Sports", "Life", "Relationship"];
var template = "Select * From Skills Where Description Like ('%{0}%')";

var queries = words.map(word => template.replace('{0}', word));
var combinedQuery = queries.join("\r\n");

console.log(queries);
console.log(combinedQuery);


2 commentaires

Vous devez ajouter plusieurs mots en utilisant ou , c'est-à-dire que la requête ressemblerait à WHERE col comme '% life%' ou col comme '% sports%' etc.


Telle est votre hypothèse, OP ne le mentionne pas du tout.