MySqlのエラーメッセージ:
Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='
私は他のいくつかの投稿を見てきましたが、この問題を解決することができませんでした。影響を受ける部分はこれに似たものです。
CREATE TABLE users (
userID INT UNSIGNED NOT NULL AUTO_INCREMENT,
firstName VARCHAR(24) NOT NULL,
lastName VARCHAR(24) NOT NULL,
username VARCHAR(24) NOT NULL,
password VARCHAR(40) NOT NULL,
PRIMARY KEY (userid)
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE TABLE products (
productID INT UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(104) NOT NULL,
picturePath VARCHAR(104) NULL,
pictureThumb VARCHAR(104) NULL,
creationDate DATE NOT NULL,
closeDate DATE NULL,
deleteDate DATE NULL,
varPath VARCHAR(104) NULL,
isPublic TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
PRIMARY KEY (productID)
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE TABLE productUsers (
productID INT UNSIGNED NOT NULL,
userID INT UNSIGNED NOT NULL,
permission VARCHAR(16) NOT NULL,
PRIMARY KEY (productID,userID),
FOREIGN KEY (productID) REFERENCES products (productID) ON DELETE RESTRICT ON UPDATE NO ACTION,
FOREIGN KEY (userID) REFERENCES users (userID) ON DELETE RESTRICT ON UPDATE NO ACTION
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
私が使っているストアドプロシージャはこれです:
CREATE PROCEDURE updateProductUsers (IN rUsername VARCHAR(24),IN rProductID INT UNSIGNED,IN rPerm VARCHAR(16))
BEGIN
UPDATE productUsers
INNER JOIN users
ON productUsers.userID = users.userID
SET productUsers.permission = rPerm
WHERE users.username = rUsername
AND productUsers.productID = rProductID;
END
私はphpでテストしていましたが、SQLyogでも同じエラーが発生します。私はまたDB全体を再作成することをテストしましたが、ダメです。
任意の助けは大歓迎です。
4つの選択肢があります。
オプション1:入力変数にCOLLATE
を追加します。
SET @rUsername = ‘aname’ COLLATE utf8_unicode_ci; -- COLLATE added
CALL updateProductUsers(@rUsername, @rProductID, @rPerm);
オプション2:COLLATE
句にWHERE
を追加します。
CREATE PROCEDURE updateProductUsers(
IN rUsername VARCHAR(24),
IN rProductID INT UNSIGNED,
IN rPerm VARCHAR(16))
BEGIN
UPDATE productUsers
INNER JOIN users
ON productUsers.userID = users.userID
SET productUsers.permission = rPerm
WHERE users.username = rUsername COLLATE utf8_unicode_ci -- COLLATE added
AND productUsers.productID = rProductID;
END
オプション3:それをIN
パラメーター定義に追加します。
CREATE PROCEDURE updateProductUsers(
IN rUsername VARCHAR(24) COLLATE utf8_unicode_ci, -- COLLATE added
IN rProductID INT UNSIGNED,
IN rPerm VARCHAR(16))
BEGIN
UPDATE productUsers
INNER JOIN users
ON productUsers.userID = users.userID
SET productUsers.permission = rPerm
WHERE users.username = rUsername
AND productUsers.productID = rProductID;
END
オプション4:フィールド自体を変更します。
ALTER TABLE users CHARACTER SET utf8 COLLATE utf8_general_ci;
ストアドプロシージャパラメータの既定の照合順序はutf8_general_ci
であり、照合順序を混在させることはできません。
データをUnicode順にソートする必要がない限り、コードの変更が不要で、ソート速度が少し速くなるため、すべてのテーブルをutf8_general_ci
照合順序を使用するように変更することをお勧めします。
UPDATE:utf8mb4/utf8mb4_unicode_ciが優先文字セット/照合方法になりました。パフォーマンスの向上はごくわずかであるため、utf8_general_ciはお勧めできません。 https://stackoverflow.com/a/766996/1432614 を参照してください。
Utf8_unicode_ciとutf8_general_ciが競合している場合の「不正な照合順序の混在」エラーに対する回答の検索に半日費やしました。
データベースの一部の列が特に照合されていないことがわかりましたtf8_unicode_ci。 mysqlは暗黙的にこれらのカラムを照合したようですtf8_general_ci。
具体的には、 'SHOW CREATE TABLE table1'クエリを実行すると、次のような出力がありました。
| table1 | CREATE TABLE `table1` (
`id` int(11) NOT NULL,
`col1` varchar(4) CHARACTER SET utf8 NOT NULL,
`col2` int(11) NOT NULL,
PRIMARY KEY (`col1`,`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
行'col1' varchar(4)文字セットutf8 NOT NULLには照合順序が指定されていません。それから私は次のクエリを実行しました:
ALTER TABLE table1 CHANGE col1 col1 VARCHAR(4) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
これにより、「不正な照合順序の混在」エラーが解決されました。これが他の誰かに役立つかもしれないと思います。
私は同様の問題を抱えていました、しかし、私の問い合わせパラメータが変数を使用して設定されたとき、それはプロシージャの中で私に起こりました。 SET @value='foo'
。
これの原因はcollation_connection
とデータベースの照合順序の不一致でした。 collation_connection
をcollation_database
と一致するように変更し、問題は解決しました。これは、param/valueの後にCOLLATEを追加するよりも、もっとエレガントなアプローチだと思います。
要約すると、すべての照合順序が一致する必要があります。 SHOW VARIABLES
を使用して、collation_connection
とcollation_database
が一致していることを確認してください(SHOW TABLE STATUS [table_name]
を使用してテーブルの照合も確認してください)。
@bpileの回答と少し似ていますが、私のケースはmy.cnfエントリの設定collation-server = utf8_general_ci
でした。それに気付いた後(そして上記のすべてを試した後)、データベースをutf8_unicode_ciではなくutf8_general_ciに強制的に切り替えました。
ALTER DATABASE `db` CHARACTER SET utf8 COLLATE utf8_general_ci;
私自身の場合、私は以下のエラーがあります
操作 '='の照合順序(utf8_general_ci、IMPLICIT)と(utf8_unicode_ci、IMPLICIT)の組み合わせが不正です
$ this-> db-> select( "users.username of matric_no、CONCAT(users.surname、 ''、users.first_name、 ''、users.last_name)をフルネーム") - > join( 'users'、 'users .username = classroom_students.matric_no '、' left ') - > where(' classroom_students.session_id '、$ session) - > where(' classroom_students.level_id '、$レベル) - > where(' classroom_students.dept_id '、$ dept ;
何週間ものGoogle検索の後、私が比較している2つのフィールドが異なる照合名から構成されていることに気づきました。最初のもの、つまりusernameはutf8_general_ciで、2番目のものはutf8_unicode_ciです。そのため、2番目のテーブルの構造に戻り、2番目のフィールド(matric_no)をutf8_general_ciに変更しました。
これは、列が明示的に別の照合順序に設定されている場合、または照会された表でデフォルトの照合順序が異なる場合に発生します。
たくさんのテーブルがある場合は、このクエリを実行するときに照合順序を変更します。
select concat('ALTER TABLE ', t.table_name , ' CONVERT TO CHARACTER
SET utf8 COLLATE utf8_unicode_ci;') from (SELECT table_name FROM
information_schema.tables where table_schema='SCHRMA') t;
これは、列ごとに正しい照合順序を使用するようにすべてのテーブルを変換するために必要なクエリを出力します。
同じ問題について膨大な数の質問を見つけたにもかかわらず( 1 、 2 、、 4 )ここでも、パフォーマンスを考慮に入れた答えは見つかりませんでした。
複数の実用的な解決策がすでに与えられていますが、私は性能を考慮したいと思います。
編集:オプション1がパフォーマンスの問題に苦しんでいないことを指摘してくれたManataxに感謝します。
オプションを使用する 1と 2、別名COLLATEキャストアプローチは、潜在的なボトルネックにつながる可能性があり、列に定義されたインデックスは使用されません。フルスキャンを引き起こします。
私は試してみませんでしたがオプション3、私の口実はそれがオプションの同じ結果に苦しむということです 1と 2。
最後に、Option 4は、実行可能な場合、非常に大きなテーブルに最適なオプションです。元の照合順序に依存する他の使用法がないことを意味します。
この単純化されたクエリを考えます:
SELECT
*
FROM
schema1.table1 AS T1
LEFT JOIN
schema2.table2 AS T2 ON T2.CUI = T1.CUI
WHERE
T1.cui IN ('C0271662' , 'C2919021')
;
私の最初の例では、もっとたくさんの結合がありました。もちろん、table1とtable2は異なる照合順序を持ちます。 照合演算子を使用してキャストすると、インデックスが使用されなくなります。
下の図のSQLの説明を参照してください。
一方、オプション4は可能なインデックスを利用することができ、高速なクエリを可能にします。
下の図では、スキーマ/テーブル/列の照合順序を変更して、適用されたオプション4の後に同じクエリが実行されています。
照合が変更された後、したがって照合キャストなしのビジュアルクエリの説明
結論として、パフォーマンスが重要でテーブルの照合順序を変更できる場合は、オプション4に進みます。単一の列に作用しなければならない場合は、次のようなものを使用できます。
ALTER TABLE schema1.table1 MODIFY `field` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;