web-dev-qa-db-fra.com

Mysql2 :: Error: Valeur de chaîne incorrecte

J'ai une application Rails en mode de production, mais tout à coup, cette erreur s'est produite aujourd'hui lorsqu'un utilisateur a essayé de sauvegarder un enregistrement.

Mysql2::Error: Incorrect string value

Plus de détails (du journal de production):

Parameters: {"utf8"=>"â<9c><93>" ... 

Mysql2::Error: Incorrect string value: '\xC5\x99\xC3\xA1k 

Mysql2::Error: Incorrect string value: '\xC5\x99\xC3\xA1k 

Maintenant, j'ai vu certaines solutions nécessitant de supprimer les bases de données et de les recréer, mais je ne peux pas le faire.

Maintenant, mysql montre ceci:

mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.04 sec)

Qu'est-ce qui ne va pas et comment puis-je le changer afin que je n'ai aucun problème avec les personnages?

Aussi: est-ce que ce problème peut être résolu avec javascript? Convertissez-le avant de l'envoyer?

Merci

51
Trt Trt

le problème est dû au jeu de caractères de votre côté serveur mysql. Vous pouvez configurer manuellement comme:

ALTER TABLE your_database_name.your_table CONVERT TO CHARACTER SET utf8

ou déposez la table et recréez-la comme ceci:

rake db:drop
rake db:create
rake db:migrate

références:

https://stackoverflow.com/a/18498210/2034097

https://stackoverflow.com/a/16934647/2034097

METTRE &AGRAVE; JOUR

la première commande n'affecte que la table spécifiée, si vous voulez modifier toutes les tables d'une base de données, vous pouvez faire comme

ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ci;

référence:

https://stackoverflow.com/a/6115705/2034097

69
Chuanpin Zhu

J'ai réussi à stocker des emojis (qui occupent 4 octets) en suivant ce blog post :

Rails 4, MySQL et Emoji (Mysql2::Error: Incorrect string value error.)

Vous pourriez penser que vous êtes en sécurité en insérant la plupart des données utf8 dans à mysql lorsque vous avez spécifié que le jeu de caractères est utf-8. Malheureusement, Cependant, vous vous trompez. Le problème est que le jeu de caractères utf8 prend 3 octets lorsqu’il est stocké dans une colonne VARCHAR. Caractères Emoji, sur d'autre part, prenez 4 octets

La solution est en 2 parties:

Changez l'encodage de votre table et de vos champs:

ALTER TABLE `[table]` 
  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin,
MODIFY [column] VARCHAR(250)
    CHARACTER SET utf8mb4 COLLATE utf8mb4_bin

Parlez-en à l'adaptateur mysql2:

development:
  adapter: mysql2
  database: db
  username: 
  password:
  encoding: utf8mb4
  collation: utf8mb4_unicode_ci

J'espère que cela aide quelqu'un!

Ensuite, j'ai dû redémarrer mon application et cela a fonctionné ..__ Veuillez noter que certains émojis fonctionneront sans ce correctif, alors que d'autres ne le feront pas:

  • ➡️ a travaillé
  • ???? N'a pas fonctionné jusqu'à ce que j'ai appliqué le correctif décrit ci-dessus.
34
Besi

Vous pouvez utiliser une migration comme celle-ci pour convertir vos tables en utf8:

class ConvertTablesToUtf8 < ActiveRecord::Migration
  def change_encoding(encoding,collation)
    connection = ActiveRecord::Base.connection
    tables = connection.tables
    dbname =connection.current_database
    execute <<-SQL
      ALTER DATABASE #{dbname} CHARACTER SET #{encoding} COLLATE #{collation};
    SQL
    tables.each do |tablename|
      execute <<-SQL
        ALTER TABLE #{dbname}.#{tablename} CONVERT TO CHARACTER SET #{encoding} COLLATE #{collation};
      SQL
    end
  end

  def change
    reversible do |dir|
      dir.up do
        change_encoding('utf8','utf8_general_ci')
      end
      dir.down do
        change_encoding('latin1','latin1_swedish_ci')
      end
    end
  end
end
23
mfazekas

Si vous voulez stocker emoji, vous avez besoin de:

1) Créer une migration (merci @mfazekas)

class ConvertTablesToUtf8 < ActiveRecord::Migration
  def change_encoding(encoding,collation)
    connection = ActiveRecord::Base.connection
    tables = connection.tables
    dbname =connection.current_database
    execute <<-SQL
      ALTER DATABASE #{dbname} CHARACTER SET #{encoding} COLLATE #{collation};
    SQL
    tables.each do |tablename|
      execute <<-SQL
        ALTER TABLE #{dbname}.#{tablename} CONVERT TO CHARACTER SET #{encoding} COLLATE #{collation};
      SQL
    end
  end

  def change
    reversible do |dir|
      dir.up do
        change_encoding('utf8mb4','utf8mb4_bin')
      end
      dir.down do
        change_encoding('latin1','latin1_swedish_ci')
      end
    end
  end
end

2) Changez le jeu de caractères de Rails en utf8mb4 (merci @ selvamani-p)

production:
  encoding: utf8mb4

Références:

https://stackoverflow.com/a/39465494/1058096

https://stackoverflow.com/a/26273185/1058096

2
dtelaroli

Besoin de changer CHARACTER SET et COLLATE pour la base de données déjà créée:

ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Ou il était nécessaire de créer une base de données avec des paramètres prédéfinis:

CREATE DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ci;
1
shilovk

De plus, si vous ne souhaitez pas modifier la structure de votre base de données, vous pouvez opter pour la sérialisation du champ en question.

class MyModel < ActiveRecord::Base
  serialize :content

  attr_accessible :content, :title
end
0
Paul Marclay

Cela ressemble à un problème d'encodage lors de l'obtention des données de la base de données. Essayez d’ajouter le texte ci-dessous à votre fichier database.yml.

   encoding: utf8 

J'espère que cela résoudra votre problème

0
Dhepthi

Je viens de découvrir cela et d’apprécier la réponse de @ mfazekas. J'ai apporté deux modifications à la migration: une pour permettre la suppression de connection.current_database (au moins dans Rails 5) et la possibilité de sauter les instructions SQL si vous n'utilisiez pas MySQL (j'utilise toujours SQLite en développement mais j'ai besoin de la migration ).

class ConvertTablesToUtf8 < ActiveRecord::Migration[5.2]
  def change_encoding(encoding,collation)
    # Allow for different adapter in different environment
    return unless ActiveRecord::Base.connection_config[:adapter] == "mysql"
    tables = connection.tables
    dbname = ActiveRecord::Base.connection_config[:database]
    execute <<-SQL
      ALTER DATABASE #{dbname} CHARACTER SET #{encoding} COLLATE #{collation};
    SQL
    tables.each do |tablename|
    execute <<-SQL
      ALTER TABLE #{dbname}.#{tablename} CONVERT TO CHARACTER SET #{encoding} COLLATE #{collation};
    SQL
    end
  end

  def change
    reversible do |dir|
      dir.up do
        change_encoding('utf8','utf8_general_ci')
      end
      dir.down do
        change_encoding('latin1','latin1_swedish_ci')
      end
    end
  end
end
0
mrturtle