1
votes

L'opérateur LIKE, N et% SQL Server ne fonctionnent pas sur la colonne nvarchar

Existe-t-il un moyen de faire fonctionner la requête suivante?

  ALTER PROCEDURE [dbo].[aTest]
  (@t  nvarchar(20))
  AS
    BEGIN

     SELECT     [perno] ,[pName]
       FROM     [dbo].[People]
       WHERE   ([People].[pName] LIKE N'' +@t + '%')
END   

Je ne peux pas utiliser comme ça:

 Where [pName] like N'حس%'

Ou utiliser un procédure stockée:

declare @t nvarchar(20)
set @t='حس'
SELECT  [perno] ,[pName]
  FROM  [dbo].[People]
  Where [pName] like N''+@t +'%'


7 commentaires

Pourquoi avez-vous besoin de N ' puisque votre variable est déjà nvarchar?


N ' fait partie de la syntaxe string literal . Cela change le type de littéral de chaîne que vous écrivez. Il n'applique pas comme par magie les modifications aux chaînes obtenues par calcul ou à des valeurs attribuées à partir de littéraux complètement différents.


deux mots, attaque par injection . Imaginez que le nom que vous recherchez est N'haha ''); GO TRUNCATE [dbo]. [People]; - '


@Jodrell Où est l'opportunité d'injection SQL? Il n'y a pas de SQL dynamique présent, juste une concaténation de chaînes pour créer un modèle pour comme .


@HABO, vous avez peut-être raison, je devrais l'essayer mais, le SQL dynamique est là LIKE N '' + @ t + '%'


@Jodrell La concaténation de chaînes n'est pas du SQL dynamique. Dynamic SQL utilise exécuter ou sp_executesql pour exécuter une chaîne arbitraire contenant des instructions SQL. (Ou une méthode externe comme ExecuteSqlCommand .)


@HABO, bonne référence ici sommarskog.se/dynamic_sql.html , mais avant de le lire, je Je pense que vous êtes probablement en sécurité, mais je vérifierais toujours.


3 Réponses :


5
votes

Vous n'avez pas besoin d'utiliser le préfixe N dans la clause WHERE car votre variable est déjà nvarchar et vous passez une variable pas une chaîne littérale .

Voici un exemple:

EXEC MyProc N'حس'; --If you don't use N prefix then you are pass a varchar string

Démo en direct

Vous avez peut-être vu du code Transact-SQL qui passe des chaînes en utilisant un préfixe N. Cela indique que la chaîne suivante est en Unicode (le N signifie en fait le jeu de caractères de la langue nationale). Ce qui signifie que vous transmettez une valeur NCHAR, NVARCHAR ou NTEXT, par opposition à CHAR, VARCHAR ou TEXT.

Depuis docs

Préfixe les constantes de chaîne de caractères Unicode avec la lettre N. Sans le préfixe N, la chaîne est convertie en page de codes par défaut de la base de données. Cette page de codes par défaut peut ne pas reconnaître certains caractères.


Pour répondre à votre question dans le commentaire avec une réponse simple, vous utilisez le mauvais type de données, donc ALTER la procédure stockée et changez le type de données de votre paramètre de VARCHAR à NVARCHAR.


UPDATE:

Puisque vous utilisez un SP, vous pouvez créer votre SP (selon votre comment ) comme

CREATE PROCEDURE MyProc
(
  @Var NVARCHAR(45)
)
AS 
BEGIN
  SELECT *
  FROM People
  WHERE Name LIKE ISNULL(@Var, Name) + '%';
  --Using ISNULL() will return all rows if you pass NULL to the stored procedure
END

et appelez-le comme

CREATE TABLE People
(
  ID INT,
  Name NVARCHAR(45)
);

INSERT INTO People VALUES
(1, N'حسام'),
(2, N'حسان'),
(3, N'حليم');

DECLARE @Name NVARCHAR(45) = N'حس';--You need to use N prefix when you pass the string literal

SELECT *
FROM People
WHERE Name LIKE @Name + '%'; --You can use it here when you pass string literal, but since you are passing a variable, you don't need N here

Si vous voyez, vous avez besoin pour utiliser le préfixe N lorsque vous passez une chaîne littérale à votre SP pas à l'intérieur du SP ou la clause WHERE non plus.

Démo pour le SP


4 commentaires

correct je n'ai pas besoin de N Lors de la déclaration de variable mais lors de l'utilisation d'une procédure stockée avec paramètre?


@jaleel Alors pourquoi déclarez-vous votre variable avec le mauvais type de données?


mauvais type de données? Je vois que vous utilisez N, je pense que c'est le bon endroit mais j'ai toujours un problème sur la procédure stockée


@jaleel Je pense avoir répondu à cela dans la première citation, si vous n'utilisez pas N alors SQL Server ne traitera pas la chaîne comme non-unicode Sans le préfixe N, le string est converti en page de codes par défaut de la base de données . De plus, je ne vois pas de procédure stockée dans votre question, donc si tel est le cas, veuillez modifier votre question



1
votes

dans ces lignes

set @t=N'حس'

le 'Øس' est une constante varchar que vous attribuez ensuite à une variable nvarchar. Mais vous avez déjà perdu des données avec la conversion d'origine en cette constante varchar et vous ne pouvez pas les récupérer.

La solution consiste à utiliser une constante nvarchar :

declare @t nvarchar(20)
set @t='حس'


0 commentaires

1
votes

Cela pourrait être beaucoup plus simple:

Essayez ceci

set @t=N'حس'; --<-- N-prefix

Vous déclarez correctement la variable comme NVARCHAR . Mais le littéral ne connaît pas sa cible. Sans le N , il est considéré comme un VARCHAR avec le classement par défaut.

La ligne suivante

Where [pName] like N''+@t +'%'

recherchera un pName LIKE '??%' .

La solution devrait être

declare @t nvarchar(20)
set @t='حس';

SELECT @t; --the result is "??"


0 commentaires