Ich habe eine Rails-Anwendung, die im Produktionsmodus ausgeführt wird, aber plötzlich trat dieser Fehler auf, als ein Benutzer versuchte, einen Datensatz zu speichern.
Mysql2::Error: Incorrect string value
Weitere Details (aus dem Produktionsprotokoll):
Parameters: {"utf8"=>"â<9c><93>" ...
Mysql2::Error: Incorrect string value: '\xC5\x99\xC3\xA1k
Mysql2::Error: Incorrect string value: '\xC5\x99\xC3\xA1k
Jetzt habe ich einige Lösungen gesehen, bei denen die Datenbanken gelöscht und neu erstellt werden mussten, aber ich kann das nicht.
Jetzt zeigt mysql das:
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)
Was ist falsch und wie kann ich es ändern, damit ich mit keinem Zeichen Probleme habe?
Außerdem: Kann dieses Problem mit Javascript gelöst werden? Konvertieren Sie es, bevor Sie es senden?
Vielen Dank
das Problem wird durch den Zeichensatz Ihrer MySQL-Serverseite verursacht. Sie können manuell wie folgt konfigurieren:
ALTER TABLE your_database_name.your_table CONVERT TO CHARACTER SET utf8
oder lassen Sie die Tabelle fallen und erstellen Sie sie wie folgt:
rake db:drop
rake db:create
rake db:migrate
verweise:
https://stackoverflow.com/a/18498210/2034097
https://stackoverflow.com/a/16934647/2034097
UPDATE
der erste Befehl wirkt sich nur auf die angegebene Tabelle aus. Wenn Sie alle Tabellen in einer Datenbank ändern möchten, können Sie dies auch tun
ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ci;
referenz:
Ich habe es geschafft, Emojis (die 4 Bytes beanspruchen) zu speichern, indem ich diesem blog post folgte:
Rails 4, MySQL und Emoji (
Mysql2::Error: Incorrect string value error.
)Sie denken vielleicht, dass Sie die meisten utf8-Daten sicher in .__ einfügen können. zu mysql, wenn Sie angegeben haben, dass der Zeichensatz
utf-8
ist. Traurig, Sie sind jedoch falsch. Das Problem ist, dass der utf8-Zeichensatz belegt 3 Byte , wenn in einer VARCHAR-Spalte gespeichert. Emoji-Zeichen auf Nehmen Sie andererseits 4 Bytes in Anspruch.Die Lösung besteht aus 2 Teilen:
Ändern Sie die Kodierung Ihrer Tabelle und Felder:
ALTER TABLE `[table]` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin, MODIFY [column] VARCHAR(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
Erzählen Sie dem
mysql2
-Adapter davon:development: adapter: mysql2 database: db username: password: encoding: utf8mb4 collation: utf8mb4_unicode_ci
Hoffe das hilft jemandem!
Dann musste ich meine App neu starten und es hat funktioniert .. Bitte beachten Sie, dass einige Emojis ohne dieses Update funktionieren, andere jedoch nicht:
Sie können eine solche Migration verwenden, um Ihre Tabellen in utf8 zu konvertieren:
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
Wenn Sie Emoji speichern möchten, benötigen Sie:
1) Erstellen Sie eine Migration (danke @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) Den Zeichensatz von Rails in utf8mb4 ändern (danke @ selvamani-p)
production:
encoding: utf8mb4
Verweise:
CHARACTER SET
und COLLATE
müssen für bereits erstellte Datenbanken geändert werden:
ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Oder es war notwendig, eine Datenbank mit voreingestellten Parametern zu erstellen:
CREATE DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ci;
Wenn Sie keine Änderungen an Ihrer Datenbankstruktur vornehmen möchten, können Sie das betreffende Feld auch serialisieren.
class MyModel < ActiveRecord::Base
serialize :content
attr_accessible :content, :title
end
Es scheint ein Codierungsproblem beim Abrufen von Daten aus der Datenbank zu sein. Versuchen Sie, das Folgende der Datei database.yml hinzuzufügen
encoding: utf8
Hoffe, das löst dein Problem
Ich kam gerade darüber und schätze @ mfazekas 'Antwort. Ich habe zwei Änderungen an der Migration vorgenommen: eine, um das Entfernen von connection.current_database (zumindest in Rails 5) zu ermöglichen, und die Möglichkeit, die SQL-Anweisungen zu überspringen, wenn MySQL nicht verwendet wird (ich verwende immer noch SQLite in der Entwicklung, aber die Migration muss ausgeführt werden ).
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