MariaDB хранит поле varbinary со значением, отличным от исходного поля, используя PHP PDO

Я использую PHP-PDO для синхронизации таблицы SQL Server с помощью RowVersion из нашей ERP в базу данных MariaDB (хостинг).

Когда я сохраняю значения в локальной (офисной) базе данных MariaDB версии 5.5.56, все идет нормально, и данные сохраняются правильно. Когда я делаю то же самое для хранения данных на нашем хостинге с версией MariaDB 10.0.37, поле rowversion сохраняет другое значение.

Вместо этого я попытался с SQL Server скопировать данные между офисом MariaDb и удаленным MariaDb, используя PHP PDO, и у меня та же проблема. Исходное значение rowversion отличается от удаленного значения rowversion.

Для хранения поля rowversion я использую VARBINARY(8).

Пример:

  • ERP SQL SERVER ROW: (id, описание, rowversion). Значения: 1, AMARILLO, 0x00000000025DB362 ERP ROW

  • Локальная база данных MariaDb: сохраненные значения 1,AMARILLO,00000000025db362 Локальная строка MariaDb

  • Удаленная база данных MariaDb: сохраненные значения: 1, AMARILLO, 00000000025d3f62 удаленная строка MariaDb

Я не понимаю, почему удаленный MariaDb сохраняет другое значение. Обе таблицы mariadb идентичны, но в одной хранится одно значение, а в другой — другое. Есть идеи? может ли быть проблема с версией базы данных?

Код PHP TEST, в данном случае с локального MariaDb на удаленный MariaDb:

    $sql = "SELECT * FROM colors";
    $sth = $this->Db->localdb->query($sql);
    $res = $sth->fetchAll(PDO::FETCH_ASSOC);

    $sql = "TRUNCATE TABLE colors";
    $this->Db->remotedb->exec($sql);

    $sql = "INSERT INTO colors (id,des,rowversion) VALUES (?,?,?)";
    $sthinsert = $this->Db->remotedb->prepare($sql);


    foreach ($res as $line)
    {
            echo "Inserting color {$line['id']}" . PHP_EOL;
            $sthinsert->execute(array(
                $line['id'],$line['des'],$line['rowversion']
            ));         
    }

Стол:

CREATE TABLE `colors` (
    id                              int NOT NULL,
    des                             varchar(30),
    rowversion                      varbinary(8),
    date                            timestamp NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (id)
) ENGINE=myisam DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci COMMENT 'Colors';

ОБНОВЛЕНО И РЕШЕНО:

После прочтения этого сообщения PHP/PDO/MySQL: вставка в MEDIUMBLOB сохраняет неверные данные Я протестировал изменение SET NAMES в моей удаленной базе данных. Это решило проблему.

Я добавил эту строку в свою программу PHP:

$this->Db->remotedb->exec("SET NAMES latin1 COLLATE latin1_general_ci");

Теперь вопрос, почему база данных (MariaDB) работает так, а вторая по-другому.

Sqlserver работает с сопоставлением Modern_Spanish_CI_AS.

Локальный mariadb работает с utf8mb4_unicode_ci, и я установил в PDO utf8

Удаленный mariadb находится в utf8mb4_general_ci, и я также устанавливал PDO для utf8.

С этими сопоставлениями данные, поступающие от SqlServer, сохранялись по-разному. Установка нового сопоставления решила эту проблему. Было бы лучше, если бы PDO мог использовать двоичные данные без какой-либо интерпретации, связанной с сопоставлением.

ВТОРОЕ ОБНОВЛЕНИЕ

Я нашел лучший способ сделать это:

  • Я создаю таблицу с CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

  • Я меняю CHARSET в PDO на:

$this->Db->remotedb->exec("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci");

При этом символы версии строки и языка сохраняются правильно.

Ваше здоровье.


person Ramon    schedule 29.12.2018    source источник
comment
Если я что-то не упустил, эти значения одинаковы. Не существует такой вещи, как шестнадцатеричное число с учетом регистра.   -  person Sammitch    schedule 29.12.2018
comment
Не идентичны: один 0...25db362, а другой 0...25d3f62   -  person Ramon    schedule 29.12.2018
comment
Как вы копируете данные?   -  person Sammitch    schedule 29.12.2018
comment
Я читаю с SqlServer и сохраняю в MariaDB, используя PHP PDO. Данные в одном MariaDb хранятся иначе, чем в другом MariaDb. Может ли какая-либо конфигурация базы данных повлиять на значения varbinary? Я использую ту же конфигурацию PDO и программу php.   -  person Ramon    schedule 30.12.2018


Ответы (1)


PDO пытается преобразовать двоичное значение в строку, используя указанную кодировку UTF-8. B3 не является допустимой кодовой точкой и поэтому заменяется на ? - при обратном кодировании из строки в двоичный код вы получаете 3F в качестве значения для замещающего символа ?.

Чтобы предотвратить преобразование PDO из двоичного кода в строку, см. этот пост SO:

сохранить изображение в базе данных mssql как varbinary(max) без преобразования

person Quagaar    schedule 29.12.2018
comment
В этом может быть смысл. Прочитав сообщение, я не могу решить проблему, так как сохраняю данные в MYSQL, а не в SqlServer. Интересно, что мои исходные данные — это SqlServer. Если я сохраняю данные в своем локальном MariaDb, все идет нормально, но если я делаю то же самое на своем хостинге/удаленном MariaDb, сохраняется неправильное значение. Моя конфигурация для PDO одинакова для обоих подключений, поэтому я думаю, что это может быть проблема конфигурации/версии базы данных. Кажется, что PDO делает разные вещи для каждой базы данных. - person Ramon; 30.12.2018
comment
Установите атрибут PDO::SQLSRV_ATTR_ENCODING при чтении из SQL Server, так как именно здесь возникает проблема. Если это не сработает, возможно, в SQL Server есть эквивалент функции MySQL hex для преобразования двоичных данных в шестнадцатеричную строку. - person Quagaar; 30.12.2018