将西里尔字符传递到存储过程不适用于Sql Server

时间:2013-06-04 12:24:35

标签: sql sql-server tsql stored-procedures

我有存储过程

if OBJECT_ID(N'dbo.spGetProducts') is not null
drop procedure dbo.spGetProducts
go

CREATE procedure [dbo].[spGetProducts]
(
 @sort_col varchar(100), @sort_dir varchar(4),
 @start int, @num int, @filters nvarchar(2000)) as
 begin
 declare @end int
 declare    
  @res table 
  (
   row_num int,
   product_name nvarchar(max)
  )
set @end = @start+@num
insert into @res
EXEC
(
 'select * from 
  (
   select (ROW_NUMBER() OVER (ORDER BY '+@sort_col+' '+@sort_dir+')) row_num,
   * FROM (select product_name from Products where '+@filters+') as x
  ) as tmp where row_num between '+@start+' and '+@end
) select row_num, product_name from @res
 end 
go

当我执行存储过程时latin characters完美无缺,但当我使用cyrillic个字符does not return anything时..

这是执行行:

  1. 拉丁字符 - 工作:

    exec dbo.spGetProducts 'product_name','desc',0,50,' 
    product_name like N''%abs%'''
    
  2. 西里尔文字符 - 不用担心:

    exec dbo.spGetProducts 'product_name','desc',0,50,' 
    product_name like N''%абв%'''
    
  3. 我还手动设置存储过程以使用

    'product_name like N''%абв%'''
    

    进入行

    select product_name from Products where '+@filters+'
    

     select product_name from Products where product_name like N''%абв%'''
    

    这个工作,所以我不知道如何解决这个问题。

2 个答案:

答案 0 :(得分:3)

关于西里尔内部参数的问题,你只需要在发送它时在整个过滤器参数前加上另一个N

exec dbo.spGetProducts 'product_name','desc',0,50, N'product_name like N''%абв%'''
                                                   ^
                                                   ^
                                                  here

但请阅读我对安全问题的评论并重新考虑更改您的设计。

<强> SQLFiddle Demo

编辑 - 一点解释:如果你没有指定你的输入参数是NVARCHAR,那么它将被隐式声明为VARCHAR,你的西里尔文абв会丢失,并在它们出现之前被???替换得传递给程序。

如果要从C#或VB传递参数,则声明它们DBType.NVarChar应足以避免此问题。

答案 1 :(得分:0)

我并不感到惊讶。您应该使用参数而不是连接SQL。

但是,由于您使用的是动态SQL,因此似乎需要重新编写整个过程。

阅读here,它会帮助你。