将 mysql 切换到 mysql2 gem 导致所有 unicode 混乱

发布于 2024-11-02 02:51:38 字数 356 浏览 11 评论 0原文

在我的应用程序在 Heroku 上并使用 mysql gem 之前。 当我将该数据迁移到我自己的 mysql 数据库并切换到 mysql2 gem 时,我的 uncode 字符将以原始 utf8 形式查看。

另一方面,如果我使用 mysql2 gem 将 unicode 数据更新到数据库中,然后切换回 mysql gem,如果我查询 unicode 字符,我会得到问号。

根据我的观察,与 mysql 客户端实用程序(在我的 Ubuntu 上)相比,mysql gem 产生相同的输出,而 mysql2 则不然。

有没有办法告诉 mysql2 gem 使用与 mysql 客户端相同的方式读取数据和编码? (因此与 mysql gem 的方式相同)

Before my app was on Heroku and used mysql gem.
When I migrate that data into my own mysql database, and switch to mysql2 gem, my uncode character is viewed in their raw utf8 form.

In the other hand, if I update unicode data into database using mysql2 gem, then switch back to mysql gem, I get back question mark if I query for unicode character.

From my observation, mysql gem produces identical output compare to mysql client utility (on my Ubuntu) while mysql2 does not.

Is there a way to tell mysql2 gem to read data and encode using the same way mysql client does? (and thus in the same way mysql gem does)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

巨坚强 2024-11-09 02:51:38

在将数据迁移到 Heroku 或从 Heroku 迁移数据时,我也遇到过类似的问题,您应该能够使用

encoding: utf8

Point 强制在 database.yml 中进行编码,以使 Heroku 默认使用 PostgreSQL,即使您已经包含了 mysql gem。

I've had similar problems when migrating data to and from Heroku, you should be able to force encoding in database.yml with

encoding: utf8

Point to make also is that Heroku uses PostgreSQL by default, even if you've included mysql gem.

疯狂的代价 2024-11-09 02:51:38

好吧,我也遇到了很多问题,但提出了一个肮脏的解决方案。问题是,在 Rails 2 中,“mysql”gem 似乎接受来自 mysql 数据库(默认)的 latin1 编码字符串作为 utf 8。mysql2

不再这样做了。使用 mysql gem 从rails2 中的activerecord 加载,显示正确的输出,但在rails3 中,mysql gem 不再工作。因此,转到 Rails2 中的控制台,并使用以下代码片段。我使用数据库的副本,以防您想返回。

def update_instance_from_backup(current_instance)
  begin
    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql",
      :host     => "localhost",
      :username => "...",
      :password => "...",
      :database => "database_backup"
    )
    attributes = current_instance.class.find(current_instance.id).attributes
    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql2",
      :host     => "localhost",
      :username => "...",
      :password => "...",
      :database => "database",
      :encoding => "utf8"
    )
  rescue
  else
    current_instance.update_attributes attributes
    puts "#{current_instance.class.name} #{current_instance.id} (dd. #{current_instance.updated_at}) updated"
  end
end

现在,您可以在任何 activerecord 实例上调用 update_instance_from_backup(instance)。

foo = Foo.find(3)
update_instance_from_backup(foo)

将允许您更新实例数据。你当然可以自己做一个循环。 :)

Ok, I also got a lot of problems with this, but made a dirty solution. Thing is, in Rails 2, the 'mysql' gem seems to accept a latin1 encoded string from the mysql database (default) as utf 8.

mysql2 does not do this anymore. Loading from activerecord in rails2 with the mysql gem, shows the correct output, but in rails3, the mysql gem does not work anymore. Therefor, go to a console in rails2, and use the following snippet. I use a copy of the database, in case you want to go back.

def update_instance_from_backup(current_instance)
  begin
    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql",
      :host     => "localhost",
      :username => "...",
      :password => "...",
      :database => "database_backup"
    )
    attributes = current_instance.class.find(current_instance.id).attributes
    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql2",
      :host     => "localhost",
      :username => "...",
      :password => "...",
      :database => "database",
      :encoding => "utf8"
    )
  rescue
  else
    current_instance.update_attributes attributes
    puts "#{current_instance.class.name} #{current_instance.id} (dd. #{current_instance.updated_at}) updated"
  end
end

Now, you can call update_instance_from_backup(instance) on any activerecord instance.

foo = Foo.find(3)
update_instance_from_backup(foo)

Will let you update your instance data. You can of course do a loop yourself. :)

梦旅人picnic 2024-11-09 02:51:38

我的解决方案是将数据转储到 .sql 文件中,使用 unicode 转换器将该 .sql 文件转换为正确的编码,然后将其转储回服务器。

My solution is to dump the data into a .sql file, use a unicode converter to convert that .sql file to proper encoding and then dump it back to the server.

樱桃奶球 2024-11-09 02:51:38

我写了一个迁移来解决这个问题,就像所有事情一样,你的里程可能会有所不同。

class FixUnicodeCrap < ActiveRecord::Migration
  def up
    r = ActiveRecord::Base.run_sql(<<sql
select TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, DATA_TYPE from INFORMATION_SCHEMA.COLUMNS 
    where TABLE_SCHEMA = database()
       and DATA_TYPE in ('varchar','text')
       and CHARACTER_SET_NAME = 'latin1'    
sql
)
    r.each do |row|
      target_type = 'BLOB'
      if row[5] == 'varchar'
        target_type = "VARBINARY(#{row[4]})"
      end
      null = row[3] == 'YES' ? "NULL" : "NOT NULL"
      if (row[0] != 'page_views') # if you need to skip any dbs, change this
        execute "ALTER TABLE #{row[0]} MODIFY #{row[1]} #{target_type};"
        execute "ALTER TABLE #{row[0]} MODIFY #{row[1]} #{row[2]} CHARACTER SET utf8 #{null};"
      end
    end
  end

  def down
  end
end


module EasySql
  def self.included(base)
    base.extend(Extensions)
  end

  module Extensions
    def run_sql(sql, *args) 
      connection.execute(
        sanitize_sql_array([sql] + args)
      )
    end
  end
end
ActiveRecord::Base.send :include, EasySql

I wrote a migration to fix this, as with all things, your mileage may vary.

class FixUnicodeCrap < ActiveRecord::Migration
  def up
    r = ActiveRecord::Base.run_sql(<<sql
select TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, DATA_TYPE from INFORMATION_SCHEMA.COLUMNS 
    where TABLE_SCHEMA = database()
       and DATA_TYPE in ('varchar','text')
       and CHARACTER_SET_NAME = 'latin1'    
sql
)
    r.each do |row|
      target_type = 'BLOB'
      if row[5] == 'varchar'
        target_type = "VARBINARY(#{row[4]})"
      end
      null = row[3] == 'YES' ? "NULL" : "NOT NULL"
      if (row[0] != 'page_views') # if you need to skip any dbs, change this
        execute "ALTER TABLE #{row[0]} MODIFY #{row[1]} #{target_type};"
        execute "ALTER TABLE #{row[0]} MODIFY #{row[1]} #{row[2]} CHARACTER SET utf8 #{null};"
      end
    end
  end

  def down
  end
end


module EasySql
  def self.included(base)
    base.extend(Extensions)
  end

  module Extensions
    def run_sql(sql, *args) 
      connection.execute(
        sanitize_sql_array([sql] + args)
      )
    end
  end
end
ActiveRecord::Base.send :include, EasySql
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文