【问题标题】:Unicode in storedProcedure parameters存储过程参数中的 Unicode
【发布时间】:2016-10-24 02:25:32
【问题描述】:

我有一个名为 City 的表,这个模式:

CREATE TABLE [dbo].[City](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [CreatedDate] [datetime] NOT NULL,
    [CreatedBy] [nvarchar](256) NULL,
    [UpdatedDate] [datetime] NOT NULL,
    [UpdatedBy] [nvarchar](256) NULL,
    [SoftDelete] [bit] NOT NULL,
    [LanguageKey] [nvarchar](2) NOT NULL DEFAULT (''),
    [ProvinceName] [nvarchar](50) NULL DEFAULT (''),
    [CityImageId] [bigint] NULL,
    [CityDescription] [nvarchar](500) NOT NULL DEFAULT (''),
    [CityLinkTo] [nvarchar](100) NOT NULL DEFAULT (''),
    [CityCode] [nvarchar](100) NOT NULL DEFAULT (''),
 CONSTRAINT [PK_dbo.City] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[City]  WITH CHECK ADD  CONSTRAINT [FK_dbo.City_dbo.Image_CityImageId] FOREIGN KEY([CityImageId])
REFERENCES [dbo].[Image] ([Id])
GO

ALTER TABLE [dbo].[City] CHECK CONSTRAINT [FK_dbo.City_dbo.Image_CityImageId]
GO

并且有一个带有此代码的存储过程:

ALTER Proc [dbo].[InventoryReport]  
(
 @startDate datetime , 
 @endDate datetime ,
 @cityName nvarchar(50)
)
AS
Begin 

Select Id , Name , AllPlace , InventoryPlace , case when Percentage is null then Convert(nvarchar(5),0) else Convert(nvarchar(5) ,Percentage )End AS Percentage
    From (
            Select c.id , c.Name  Name, count(p.id) AllPlace , count(inventoryPlace.InventoryId) InventoryPlace ,
                        ROUND( Convert(float , NULLIF(count(inventoryPlace.InventoryId), 0)  )/ Convert(float,NULLIF(count(p.id), 0)  ),2,null) Percentage
                        from Place  p
                    left join (
                            Select id InventoryId , name  from (
                            Select ROW_NUMBER() Over(Partition by  id , name  Order by  id , date) rn,
                                    * from (
                                    Select  
                                             p.id , p.name , i.date
                                             from Place  p  
                                                left join Room r    on  p.id = r.placeid            and p.SoftDelete = 0    and r.SoftDelete = 0 
                                                join RoomService rs on  r.id = rs.roomid            and rs.SoftDelete = 0 
                                                join inventory  i   on  rs.id = i.roomServiceId     and i.SoftDelete = 0    
                                                                        AND i.date >= @startDate  and i.date <@endDate  and Price <>0 
                                    Group By  p.id , p.name , i.Date 
                                    )a 
                            )r 
                            where r.rn =  DATEDIFF(day , @startDate , @endDate) 
                        )inventoryPlace
                            on p.Id = inventoryPlace.InventoryId
                        right join City c           
                            on  c.id = p.CityId and c.SoftDelete = 0 
                        Where 
                            (@cityName is null OR @cityName = N'' OR c.Name = @cityName) and  p.SoftDelete = 0   and IsVisible = 1
                        Group By c.id , c.name

            ) As PlaceInventoryReport
Order by Id
END

城市表中的名称字段为Nvarchar(50)@cityNamenvarchar(50)。我执行以下代码:

exec InventoryReport @startDate='2016-07-22 00:00:00',@endDate='2016-08-21 00:00:00',@cityName =N'بیرجند'


exec InventoryReport @startDate='2016-07-22 00:00:00',@endDate='2016-08-21 00:00:00',@cityName ='بیرجند' 

第一次执行由 Sql Profiler 生成并从应用程序调用,然后没有结果(这是错误的),第二次由我自己方便地调用并产生一条记录。区别是N'

这两个值“بیرجند”在字符上是相同的,我已经从原处复制了它们。 我不知道出了什么问题,为什么这两个执行语句的结果不同?

提前致谢。

【问题讨论】:

  • N-prefix 告诉 sql server 将字符串视为 unicode 值。而如果不提及相同的内容,它将被视为字符串。更多信息在这里:support.microsoft.com/en-us/kb/239530跨度>
  • @Malcolm 当我们将列的数据类型定义为 NVARCHAR 时,它会将值存储为 UNICODE 格式还是字符串?如果它存储为字符串,那么为什么我们不应该使用 8000 字符长度的 varchar?如果它以 UICODE 格式存储,为什么值不匹配?
  • @samira 您是否对列的语言使用了准确的排序规则..?
  • @RajeshRanjan 是的,我使用了排序,但它也不起作用。
  • @samira 你能分享一下表格脚本和一些示例记录吗?

标签: sql-server stored-procedures unicode parameters parameter-passing


【解决方案1】:

它将字符串声明为 nvarchar 数据类型,而不是 varchar

  1. 您可能已经看到 Transact-SQL 代码使用传递字符串 一个 N 前缀。这表示后面的字符串是 Unicode (N 实际上代表国家语言字符集)。哪一个 表示您正在传递 NCHAR、NVARCHAR 或 NTEXT 值,如 与 CHAR、VARCHAR 或 TEXT 相对。

    引用Microsoft

  2. 在 Unicode 字符串常量前加上字母 N。 N前缀,字符串转换为默认代码页 数据库。此默认代码页可能无法识别某些 字符。

【讨论】:

  • 谢谢,但正如我所写,我已将列和参数声明为 Nvarchar(50)。
  • @samirariazati 是的,您已将参数声明为 NVARCHAR(50),但您为其分配了非 unicode 值。那是行不通的。为了让它工作,一切都应该是 unicode。
  • 但是我尝试使用您提到的相同代码,我得到了正确的结果,但在您的情况下,您的表架构可能存在问题,请您分享您的表脚本。
  • @NazirUllah 我已经编辑了问题并添加了架构。
  • 您的脚本和 sp 被视为正确检查您是否正在尝试使用重复或其他表格数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
相关资源
最近更新 更多