简体   繁体   English

MariaDB使用PHP PDO以与原始字段不同的值存储varbinary字段

[英]MariaDB stores varbinary field with different value from the original field using PHP PDO

I'm using PHP - PDO to synchronize a SQL Server Table using RowVersion from our ERP to a MariaDB Database (hosting). 我正在使用PHP-PDO将使用RowVersion的SQL Server表从我们的ERP同步到MariaDB数据库(托管)。

When I save values in a local (office) MariaDB database version 5.5.56, everything goes fine and data is stored correctly. 当我将值保存在本地(办公室)MariaDB数据库版本5.5.56中时,一切正常,数据已正确存储。 When I do just the same to store data in our hosting with MariaDB version 10.0.37, rowversion field saves a different value. 当我执行相同的操作以将数据存储在MariaDB 10.0.37版中的主机中时,rowversion字段将保存不同的值。

I've tried, instead from SQL Server, to copy data between office MariaDb and remote MariaDb, using PHP PDO, and I have the same problem. 我尝试使用PHP PDO,而不是从SQL Server,在办公室MariaDb和远程MariaDb之间复制数据,但我遇到了同样的问题。 Original rowversion value is different from remote rowversion value. 原始rowversion值与远程rowversion值不同。

To store rowversion field I'm using VARBINARY(8). 为了存储行版本字段,我正在使用VARBINARY(8)。

Example: 例:

  • ERP SQL SERVER ROW: (id, description, rowversion). ERP SQL SERVER ROW:(ID,描述,行版本)。 Values: 1, AMARILLO, 0x00000000025DB362 ERP ROW 值:1,AMARILLO,0x00000000025DB362 ERP ROW

  • MariaDb local database: stored values 1,AMARILLO,00000000025db362 Local MariaDb row MariaDb本地数据库:存储的值1,AMARILLO,00000000025db362 本地MariaDb行

  • MariaDb remote database: stored values: 1, AMARILLO, 00000000025d3f62 MariaDb remote row MariaDb远程数据库:存储的值:1,AMARILLO,00000000025d3f62 MariaDb远程行

I don't understand why remote MariaDb saves a different value. 我不明白为什么远程MariaDb保存不同的值。 Both mariadb tables are identical, but one stores one value and the other a different value. 两个mariadb表相同,但是其中一个存储一个值,另一个存储不同的值。 Any ideas? 有任何想法吗? could it be a database version problem? 可能是数据库版本问题吗?

PHP TEST code, in this case from local MariaDb to remote 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']
            ));         
    }

Table: 表:

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';

UPDATED AND SOLVED: 更新并解决:

After reading this post PHP/PDO/MySQL: inserting into MEDIUMBLOB stores bad data I've tested to change the SET NAMES in my remote database. 阅读这篇文章后, PHP / PDO / MySQL:插入MEDIUMBLOB中存储了错误的数据,我已经测试过要更改远程数据库中的SET NAMES。 That solved the problem. 那解决了问题。

I added this line to my PHP program: 我将此行添加到我的PHP程序中:

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

Now the question is why a database (MariaDB) works in one way and the second in other way. 现在的问题是,为什么数据库(MariaDB)以一种方式工作而第二种以另一种方式工作。

Sqlserver is working with Modern_Spanish_CI_AS collation. Sqlserver正在使用Modern_Spanish_CI_AS排序规则。

Local mariadb is working with utf8mb4_unicode_ci, and I set in PDO utf8 本地mariadb正在使用utf8mb4_unicode_ci,并且我在PDO utf8中进行了设置

Remote mariadb is in utf8mb4_general_ci, and I also was setting PDO for utf8. 远程mariadb位于utf8mb4_general_ci中,我也为utf8设置了PDO。

With those collations, the data coming from SqlServer was stored different. 通过这些排序规则,来自SqlServer的数据存储的方式有所不同。 Setting the new collation solved it. 设置新的排序规则即可解决。 It would be better if PDO could use binary data without any interpretation realted to collation. 如果PDO可以使用二进制数据而不进行任何解释进行整理会更好。

SECOND UPDATE 第二次更新

I've found a better way to do this: 我找到了一种更好的方法:

  • I create the table with CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci 我使用CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci创建表

  • I change the CHARSET in PDO to: 我将PDO中的CHARSET更改为:

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

With this, rowversion and languague specific chars are stored right. 这样,就可以正确存储rowversion和languague特定的字符。

Cheers. 干杯。

PDO tries to convert the binary value into a string using the specified UTF-8 encoding. PDO尝试使用指定的UTF-8编码将二进制值转换为字符串。 B3 is not a valid code point and is thus replaced by ? B3不是有效的代码点,因此被替换为? - when encoding back from string to binary, you then get 3F as value for the replacement character ? -从字符串编码为二进制编码时,然后获得3F作为替换字符的值? .

To prevent PDO from doing binary to string conversion, see this SO post: 为了防止PDO进行二进制到字符串的转换,请参见以下SO帖子:

save image in mssql database as varbinary(max) without conversion 将图像保存在mssql数据库中为varbinary(max),无需进行转换

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM