'=' İşlemi için geçersiz harmanlama karışımı (utf8_unicode_ci, IMPLICIT) ve (utf8_general_ci, IMPLICIT)


161

MySql'de hata mesajı:

Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='

Başka gönderilerden geçtim ve bu sorunu çözemedim. Etkilenen kısım buna benzer bir şeydir:

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;

Kullandığım saklı yordam şudur:

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

Ben php ile test edildi, ama aynı hata SQLyog ile verilir. Ayrıca tüm DB yeniden yaratma test ettim ama iyi değil.

Herhangi bir yardım çok takdir edilecektir.

Yanıtlar:


221

Saklı yordam parametreleri için varsayılan harmanlamadır utf8_general_cive harmanlamaları karıştıramazsınız, bu nedenle dört seçeneğiniz vardır:

1.Seçenek : COLLATEGiriş değişkeninize ekleyin :

SET @rUsername = aname COLLATE utf8_unicode_ci; -- COLLATE added
CALL updateProductUsers(@rUsername, @rProductID, @rPerm);

2. Seçenek : eklenti COLLATEiçin WHEREfıkra:

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

Seçenek 3 : INParametre tanımına ekleyin :

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

Seçenek 4 : Alanın kendisini değiştirin:

ALTER TABLE users CHARACTER SET utf8 COLLATE utf8_general_ci;

Verileri Unicode düzeninde sıralamanız gerekmedikçe utf8_general_ci, kod değişikliği gerektirmediğinden ve sıralamayı biraz hızlandıracağı için tüm tablolarınızı harmanlamayı kullanmak için değiştirmenizi öneririm .

GÜNCELLEME : utf8mb4 / utf8mb4_unicode_ci artık tercih edilen karakter seti / harmanlama yöntemidir. Performans iyileştirme ihmal edilebilir olduğundan utf8_general_ci'ye karşı tavsiye edilir. Bkz. Https://stackoverflow.com/a/766996/1432614


1
O eklemek de mümkündür COLLATE utf8_unicode_cidize sabitleri için: SET @EMAIL = 'abc@def.com' COLLATE utf8_unicode_ci;. Konsoldan bir komut dosyası çalıştırıyorsanız, konsol varsayılan kodlamasının dize sabitlerinizin harmanlaması için geçerli olduğu durumlarda özellikle kullanışlıdır.
gaborsch

Veya veritabanını bırakın ve utf8_general_ci ile yeni oluşturun; harmanlama.
Oleksii Kyslytsyn

2
İleride başvurmak için, iki harmanlama arasındaki farkları anlamadığınız sürece tüm tablolarınızı utf8_general_ci olarak değiştirmeyin.
Manatax

1
@GaborSch Dize değişkenlerine harmanlama eklemek benim için bir çözümdü, yorumunuzu fark etmeden önce bu konuda ayrıntılı bir cevap yazdım.
nkatsar

im (utf8mb4_unicode_ci, IMPLICIT)yerine aynı hatayı alıyorum (utf8_unicode_ci, IMPLICIT). ben python kullanarak web kapalı veri kazıma, sonra daha sonra veri veritabanına veri yükleyen sunucumda bir PHP dosyası ile işlenmiş verileri ile bir CSV dosyası oluşturma. tüm MySQL tablolarım / sütunlarım olarak sıralanıyor utf8mb4_unicode_ci. veri utf8python / csv gibi kodlamak çünkü sorun ortaya çıkabilir ?
oldboy

28

Yarım gün, utf8_unicode_ci ve utf8_general_ci arasındaki çakışmalarla özdeş "Harmanlama harmanlamaları karışımı" hatasına yanıt aramak için geçirdim.

Veritabanımdaki bazı sütunların utf8_unicode_ci özel olarak harmanlanmadığını fark ettim . Görünüşe göre mysql bu sütunları utf8_general_ci örtük olarak derledi .

Özellikle, 'SHOW CREATE TABLE table1' sorgusu çalıştırıldığında aşağıdaki gibi bir çıktı çıktı:

| 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 |

Hat Not 'col1' varchar (4) KARAKTER SETİ utf8 DEĞİL BOŞ belirtilen bir harmanlama sahip değil. Sonra aşağıdaki sorguyu koştu:

ALTER TABLE table1 CHANGE col1 col1 VARCHAR(4) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;

Bu, "Yasadışı harmanlama karışımı" hatasını çözdü. Umarım bu başka birine yardımcı olabilir.


7
Teşekkürler. 'NASIL OLUŞTUR TABLOSU' sorunun temel nedenini anlamanın ve düzeltmenin en kolay yoludur.
joro

2
Ayrıca COLLATE, tüm tablo için (yani ALTER TABLE table1 CHARSET utf8 COLLATE utf8_unicode_ci) belirtmenin sorunu çözmeyeceğini , her (sorunlu) sütun için yapılması gerektiğini unutmayın.
Skippy le Grand Gourou

6

Ben benzer bir sorun vardı, ama benim sorgu parametresi örneğin kullanılarak ayarlandığında, prosedür içinde bana meydana geldi SET @value='foo'.

Buna neden olan uyumsuzluk collation_connectionve Veritabanı harmanlamasıydı. collation_connectionMaç değişti collation_databaseve sorun ortadan kalktı. Bu parametrenin / değerden sonra COLLATE eklemekten daha zarif bir yaklaşım olduğunu düşünüyorum.

Özetle: tüm harmanlamalar eşleşmelidir. Kullanın SHOW VARIABLESve emin olun collation_connectionve collation_databaseeşleştirin (ayrıca tablo harmanlamasını kullanarak kontrol edin SHOW TABLE STATUS [table_name]).


1
Bana da aynı sorun oldu, harmanlamayı doğrudan değişken bildiriminde ayarlayarak collation_YYY değişkenlerini değiştirmekten kaçındım. SET @my_var = 'string1,string2' COLLATE utf8_unicode_ci;
nkatsar

5

@ Bpile yanıtı biraz benzer, benim durumum bir my.cnf giriş ayarı oldu collation-server = utf8_general_ci. Bunu fark ettikten sonra (ve yukarıdaki her şeyi denedikten sonra), veritabanımı zorla utf8_unicode_ci yerine utf8_general_ci'ye değiştirdim ve hepsi bu oldu:

ALTER DATABASE `db` CHARACTER SET utf8 COLLATE utf8_general_ci;

1
Konfigürasyonların çok fazla yayılması garip. Tüm harmanlama varsayılanları aynı yerde ayarlanmalıdır.
Manatax

0

Kendi durumumda aşağıdaki hata var

'=' İşlemi için geçersiz harmanlama karışımı (utf8_general_ci, IMPLICIT) ve (utf8_unicode_ci, IMPLICIT)

$ this-> db-> select ("matric_no olarak users.username, CONCAT (users.surname, '', users.first_name, '', users.last_name) tam ad olarak") -> katıl ('users', 'users .username = classroom_students.matric_no ',' sol ') -> nerede (' classroom_students.session_id ', $ oturum) -> nerede (' classroom_students.level_id ', $ seviye) -> nerede (' classroom_students.dept_id ', $ borç) );

Google'da arama yapmanın haftalarından sonra, karşılaştırdığım iki alanın farklı harmanlama adından oluştuğunu fark ettim. Birincisi yani kullanıcı adı utf8_general_ci, ikincisi utf8_unicode_ci iken ikinci tablonun yapısına geri döndüm ve ikinci alanı (matric_no) utf8_general_ci olarak değiştirdim ve bir cazibe gibi çalıştı.


0

Aynı sorun hakkında çok sayıda soru bulmasına rağmen ( 1 , 2 , 3 , 4 ) Performansı dikkate alan bir cevap bile bulamadım, burada bile.

Birden çok çalışma çözümü verilmiş olmasına rağmen performans değerlendirmesi yapmak istiyorum.

DÜZENLEME: Manatax'a seçenek 1'in performans sorunları yaşamayacağına işaret ettiği için teşekkürler.

Kullanılması Seçenek 1 ve 2 , nam HARMANLA sütun üzerinde tanımlı herhangi endeksi neden kullanılmayacaktır neden döküm yaklaşımı, potansiyel darboğaz yol açabilir tam tarama .

Seçenek 3'ü denememe rağmen önsezim, seçenek 1 ve 2'nin aynı sonuçlarına maruz kalacağıdır .

Son olarak, Seçenek 4 , uygulanabilir olduğunda çok büyük tablolar için en iyi seçenektir. Yani orijinal harmanlamaya dayanan başka bir kullanım yok.

Bu basitleştirilmiş sorguyu düşünün:

SELECT 
    *
FROM
    schema1.table1 AS T1
        LEFT JOIN
    schema2.table2 AS T2 ON T2.CUI = T1.CUI
WHERE
    T1.cui IN ('C0271662' , 'C2919021')
;

Orijinal örneğimde, çok daha fazla birleşim vardı. Tabii ki, tablo1 ve tablo2 farklı harmanlamalara sahiptir. Yayınlamak için harmanlama işlecini kullanmak, dizinlerin kullanılmamasına neden olur.

Aşağıdaki resimde sql açıklamasına bakınız.

COLLATE dökümünü kullanırken Görsel Sorgu Açıklaması

Öte yandan, seçenek 4 olası endeksten faydalanabilir ve hızlı sorgulara yol açabilir.

Aşağıdaki resimde, aynı sorgunun Şema / tablo / sütun harmanlamasını değiştirerek, Seçenek 4 uygulandıktan sonra çalıştırıldığını görebilirsiniz .

Harmanlama değiştirildikten sonra ve bu nedenle harmanlama dökümü yapılmadan Görsel Sorgu Açıklaması

Sonuç olarak, performans önemliyse ve tablonun harmanlamasını değiştirebiliyorsanız, Seçenek 4'e geçin . Tek bir sütun üzerinde işlem yapmanız gerekiyorsa, şöyle bir şey kullanabilirsiniz:

ALTER TABLE schema1.table1 MODIFY `field` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Katkınız için teşekkür ederiz Raffaele, ancak 1 seçeneğini indeks kullanacağına inanıyorum, çünkü tabloyu dökmüyorsunuz, ancak SP'ye geçmeden önce karşılaştırma değeri.
Manatax

Bunu işaret ettiğiniz için teşekkürler. Benim hatamdı. Cevabımı buna göre düzenledim.
Raffaele

0

Bu, bir sütunun açıkça farklı bir harmanlamaya ayarlandığı veya sorgulanan tabloda varsayılan harmanlamanın farklı olduğu durumlarda oluşur.

harmanlamayı değiştirmek istediğiniz birçok tablonuz varsa bu sorguyu çalıştırın:

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;

sütun başına doğru harmanlamayı kullanmak için tüm tabloları dönüştürmek için gereken sorguların çıktısını alır


SP için varsayılan harmanlamanız sorgulanan tablo için kullanılan harmanlamadan farklı olduğunda da (benim durumumda olduğu gibi) olur.
Manatax
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.