Flo*_*Flo 4 collation character-set utf-8 json sql-server-2019
我试图将德语 \xc3\x9f 存储在 SQL Server 中,但结果是 \xc3\x83\xc5\xb8。\n例如“Gleimstra\xc3\x9fe”存储为“Gleimstra\xc3\x83\” xc5\xb8e"
\n但其他角色也会发生这种情况:
\n我查看了数据库排序规则,它显示SQL_Latin1_General_CP1_CI_AS
。然后我用谷歌搜索并找到了这个。
但我不知道我现有的排序规则是否导致了问题,或者我需要做什么才能存储 \xc3\xb6、\xc3\x9f、\xc3\xa9、\xc3\xab、\ 等特殊字符xc3\xa7、\xc3\xb1、\xc3\xad。
\n更新1
\n事实上,我将字符串存储在一nvarchar
列中。我通过 .NET 应用程序将数据发送到数据库。这是我在 web.config 中作为连接字符串的内容:
\n<add name="conn" connectionString="data source=(local)\\sql;Initial Catalog=mydb;User Id=myuser;Password=mypassword;" providerName="System.Data.SqlClient"/>
更新2
\n我从 JSON 文件中读取值,并将其传递给 a Newtonsoft.Json.Linq.JArray
,然后将其传递给函数,如下所示:
InsertStreetId(item.SelectToken("location.street").Value(Of String))\n\n\n Public Shared Function InsertStreetId(ByVal street As String) As Integer\n Dim streetId As Integer\n\n Dim myConnection As SqlConnection = GetConnection()\n Dim cmd As New SqlCommand("INSERT INTO geo_streets(streetname) VALUES (@streetname)" +\n ";SELECT CAST(scope_identity() as int);", myConnection)\n cmd.Parameters.Add(New SqlParameter("@streetname", street))\n\n Try\n myConnection.Open()\n streetId = CInt(cmd.ExecuteScalar)\n Catch ex As Exception\n Finally\n myConnection.Close()\n End Try\n Return streetId\n End Function\n
Run Code Online (Sandbox Code Playgroud)\n更新3
\n好的,这就是我所做的:
\nDim myConnection As SqlClient.SqlConnection = GetConnection()\n\nDim cmd As New SqlClient.SqlCommand("UPDATE cities SET name=@name,updatedate=getdate() WHERE geonameid=@geonameid", myConnection)\ncmd.Parameters.Add(New SqlClient.SqlParameter("@name", "K\xc4\x85ty Wroc\xc5\x82awskie"))\ncmd.Parameters.Add(New SqlClient.SqlParameter("@geonameid", 6474))\n\nmyConnection.Open()\ncmd.ExecuteNonQuery\nmyConnection.Close()\n
Run Code Online (Sandbox Code Playgroud)\n这会将字符串“K\xc4\x85ty Wroc\xc5\x82awskie”正确插入到我的数据库中。所以我猜数据库排序规则工作正常以支持特殊字符?
\n如果是这样,我现在可能遇到另一个问题,但请告诉我是否最好就此创建一个新问题:\n如上所述,新插入的记录工作正常。但是,在我的数据库中,我仍然有如下值:“S\xc3\x84p\xc4\x82\xc5\x82lno Kraje\xc4\xb9skie”(应该是“S\xc4\x99p\xc3\xb3lno Kraje\xc5\x84skie”) ”)。
\n我现在应该对所有列进行查找/替换吗?如果是这样,我在哪里可以找到映射表来知道要查找什么以及用什么替换,因为我不知道从哪里开始。
不知何故,数据以 UTF-8 字节的形式发送。由于您的数据库排序规则为SQL_Latin1_General_CP1_CI_AS
,因此使用代码页 1252 (Latin1) 来存储VARCHAR
数据。该\xc3\x9f
字符被编码为字节C3 9F。在代码页 1252 中,这两个字节相当于以下字符:\xc3\x83和\xc5\xb8。
您可以通过在 SSMS 或 Visual Studio Code 等中执行以下命令来亲自查看这一点:
\nSELECT CHAR(0xC3) + CHAR(0x9F);\n
Run Code Online (Sandbox Code Playgroud)\n解决此问题的一种选择是使用 UTF-8 排序规则(即以 结尾的排序规则_UTF8
)作为数据库默认排序规则,因为您使用的是 SQL Server 2019,所以您可以这样做。
如果您不能或根本不想将数据库默认排序规则更改为排序规则_UTF8
,那么您将需要找到一种方法来更改连接的编码/区域性/区域设置/排序规则以匹配您的数据库代码页(即Windows 1252)。幸运的是,代码页 1252 确实存储了这些字符(即\xc3\xb6、\xc3\x9f、\xc3\xa9、\xc3\xab、\xc3\xa7、\xc3\xb1、\xc3\xad),但如果您需要要存储更大范围的字符,您可能需要切换到 UTF-8 排序规则(如果坚持使用VARCHAR
数据),或者切换到使用NVARCHAR
列/数据(在这种情况下,您需要在应用程序中为字符串文字添加前缀,使用大写的N
,和/或指定参数的数据类型NVARCHAR
而不是VARCHAR
数据类型,具体取决于数据的发送方式)。这两个选项都是 Unicode,可以处理所有字符。如果切换到NVARCHAR
数据和列(这可能是一个更大的更改),数据库连接软件应假定编码为 UTF-16 Little Endian,而无需您指定。
问题的更新 2指出了两个可能的嫌疑人:
\n\n\n我从 JSON 文件中读取值,并将其传递到 Newtonsoft.Json.Linq.JArray 中
\n
和:
\n\n\n然后将其传递给一个函数:
\nRun Code Online (Sandbox Code Playgroud)\ncmd.Parameters.Add(New SqlParameter("@streetname", street))\n
让我们从第二项开始,因为它是一个问题,即使它不是这个特定问题的根源。
\n您正在使用以下构造函数SqlParameter
:SqlParameter(String, Object) (我猜它与臭名昭著的SqlParameterCollection.AddWithValue(String, Object)方法相同)。这里的问题是数据类型是从值推断出来的,有时在尝试猜测数据类型时可能会出错。明确指定数据类型总是更好。而且您知道数据类型。因此,请使用以下内容(如果不是 500,请务必调整参数的大小以匹配实际列):
Dim param as New SqlParameter("@streetname", SqlDbType.NVarChar, 500)\nparam.Value = street\ncmd.Parameters.Add(param)\n
Run Code Online (Sandbox Code Playgroud)\n您应该首先进行更改,看看它是否解决了问题(然后修复在未显式设置数据类型的情况下创建参数的所有代码)。虽然这在任何一种情况下都会有所改进,但我怀疑它并不能真正解决问题。我认为它必须推断类型是 XML 才能转换为 UTF-8 编码,并且我不相信只有名称而值中没有实际 XML 的情况会发生这种情况。
\n另一个有趣的项目是通过 Json.NET 从文件中读取数据。如果您需要显式设置输出编码,否则它默认为 UTF-8,我不会感到惊讶。看来文件被正确读取,因为\xc3\x9f确实编码为 UTF-8 作为字节C3 9F。
\n因此,如果修复创建方式SqlParameter
无法解决问题,那么您需要考虑设置 JSON 的编码。
我强烈建议您将进入方法的值的字节保存InsertStreetId
到文件中以进行调试,使用类似以下内容:
BitConverter.ToString( BitConverter.GetBytes( street ) )\n
Run Code Online (Sandbox Code Playgroud)\n我怀疑您会看到如下值:
\n4700 6C00 6500 6900 6D00 7300 7400 7200 6100 C300 7801 6500
这是 的 UTF-16 LE 表示形式N\'Gleimstra\xc3\x83\xc5\xb8e\'
。如果是这种情况,则问题发生在InsertStreetId
调用该方法之前,这意味着这与 SQL Server 无关。
归档时间: |
|
查看次数: |
12162 次 |
最近记录: |