存储过程 将希伯来字符插入 NVARCHAR 列,但 SELECT 显示“?”
Stored procedure Inserts Hebrew characters into an NVARCHAR column, but SELECT shows "?"
当我从tableSELECT
时,我存储的数据存储为问号。
@word
是我存储过程中的一个参数,取值来自C#代码:
string word = this.Request.Form["word"].ToString();
cmd.Parameters.Add("@word", System.Data.SqlDbType.NVarChar).Value = word;
我的存储过程是这样的:
CREATE PROCEDURE ....
(
@word nvarchar(500)
...
)
Insert into rub_translate (language_id,name)
values (8 ,@word COLLATE HEBREW_CI_AS )
我的数据库和列正在使用 SQL_Latin1_General_CP1_CI_AS
排序规则,我无法更改它们。
任何人都可以给我一个解决方案我怎样才能通过修改列或 table 来解决这个问题?
您可以按原样插入,因为它是 unicode,然后 select it with a proper collation:
declare @test table([name] nvarchar(500) collate Latin1_General_CI_AS);
declare @word nvarchar(500) = N'זה טקסט.';
insert into @test ( [name] ) values ( @word );
select [t].[name] collate Hebrew_CI_AS from @test as [t]
或者您可以 change the collation of that one column 在 table 中全部在一起。但是请记住,在一个或多个列中使用与数据库不同的排序规则有一个缺点:当您需要比较不同排序规则之间的数据时,您需要将 collate 语句添加到查询中。
为了使其正常工作,您需要执行以下操作:
在app代码中声明入参为NVARCHAR
(你已经做到了)
在存储过程中声明入参为NVARCHAR
(此处不显示代码)
插入或更新 table 中定义为 NVARCHAR
的列(您声称是这种情况)
使用 NVARCHAR
时,数据库的默认排序规则是什么并不重要。实际上,当使用 NVARCHAR
时,table 中列的排序规则是什么并不重要,至少对于正确插入字符而言是这样。
此外,在 INSERT
语句中指定 COLLATE
关键字是不必要的,无论如何也无济于事。如果将存储过程输入参数定义为 VARCHAR
,则字符在进入存储过程时已转换为 ?
。如果该列实际上定义为 VARCHAR
(您没有提供 table 的 DDL),那么如果 Collation 不是 Hebrew_*
那么您无能为力(除了将数据类型更改为 NVARCHAR
或将排序规则更改为 Hebrew_
。
如果顶部列出的那三项确实存在,那么最后要检查的是输入值本身。由于这是一个网络应用程序,因此可能页面本身的编码设置不正确。您需要在 cmd.Parameters.Add("@word", System.Data.SqlDbType.NVarChar).Value = word;
行设置一个断点并确认 word
变量中保存的值包含希伯来字符而不是 ?
s.
另外: 你不应该在没有指定最大值 length/size 的情况下创建字符串参数。默认值为 30(在本例中,有时为 1),但存储过程中的参数定义为 NVARCHAR(500)
。这可能会导致静默截断("silent" 意味着它不会导致错误,它只会截断值)。相反,您应该始终指定大小。例如:
cmd.Parameters.Add("@word", System.Data.SqlDbType.NVarChar, 500).Value = word;
当我从tableSELECT
时,我存储的数据存储为问号。
@word
是我存储过程中的一个参数,取值来自C#代码:
string word = this.Request.Form["word"].ToString();
cmd.Parameters.Add("@word", System.Data.SqlDbType.NVarChar).Value = word;
我的存储过程是这样的:
CREATE PROCEDURE ....
(
@word nvarchar(500)
...
)
Insert into rub_translate (language_id,name)
values (8 ,@word COLLATE HEBREW_CI_AS )
我的数据库和列正在使用 SQL_Latin1_General_CP1_CI_AS
排序规则,我无法更改它们。
任何人都可以给我一个解决方案我怎样才能通过修改列或 table 来解决这个问题?
您可以按原样插入,因为它是 unicode,然后 select it with a proper collation:
declare @test table([name] nvarchar(500) collate Latin1_General_CI_AS);
declare @word nvarchar(500) = N'זה טקסט.';
insert into @test ( [name] ) values ( @word );
select [t].[name] collate Hebrew_CI_AS from @test as [t]
或者您可以 change the collation of that one column 在 table 中全部在一起。但是请记住,在一个或多个列中使用与数据库不同的排序规则有一个缺点:当您需要比较不同排序规则之间的数据时,您需要将 collate 语句添加到查询中。
为了使其正常工作,您需要执行以下操作:
在app代码中声明入参为
NVARCHAR
(你已经做到了)在存储过程中声明入参为
NVARCHAR
(此处不显示代码)插入或更新 table 中定义为
NVARCHAR
的列(您声称是这种情况)
使用 NVARCHAR
时,数据库的默认排序规则是什么并不重要。实际上,当使用 NVARCHAR
时,table 中列的排序规则是什么并不重要,至少对于正确插入字符而言是这样。
此外,在 INSERT
语句中指定 COLLATE
关键字是不必要的,无论如何也无济于事。如果将存储过程输入参数定义为 VARCHAR
,则字符在进入存储过程时已转换为 ?
。如果该列实际上定义为 VARCHAR
(您没有提供 table 的 DDL),那么如果 Collation 不是 Hebrew_*
那么您无能为力(除了将数据类型更改为 NVARCHAR
或将排序规则更改为 Hebrew_
。
如果顶部列出的那三项确实存在,那么最后要检查的是输入值本身。由于这是一个网络应用程序,因此可能页面本身的编码设置不正确。您需要在 cmd.Parameters.Add("@word", System.Data.SqlDbType.NVarChar).Value = word;
行设置一个断点并确认 word
变量中保存的值包含希伯来字符而不是 ?
s.
另外: 你不应该在没有指定最大值 length/size 的情况下创建字符串参数。默认值为 30(在本例中,有时为 1),但存储过程中的参数定义为 NVARCHAR(500)
。这可能会导致静默截断("silent" 意味着它不会导致错误,它只会截断值)。相反,您应该始终指定大小。例如:
cmd.Parameters.Add("@word", System.Data.SqlDbType.NVarChar, 500).Value = word;