Можно ли сохранить символ «0» в sqlite в виде текста

У меня есть строка UTF с символом \0 и текстовым полем в таблице sqlite.
Когда я попытался вставить строку в текстовое поле таблицы, а затем прочитать ее из базы данных, я заметил, что строковое значение усекается после символа \0.

Вопрос: возможно ли сохранить/восстановить такие строки в sqlite без потери данных после \0?

Фрагмент кода:

 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);
            }
        }
    }    

ОБНОВЛЕНИЕ №1 Похоже, проблема на этапе чтения. В файле базы данных существует по крайней мере "afterNull" часть строки.

ОБНОВЛЕНИЕ № 2 Это считалось ошибкой System.Data.SQLite (‹1.04.84). http://system.data.sqlite.org/index.html/tktview/3567020edf12d438cb7cf757b774ff3a04dc381e


person Vladimir Datsyuk    schedule 05.03.2013    source источник
comment
Я думаю, для этого и нужен BLOB.   -  person Joachim Isaksson    schedule 05.03.2013
comment
Когда строка передается в sqlite, она, вероятно, рассматривает «\ 0» как ограничитель строки. Не могли бы вы вместо этого использовать '\\0'?   -  person Kyle    schedule 05.03.2013
comment
Иоахим, спасибо. Я почти уверен, что использование BLOB решит проблему сохранения. Может быть, это единственный вариант для меня. В моем случае большую часть времени у меня есть только удобочитаемые строки без \0. Довольно редко у меня есть удобочитаемые строки с \0. После введения BLOB необходимо будет выполнить дополнительные преобразования строк ToBytes/FromBytes, а также будет сложнее внедрить функцию поиска в мое приложение.   -  person Vladimir Datsyuk    schedule 06.03.2013
comment
Zenox, вопрос в том, почему \0 рассматривается как ограничитель строки для сохранения строк UTF в sqlite. Sqlite использует UTF для хранения текста. \0 - это всего лишь первый символ из огромной таблицы UTF. Я надеюсь, что все остальные символы могут быть сохранены без каких-либо проблем.   -  person Vladimir Datsyuk    schedule 06.03.2013
comment
В sqlite API есть функция sqlite3_bind_text, которая фактически вызывается адаптером данных Sqlite. Здесь sqlite.org/c3ref/bind_blob.html упоминается, что при передаче пареметров правильно, затем процитируйте: [Если какие-либо символы NUL встречаются при смещениях байтов меньше, чем значение четвертого параметра, тогда результирующее строковое значение будет содержать встроенные NUL]   -  person Vladimir Datsyuk    schedule 06.03.2013
comment
Отвечает ли это на ваш вопрос? строки SQLite с NUL   -  person iammilind    schedule 13.02.2020


Ответы (1)


В SQLite символы \0 считаются недопустимыми.

Хотя можно поместить такие строки в базу данных (используя форму указателя+длины различных функций), многие функции, работающие со строками, останавливаются при встрече с символом \0. Поэтому в документации говорится:

Результат выражений, включающих строки со встроенными значениями NUL, не определен.

Если вам действительно нужно хранить данные с нулевыми байтами, вы должны хранить их как большой двоичный объект (DbType.Binary).

person CL.    schedule 05.03.2013
comment
Спасибо за ответ. Похоже, в этой ситуации я должен использовать BLOB/DbType.Binary. Однако мне кажется странным, что \0 не является допустимым символом в UTF. Я думаю, что это просто первый символ в любой таблице UTF. Он также на 100% действителен в строках .NET. Так что, по крайней мере, для меня выглядит странно, что кодировка строки по умолчанию в sqlite - UTF8, но невозможно использовать один символ из таблицы UTF8 (даже если этот символ используется как специальный в строках C). - person Vladimir Datsyuk; 06.03.2013
comment
Символы \0 допустимы в строках в кодировке UTF, и SQLite позволяет вам их хранить. U+0000 — это \0, что является допустимым символом UTF-8 en.wikipedia.org/wiki /UTF-8 . Подробнее о второй части см. на странице sqlite.org/c3ref/bind_blob.html. - person ryantm; 07.10.2014
comment
@ryantm Результат выражений, включающих строки со встроенными NUL, не определен. - person CL.; 07.10.2014
comment
Я не совсем уверен, что это значит, но я предполагаю, что речь идет о выражениях запроса sqlite.org /lang_expr.html . Когда я помещаю в них \0, он обрабатывает его так, как будто конец запроса находится на этом символе (обычно синтаксическая ошибка, когда он находится в середине строки). Когда я использую привязку (текст или блоб), он принимает \0, что согласуется с предложением, предшествующим тому, которое вы процитировали: если какие-либо символы NUL встречаются со смещением байтов меньше, чем значение четвертого параметра, то результирующее строковое значение будет содержать встроенные значения NUL. - person ryantm; 08.10.2014