我正在尝试将德语 ß 存储在 SQL Server 中,但结果为 ß。例如,“Gleimstraße”存储为“Gleimstraße”
但这也发生在其他角色身上:
- “König-Karl-Straße”存储为“König-Karl-Straße”
- “Quai André-Citroën”存储为“Quai André Citroën”
- "Carrer dels Adreçadors 存储为 "Carrer dels Adreçadors"
我查看了数据库排序规则,它显示SQL_Latin1_General_CP1_CI_AS
. 然后我用谷歌搜索并找到了这个。
但我不知道我现有的排序规则是否会导致问题,或者我需要做什么才能存储特殊字符,如 ö、ß、é、ë、ç、ñ、í。
更新 1
实际上,我将字符串存储在一nvarchar
列中。我通过我的 .NET 应用程序将数据发送到数据库。这就是我在 web.config 中作为连接字符串的内容:
<add name="conn" connectionString="data source=(local)\sql;Initial Catalog=mydb;User Id=myuser;Password=mypassword;" providerName="System.Data.SqlClient"/>
更新 2
我从传递给 a 的 JSON 文件中读取值Newtonsoft.Json.Linq.JArray
,然后将其传递给函数,如下所示:
InsertStreetId(item.SelectToken("location.street").Value(Of String))
Public Shared Function InsertStreetId(ByVal street As String) As Integer
Dim streetId As Integer
Dim myConnection As SqlConnection = GetConnection()
Dim cmd As New SqlCommand("INSERT INTO geo_streets(streetname) VALUES (@streetname)" +
";SELECT CAST(scope_identity() as int);", myConnection)
cmd.Parameters.Add(New SqlParameter("@streetname", street))
Try
myConnection.Open()
streetId = CInt(cmd.ExecuteScalar)
Catch ex As Exception
Finally
myConnection.Close()
End Try
Return streetId
End Function
更新 3
好的,这就是我所做的:
Dim myConnection As SqlClient.SqlConnection = GetConnection()
Dim cmd As New SqlClient.SqlCommand("UPDATE cities SET name=@name,updatedate=getdate() WHERE geonameid=@geonameid", myConnection)
cmd.Parameters.Add(New SqlClient.SqlParameter("@name", "Kąty Wrocławskie"))
cmd.Parameters.Add(New SqlClient.SqlParameter("@geonameid", 6474))
myConnection.Open()
cmd.ExecuteNonQuery
myConnection.Close()
这会正确地将字符串“Kąty Wrocławskie”插入到我的数据库中。所以我猜数据库排序规则工作正常以支持特殊字符?
如果是这样,我现在可能有另一个问题,但请让我知道是否最好创建一个新问题:如前所述,新插入的记录工作正常。但是,在我的数据库中,我仍然有如下值:“SÄpĂłno KrajeĹskie”(应该是“Sępólno Krajeńskie”)。
我现在应该对所有列进行查找/替换吗?如果是这样,我在哪里可以找到一个映射表来知道要查找什么以及替换什么,因为我不知道从哪里开始。
不知何故,数据以 UTF-8 字节的形式发送。因为您的数据库排序规则是
SQL_Latin1_General_CP1_CI_AS
,所以它使用代码页 1252 (Latin1) 获取VARCHAR
数据。该ß
字符被编码为字节C3 9F。在代码页 1252 中,这两个字节等同于以下字符:Ã和Ÿ。您可以通过在 SSMS 或 Visual Studio Code 等中执行以下命令来亲自查看:
解决此问题的一种选择是使用 UTF-8 排序规则(即以 结尾
_UTF8
)作为数据库默认排序规则,因为您使用的是 SQL Server 2019,所以您可以这样做。如果您不能或根本不想将数据库默认排序规则更改为
_UTF8
排序规则,那么您将需要找到一种方法来更改连接的编码/文化/区域设置/排序规则以匹配您的数据库代码页(即Windows 1252)。幸运的是,代码页 1252 确实存储了这些字符(即ö、ß、é、ë、ç、ñ、í),但如果您需要存储更大范围的字符,您可能需要切换到 UTF-8 排序规则(如果坚持使用VARCHAR
数据),或者切换到使用列/数据(在这种情况下,您需要在应用程序中NVARCHAR
为字符串文字加上大写前缀N
,和/或指定NVARCHAR
VARCHAR
参数的数据类型,取决于数据的发送方式)。这两个选项都是 Unicode,可以处理所有字符。如果切换到NVARCHAR
数据和列(这可能是一个更大的变化),数据库连接软件应该假定编码为 UTF-16 Little Endian,而无需您指定。问题的更新 2指出了两个可能的嫌疑人:
和:
让我们从第二项开始,因为它是一个问题,即使它不是这个特定问题的根源。
您正在使用以下构造函数
SqlParameter
:SqlParameter(String, Object)(我猜这与臭名昭著的SqlParameterCollection.AddWithValue(String, Object)方法相同)。这里的问题是数据类型是从值中推断出来的,有时在尝试猜测数据类型时会出错。明确指定数据类型总是更好。你知道数据类型。因此,请改用以下内容(如果不是 500,请务必调整参数的大小以匹配实际列):您应该首先进行更改以查看它是否解决了问题(然后修复所有创建参数而不显式设置数据类型的代码)。虽然在任何一种情况下都会有所改进,但我怀疑它实际上并不能解决问题。我认为它必须推断出 XML 的类型才能转换为 UTF-8 编码,而且我不相信只有一个名称而值中没有实际的 XML 会发生这种情况。
另一个有趣的项目是通过 Json.NET 从文件中读取数据。如果您需要显式设置输出编码,我不会感到惊讶,否则它默认为 UTF-8。似乎文件被正确读取,因为ß确实编码为 UTF-8 作为字节C3 9F。
因此,如果修复
SqlParameter
创建方式不能解决问题,那么您需要考虑设置 JSON 的编码。我强烈建议您将进入
InsertStreetId
方法的值的字节保存到文件中以进行调试,使用如下内容:我怀疑你会看到一个值,例如:
4700 6C00 6500 6900 6D00 7300 7400 7200 6100 C300 7801 6500
这是
N'Gleimstraße'
. 如果是这种情况,那么问题是在InsertStreetId
调用方法之前发生的,这意味着这与 SQL Server 无关。