Странные результаты сравнения строк после получения значения TEXT - PullRequest
0 голосов
/ 19 февраля 2012

Я собираю данные с нескольких страниц и вставляю их в базу данных MySQL.Там могут быть дубликаты;Я только хочу хранить уникальные записи.На случай, если моего первичного ключа недостаточно, я ставлю тест, который проверяется, когда я получаю ошибку MySQL 1062 * (повторяющаяся запись в первичном ключе **).Тест проверяет, что все части вставляемого кортежа идентичны сохраненному кортежу.Я обнаружил, что когда я получаю ошибку 1062, что сохраненный кортеж и очищенный кортеж отличаются только одним элементом / полем, полем TEXT.

Сначала я извлек уже сохраненную запись и передал их обе в htmlspecialchars(), чтобы визуально сравнить вывод;они выглядели одинаково.

Согласно strlen(), длина строки, извлеченной из БД, составляла 304 символа, но длина новой извлеченной строки была 305. similar_text() подтвердила это, вернув 304 ***.

Итак, я перебрал одну строку, сравнивая символ для символа с другой строкой, останавливаясь при несоответствии.Проблема была в первом персонаже.В строке, поступающей из БД, это было N, но обе строки начинаются с I (даже при выводе из htmlspecialchars()).Плюс строка БД была предположительно на один символ короче, а не длиннее.

Затем я проверил вывод (печать htmlspecialchars()) и снова strlen(), но на этот раз до вставки исходной строки (той, которая заканчивается в БД) и до вставки дублированной строки,Они выглядели так же, как и раньше, и strlen() вернул 305 для обоих.

Так что это заставило меня думать, что между моим PHP и MySQL что-то происходит.Поэтому вместо того, чтобы сравнивать вновь очищенную строку со строкой в ​​базе данных с тем же первичным ключом (идентификатором), я пытаюсь получить кортеж, в котором каждое отдельное поле равно их соответствующим частям во вновь очищенном разделе, например SELECT * FROM table WHERE value1='{$MYSQL_ESCAPED['value1']}' .... AND valueN='{$MYSQL_ESCAPED['valueN']}';, икортеж возвращается.Поэтому они идентичны во всех отношениях, включая проблемное поле TEXT.

Что здесь происходит?

Сразу, когда я вижу N перед строкой, я думаю о NVARCHAR и т. Д. Из MSSQL, но, как я знаю, это не является частью MySQL, но ...

Может ли это иметь какое-либо отношение к тому факту, что "Каждое значение TEXT сохраняется с использованием двухбайтового префикса длины, который указывает количество байтов в значении." ?

Или это просто указывает на проблему кодировки символов?


Редактировать:

  • Не существуетбайтовые символы, хранящиеся в базе данных.
  • mb_strlen() возвращает те же результаты, что и strlen(), где упомянуто выше.
  • Использование utf8_encode() или mb_convert_encoding() перед вставкой в ​​БД не имеет значения;невидимый N по-прежнему префикс строки, полученной из базы данных.

Примечания :

  • Перед вставкой любой строки в мойБаза данных, которую я передаю через mysql_real_escape_string(trim(preg_replace('/\s\s+/', ' ', $str))), которая заменяет двойные пробелы одиночными, удаляет начальные и хвостовые пробелы и экранирует их для вставки MySQL.
  • Страница, на которой я печатаю вывод и тестирование, - UTF-8.
  • При создании моя БД имеет набор символов, установленный на utf8, ее сопоставление на utf8_general_ci, и я используюкоманда SET NAMES 'utf8' COLLATE 'utf8_general_ci'; тоже, в качестве меры предосторожности.
  • Примечания к ноге:
    • * Я также заставляю выход из соскоба.
    • ** Первичный ключ - это просто идентификатор (VARCHAR(10)), который я вычеркиваю со страниц.
    • *** Количество общих символов

1 Ответ

0 голосов
/ 19 февраля 2012

Поля TEXT подлежат преобразованию набора символов как / когда MySQL сочтет нужным.Однако MySQL не будет случайным образом добавлять / удалять данные без причины.В то время как текстовые поля хранят длину данных в виде 2 дополнительных байтов в заголовке двоичного объекта данных, содержащего данные текстового поля, эти 2 байта НИКОГДА не показываются конечному пользователю.Если предположить, что настройки набора символов одинаковы во всем конвейере client-> database-> on-disk-> database-> client, длина строки никогда не должна изменяться.

...