运行rails测试套件时,MySql中出现"非法混合排序"错误

use*_*651 6 mysql ruby-on-rails collation

我最近拂去了我的一个旧的Ruby on Rails项目.在过去,我从来没有遇到任何问题通过所有测试,但现在有一个测试,给我以下错误:

ActiveRecord :: StatementInvalid:Mysql :: Error:#HY000非法混合排序(latin1_swedish_ci,IMPLICIT)和(utf8_general_ci,COERCIBLE)操作'=':SELECT*FROM cards WHERE(cards.l1_description ='是'AND cards.l2_word = '')

所以我去我的测试数据库并询问:

mysql> use flashcard_test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show full columns from cards;
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+
| Field          | Type         | Collation         | Null | Key | Default | Extra          | Privileges                      | Comment |
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+
| id             | int(11)      | NULL              | NO   | PRI | NULL    | auto_increment | select,insert,update,references |         |
| l2_word        | varchar(255) | latin1_swedish_ci | YES  |     | NULL    |                | select,insert,update,references |         |
| l1_description | text         | latin1_swedish_ci | YES  |     | NULL    |                | select,insert,update,references |         |
| l1_id          | int(11)      | NULL              | YES  |     | NULL    |                | select,insert,update,references |         |
| l2_id          | int(11)      | NULL              | YES  |     | NULL    |                | select,insert,update,references |         |
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+
5 rows in set (0.01 sec)
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,整理是latin1_swedish_ci,大概如果是"utf8_general_ci",我的问题就会得到解决.值得庆幸的是,我的开发数据库已经没问题,所以我去了

rake db:test:clone_structure
Run Code Online (Sandbox Code Playgroud)

并返回到MySql并再次检查测试数据库

mysql> show full columns from cards;
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| Field          | Type         | Collation       | Null | Key | Default | Extra          | Privileges                      | Comment |
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| id             | int(11)      | NULL            | NO   | PRI | NULL    | auto_increment | select,insert,update,references |         |
| l2_word        | varchar(255) | utf8_general_ci | YES  |     | NULL    |                | select,insert,update,references |         |
| l1_description | text         | utf8_general_ci | YES  |     | NULL    |                | select,insert,update,references |         |
| l1_id          | int(11)      | NULL            | YES  |     | NULL    |                | select,insert,update,references |         |
| l2_id          | int(11)      | NULL            | YES  |     | NULL    |                | select,insert,update,references |         |
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
5 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

啊,所以现在一切都很好看,所以我再一次

rake test
Run Code Online (Sandbox Code Playgroud)

但是我再次遇到同样的问题,当我检查我的测试数据库时,我发现整理列已经重置为latin1_swedish_ci.

我不太清楚rake测试是如何工作的,但我的工作假设是它使用schema.rb重新创建数据库.现在,在我的一次迁移中,我得到了

 class CreateCards < ActiveRecord::Migration
   def self.up
     create_table :cards, :options => "DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci"  do |t|
       t.column :english_word, :string
       t.column :chinese_description, :text
     end
   end

   def self.down
     drop_table :cards
   end
 end
Run Code Online (Sandbox Code Playgroud)

这显然已经解决了那里的整理问题.(我有另一个迁移,分别将english_word和chinese_description重命名为l2_word和l1_description.)但是这些信息还没有成为schema.rb.不知何故,显然,MySql决定假设我想要latin1_swedish_ci.

因此,总而言之,我认为我需要做的是以某种方式编辑某些东西,以便我将使用utf8_general_ci整理,然后我的问题就会消失(对吧?).但我无法弄清楚如何在"rake test"执行此操作时生成运行的代码.有人可以帮忙吗?

对于它的价值,测试和开发数据库都被创建为

create database flashcard_test default character set utf8 default collate utf8_general_ci;
Run Code Online (Sandbox Code Playgroud)

create database flashcard_development default character set utf8 default collate utf8_general_ci;
Run Code Online (Sandbox Code Playgroud)

而我的database.yml有

development:
  adapter: mysql
  database: flashcard_development
  username: root
  password: 
  encoding: utf8

test:
  adapter: mysql
  database: flashcard_test
  username: root
  password: 
  encoding: utf8
  collation: utf8_general_ci
Run Code Online (Sandbox Code Playgroud)

http://nhw.pl/wp/2008/09/16/mysql-collat​​e-setting-in-rails-application似乎暗示这个问题与RoR和MySql之间的连接有关,但我还没有对那里的建议有任何好运.

Sv1*_*Sv1 5

将collat​​ion:utf8_general_ci添加到您已经完成的database.yml文件应该可以解决问题.尝试使用"rake RAILS_ENV = test db:migrate:reset db:fixtures load"重新创建测试数据库 - 警告这将清除您在灯具之外的所有数据.

这对我有用.要验证是否可以执行以下操作来查看数据库,表和列的排序规则:

-- Database Collations:
SELECT schema_name,default_character_set_name,default_collation_name 
FROM information_schema.SCHEMATA 
WHERE schema_name not IN ('mysql');

-- Table Collations:
SELECT T.table_schema, T.table_name, T.TABLE_COLLATION, CCSA.CHARACTER_SET_NAME 
FROM information_schema.`TABLES` T,
 information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
WHERE CCSA.collation_name = T.table_collation
AND T.table_schema not IN ('mysql');

-- Column Collations:
SELECT table_schema, table_name, column_name, collation_name, character_set_name
FROM information_schema.`COLUMNS` C
WHERE C.table_schema not IN ('mysql')
ORDER BY 1,2,4;
Run Code Online (Sandbox Code Playgroud)

现在,测试数据库中的所有内容都应该具有database.yml中指定的排序规则.