【发布时间】:2013-03-05 17:38:55
【问题描述】:
我在 sqlite 表中有一个带有 \0 字符和文本字段的 UTF 字符串。
当我尝试将字符串插入表格文本字段然后从数据库中读取它时,我注意到字符串值在 \0 字符之后被截断。
问题:是否可以在 \0 之后在 sqlite 中保存/恢复此类字符串而不会丢失数据?
代码sn-p:
public static void IssueWith0Character()
{
const string sql = "DROP TABLE IF EXISTS SomeTable;" +
"CREATE TABLE SomeTable (SomeField TEXT not null);"
+ "INSERT INTO SomeTable (SomeField) Values ( :value )";
var csb = new SQLiteConnectionStringBuilder
{DataSource = "stringWithNull.db", Version = 3};
// string with '0' character
const string stringWithNull = "beforeNull\0afterNull";
using (var c = new SQLiteConnection(csb.ConnectionString))
{
c.Open();
using (var cmd = c.CreateCommand())
{
var p = new SQLiteParameter(":value", DbType.String) {Value = stringWithNull};
cmd.CommandText = sql;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
}
using (var cmd = c.CreateCommand())
{
cmd.CommandText = "SELECT SomeField FROM SomeTable;";
var restoredValue = (string) cmd.ExecuteScalar();
Debug.Assert(stringWithNull == restoredValue);
}
}
}
UPDATE #1 看起来问题出在阅读阶段。数据库文件中至少存在字符串的“afterNull”部分。
UPDATE #2 这被认为是 System.Data.SQLite 错误 (http://system.data.sqlite.org/index.html/tktview/3567020edf12d438cb7cf757b774ff3a04dc381e
【问题讨论】:
-
我认为这就是
BLOB的用途。 -
当字符串被传递给 sqlite 时,它可能会将 '\0' 视为字符串终止符。你能改用'\\0'吗?
-
约阿希姆,谢谢。我几乎可以肯定使用 BLOB 将解决持久性问题。可能这对我来说是唯一的选择。在我的情况下,大多数时候我只有人类可读的字符串,没有 \0s。我很少有带有 \0 的人类可读字符串。 А 引入 BLOB 后,将需要进行额外的 ToBytes/FromBytes 字符串转换,并且在我的应用程序中引入搜索功能将更加困难。
-
Zenox,问题是为什么 \0 被视为在 sqlite 中保存 UTF 字符串的字符串终止符。 Sqlite 使用 UTF 存储文本。 \0 只是巨大 UTF 表中的第一个字符。我希望所有其他符号都可以保存而没有任何问题。
-
sqlite API 中有 sqlite3_bind_text 函数,实际上是由 Sqlite 数据适配器调用的。这里sqlite.org/c3ref/bind_blob.html提到如果参数传递正确然后引用:[如果任何NUL字符出现在小于第四个参数值的字节偏移处,那么结果字符串值将包含嵌入的NUL]