sql >> Databáze >  >> RDS >> Mysql

MySQL Nelegální mix porovnávání

Je užitečné porozumět následujícím definicím:

  • Kódování znaků podrobně popisuje, jak je každý symbol reprezentován binárně (a tedy uložen v počítači). Například symbol é (U+00E9, latinské malé písmeno E s akutním) je kódováno jako 0xc3a9 v UTF-8 (které MySQL nazývá utf8 ) a 0xe9 v Windows-1252 (které MySQL nazývá latin1 ).

  • sadu znaků je abeceda symbolů, které lze znázornit pomocí daného kódování znaků. Je matoucí, že tento termín je také používán ve významu stejně jako kódování znaků.

  • Posouzení je řazení na znakové sadě, takže řetězce lze porovnávat. Například:latin1_swedish_ci MySQL Collation považuje většinu variací znaku s diakritikou za ekvivalent k základnímu znaku, zatímco jeho latin1_general_ci řazení je seřadí před dalším základním znakem, ale ne ekvivalentní (existují i ​​další, významnější rozdíly:například pořadí znaků jako å , ä , ö a ß ).

MySQL rozhodne, které řazení se má použít na daný výraz, jak je zdokumentováno v Porovnání výrazů :konkrétně řazení sloupce má přednost před řetězcovým literálem.

WHERE klauzule vašeho dotazu porovnává následující řetězce:

  1. hodnotu v fos_user.username , zakódovaný ve znakové sadě sloupce (Windows-1252) a vyjadřující preference pro jeho řazení latin1_swedish_ci (s hodnotou koercibility 2); s

  2. řetězcový literál 'Nrv⧧Kasi' , zakódované ve znakové sadě připojení (UTF-8, jak je nakonfigurováno Doctrine) a vyjadřující preferenci pro řazení připojení utf8_general_ci (s hodnotou koercibility 4).

Vzhledem k tomu, že první z těchto řetězců má nižší hodnotu koercibility než druhý, MySQL se pokusí provést porovnání pomocí řazení tohoto řetězce:latin1_swedish_ci . Za tímto účelem se MySQL pokusí převést druhý řetězec na latin1 —ale protože znak v této znakové sadě neexistuje, porovnání se nezdaří.

Upozornění

Měli bychom se na chvíli zastavit a zvážit, jak je sloupec aktuálně kódován:pokoušíte se filtrovat záznamy, kde fos_user.username se rovná řetězci, který obsahuje znak, který nemůže existují v tomto sloupci !

Pokud se domníváte, že sloupec ano obsahovat takové znaky, pak jste pravděpodobně psali do sloupce, když bylo kódování znaků připojení na něco nastaveno (např. latin1 ), což způsobilo, že MySQL interpretuje přijatou sekvenci bajtů jako znaky, které jsou všechny ve znakové sadě Windows-1252.

V takovém případě byste měli před dalším pokračováním opravit svá data!

  1. převeďte takové sloupce na kódování znaků, které bylo použito při vkládání dat, pokud se liší od stávajícího kódování:

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET foo;
    
  2. zahoďte informace o kódování spojené s takovými sloupci jejich převedením na binary znaková sada:

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET binary;
    
  3. přiřadit k takovým sloupcům kódování, ve kterém byla data skutečně přenášena, jejich převodem na příslušnou znakovou sadu.

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET bar;
    

Všimněte si, že při převodu z vícebajtového kódování může být nutné zvětšit velikost sloupce (nebo dokonce změnit jeho typ), aby se přizpůsobila maximální možné délce převedeného řetězce.

Jakmile se ujistíte, že jsou sloupce správně zakódovány, můžete vynutit provedení porovnání pomocí řazení Unicode buď –

  • explicitně převede hodnotu fos_user.username na znakovou sadu Unicode:

    WHERE CONVERT(fos_user.username USING utf8) = ?
    
  • vynucení, aby měl řetězcový literál nižší hodnotu koercibility než sloupec (způsobí implicitní převod hodnoty sloupce na UTF-8):

    WHERE fos_user.username = ? COLLATE utf8_general_ci
    

Nebo by se dalo, jak říkáte, trvale převést sloupec(y) do kódování Unicode a vhodně nastavit jeho řazení.

Principem je, že kódování Unicode zabírá více místa než jednobajtové znakové sady, takže:

  • může být vyžadováno více úložiště;

  • srovnávání může být pomalejší; a

  • Délky předpon indexu může být nutné upravit (všimněte si, že maximum je v bajtech, takže může představovat méně znaků než dříve).

Mějte také na paměti, že jak je zdokumentováno v části ALTER TABLE Syntaxe :



  1. dotaz mysql pro aktualizaci pole na max(pole) + 1

  2. Soubor výpisu jádra a přidání kódů ladění do aplikace spustitelné pro Oracle Apps

  3. zahrnout třídu Jfactory do externího souboru php, Joomla

  4. MySQL:více tabulek nebo jedna tabulka s mnoha sloupci?