如何将c#字符串中的UTF-8字节存储在SQL Server 2000的TEXT列中

本文关键字:SQL Server 2000 列中 TEXT 存储 UTF-8 字符串 字节 | 更新日期: 2023-09-27 18:09:10

我有一个现有的SQL Server 2000数据库,它在text列中存储文本的UTF-8表示。我没有修改列类型的选项,并且必须能够将c#程序中的非ascii Unicode数据存储到该列中。

代码如下:

sqlcmd.CommandText =
    "INSERT INTO Notes " +
    "(UserID, LocationID, Note) " +
    "VALUES (" +
        Note.UserId.ToString() + ", " +
        Note.LocationID.ToString() + ", " +
        "@note); " +
    "SELECT CAST(SCOPE_IDENTITY() AS BIGINT) ";
SqlParameter noteparam = new SqlParameter( "@note", System.Data.SqlDbType.Text, int.MaxValue );
在这一点上,我已经尝试了几种不同的方法来获得我的UTF-8数据到参数。例如:
// METHOD ONE
byte[] bytes = (byte[]) Encoding.UTF8.GetBytes( Note.Note );
char[] characters = bytes.Select( b => (char) b ).ToArray();
noteparam.Value = new String( characters );

我也试过简单的

// METHOD TWO
noteparam.Value = Note.Note;

// METHOD THREE
byte[] bytes = (byte[]) Encoding.UTF8.GetBytes( Note.Note );
noteparam.Value = bytes;

继续,下面是剩下的代码:

sqlcmd.Parameters.Add( noteparam );
sqlcmd.Prepare();
try
    {
    Note.RecordId = (Int64) sqlcmd.ExecuteScalar();
    }
catch
    {
    return false;
    }

方法一(将UTF8字节转换为字符串)做了一些奇怪的事情-我认为它是第二次对字符串进行UTF-8编码。

方法二存储垃圾。

方法三在ExecuteScalar()中抛出一个异常,声称它不能将参数转换为String。

我已经知道的事情,所以不必告诉我:

  • SQL Server 2000已经过了/即将结束生命周期
  • TEXT列不代表Unicode文本
  • 说真的,SQL Server 2000已经过时了。你需要升级。

有什么建议吗?

如何将c#字符串中的UTF-8字节存储在SQL Server 2000的TEXT列中

如果您的数据库排序规则是SQL_Latin1_General_CP1(美国版SQL Server 2000的默认值),那么您可以使用以下技巧将Unicode文本存储为UTF-8在char, varchartext列中:

byte[] bytes = Encoding.UTF8.GetBytes(Note.Note);
noteparam.Value = Encoding.GetEncoding(1252).GetString(bytes);

之后,当你想要读回文本时,反转这个过程:

SqlDataReader reader;
// ...
byte[] bytes = Encoding.GetEncoding(1252).GetBytes((string)reader["Note"]);
string note = Encoding.UTF8.GetString(bytes);

如果您的数据库排序规则是而不是 SQL_Latin1_General_CP1,那么您将需要用正确的代码页替换1252。

注意:如果您查看Enterprise Manager或Query Analyzer中存储的文本,您将看到替换非ascii文本的奇怪字符,就像您在不支持Unicode的文本编辑器中打开UTF-8文档一样。

工作原理:当将Unicode文本存储在非Unicode列中时,SQL Server自动将文本从Unicode转换为数据库排序规则指定的代码页。目标代码页中不存在的任何Unicode字符都将被不可逆转地打乱,这就是前两个方法不起作用的原因。

但是方法一你是对的。缺少的步骤是通过使用Windows-1252代码页将原始UTF-8字节转换为Unicode来"保护"它们。现在,当SQL Server执行从Unicode到Windows-1252的自动转换时,它会得到原始的UTF-8字节。