выполнить не удалось: Неверное строковое значение: '\ xD6sterl ...' с DBD mariadb и perl - PullRequest
1 голос
/ 19 июня 2019

Я начинающий программист на Perl, пытаюсь использовать DBI для записи буфера текста, содержащего электронное письмо с umlauts и другими не-ASCII-символами, в базу данных joomla, и у меня возникла проблема.

DBD::mysql::st execute failed: Incorrect string value: '\xD6sterl...' for column `lsv5webstage`.`xuxgc_content`.`fulltext` at row 1 at /home/alerts/scripts_linstage/AdvisoryTest.pm line 373.

Я недостаточно знаком с тем, как работает кодирование, чтобы полностью понять, в чем проблема. Это система fedora29 с mariadb-10.3.12 и joomla-3.9.

По-видимому, '\ xD6' - это O с умляутом в "Себастьяне Эстерлунде". Я читал что-то о том, что utf8 не может обрабатывать 4-х символьный код, но я не до конца понимаю.

Я нашел в Интернете следующую ссылку, в которой говорится об изменении типа кодировки с utf8 на utf8mb4, но все таблицы, похоже, уже используют эту кодировку:

> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR 
Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8mb4_unicode_ci |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+

Я не уверен, что это полезно, но это оператор вставки, который я использую в своем perl-коде:

    my $sql                 = <<EOF;
    INSERT INTO xuxgc_content (title, alias, introtext, `fulltext`, state, catid, created, created_by, created_by_alias, modified, modified_by, checked_out, checked_out_time, publish_up, publish_down, images, urls, attribs, version, ordering, metakey, metadesc, metadata, access, hits, language)
    VALUES ($title, "$title_alias", $introText, $fullText, $state, $catid, $created, $created_by, $created_by_alias, $modified, $modified_by, $checked_out, $checked_out_time, $publish_up, $publish_down, $images, $urls, $attribs, $version, $ordering, $metakey, $metadesc, $metadata, $access, $hits, $language);
    EOF

    my $sth = $dbh->prepare($sql);
    $sth->execute();
    db_disconnect($dbh);

Переменная $ fullText заполняется из буфера, который содержит тело письма. Я запускаю его через quote () перед выполнением INSERT.

$fullText       = $dbh->quote($fullText);

Я также пытался использовать "SET NAMES utf8mb4; INSERT INTO Mytable ...;" и ему просто не понравился формат.

Вот полная функция, которая используется для подключения к базе данных:

sub db_connect () {
  my %DB        = (
    'host'  => 'myhost',
    'db'    => 'mydb',
    'user'  => 'myuser',
    'pass'  => 'mypass',
  );

  return DBI->connect("DBI:mysql:database=$DB{'db'};host=$DB{'host'}", $DB{'user'}, $DB{'pass'}, { mysql_enable_utf8mb4 => 1 });
 }

Я не припоминаю, чтобы в прошлом эта проблема возникала, и этот сценарий использовался довольно давно.

1 Ответ

1 голос
/ 19 июня 2019

D6 является шестнадцатеричным для Ö в CHARACTER SET latin1 (и некоторых других).

Вы заявили, что ваш клиент использует кодировку UTF-8 (utf8mb4), поэтому он плюет на вас.

Пожалуйста, укажите SELECT HEX(col), col ..., чтобы увидеть, попал ли D6 в базу данных (следовательно, проблема insert ) или что-то еще (возможно, проблема выборки / отображения).

Кроме того, вы не указали строку $fulltext в кавычках, поэтому вы, вероятно, получите всевозможные синтаксические ошибки.

Пожалуйста, не вслепую вставляйте строки в операторы INSERT, но избегайте их, когда вы их вводите.

В этом может быть полезная подсказка Perl:

    use utf8;
    use open ':std', ':encoding(UTF-8)';
my $dbh = DBI->connect("dbi:mysql:".$dsn, $user, $password, {
   PrintError => 0,
   RaiseError => 1,
   mysql_enable_utf8 => 1,  # Switch to UTF-8 for communication and decode.
});
# or {mysql_enable_utf8mb4 => 1} if using utf8mb4

И ищите методы для привязки / цитирования / экранирования.

...