Bir veritabanı boyunca KARAKTER SETİ (ve KOLEKSİYON) nasıl değiştirilir?


172

Önceki programcımız bir tabloda yanlış harmanlamayı ayarladı (Mysql). UTF8 olması gerektiği zaman Latin harmanlama ile kurdu ve şimdi sorunlarım var. Çince ve Japonya karakteri olan her kayıt ??? karakter.

Harmanlamayı değiştirmek ve karakterin ayrıntılarını geri almak mümkün mü?



Harmanlamanın '???' ile ne ilgisi var? karakter seti? Bunun karakter seti ile ilgisi olduğunu düşündüm.
peterchaula

Niyeti yansıtacak şekilde başlığı değiştiriyorum. Bir veritabanı için varsayılan harmanlamayı değiştirmek istenenden çok daha az.
Rick James

Yanıtlar:


367

veritabanı harmanlamasını değiştir:

ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8mb4_0900_ai_ci;

tablo harmanlamasını değiştir:

ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE utf8mb4_0900_ai_ci;

sütun harmanlamasını değiştir:

ALTER TABLE <table_name> MODIFY <column_name> VARCHAR(255) CHARACTER SET utf8 COLLATE utf8mb4_0900_ai_ci;

Parçalar ne utf8mb4_0900_ai_cianlama geliyor?

3 bytes -- utf8
4 bytes -- utf8mb4 (new)
v4.0 --   _unicode_
v5.20 --  _unicode_520_
v9.0 --   _0900_ (new)
_bin      -- just compare the bits; don't consider case folding, accents, etc
_ci       -- explicitly case insensitive (A=a) and implicitly accent insensitive (a=á)
_ai_ci    -- explicitly case insensitive and accent insensitive
_as (etc) -- accent-sensitive (etc)
_bin         -- simple, fast
_general_ci  -- fails to compare multiple letters; eg ss=ß, somewhat fast
...          -- slower
_0900_       -- (8.0) much faster because of a rewrite

Daha fazla bilgi:


5
Dikkat CHARACTER SET utf8varsayılan yapar utf8_general_ciama aynı zamanda böyle harmanlama tanımlayabilirsiniz ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8_unicode_ci;gerekirse
KCD

1
... ve denemenizi tavsiye ederimcreate table testit(a varchar(1)); show create table testit \G drop table testit;
KCD

2
Sadece ikincisinin harmanlamayı şu şekilde değiştireceğini belirtmek isterim utf8_general_ci; Eğer bunu değiştirmek isterseniz utf8_unicode_ci, dizme tanımlayabilirsiniz: ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;. @KCD'nin işaret ettiği gibi, bu, veritabanlarında olduğu gibi tablolarda da aynı şekilde çalışır.
Bilgelik

9
Tam utf8 desteği için aşağıdakileri yapmak daha iyidir ALTER DATABASE <database_name> CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci. Diğer iki ifade için de aynısını yapmalısınız.
Greeso

Gerçekten "ALTER TABLE <table_name> MODIFY <column_name> ..." kullanmanız gerekiyor mu? Dev.mysql.com/doc/refman/5.5/en/alter-table.html göre "ALTER TABLE <table_name> KARAKTER AYARINA DÖNÜŞ ..." de sütunları değiştiriyor mu? Ya da belki de kılavuzu doğru şekilde okumuyor / anlamıyorum.
hansfn

49

Heres nasıl tüm veritabanları / tabloları / sütunları değiştirmek için. Bu sorguları çalıştırdığınızda, şemanızın tamamını utf8'e dönüştürmek için gereken tüm sonraki sorguların çıktısını alırlar. Bu yardımcı olur umarım!

- DATABASE Varsayılan Harmanlamasını Değiştir

SELECT DISTINCT concat('ALTER DATABASE `', TABLE_SCHEMA, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.tables
where TABLE_SCHEMA like  'database_name';

- TABLO Harmanlama / Karakter Kümesini Değiştir

SELECT concat('ALTER TABLE `', TABLE_SCHEMA, '`.`', table_name, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.tables
where TABLE_SCHEMA like 'database_name';

- COLUMN Harmanlama / Karakter Kümesini Değiştir

SELECT concat('ALTER TABLE `', t1.TABLE_SCHEMA, '`.`', t1.table_name, '` MODIFY `', t1.column_name, '` ', t1.data_type , '(' , t1.CHARACTER_MAXIMUM_LENGTH , ')' , ' CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.columns t1
where t1.TABLE_SCHEMA like 'database_name' and t1.COLLATION_NAME = 'old_charset_name';

İyi. ! Aynı sorunu çözmeye çalıştığım yaklaşık bir saat. Bu 3 komutu kullanıyorum ve karakter setinin değiştiğini gördüm. Ama asıl sorun benim için kaldı. Doğrudan veritabanına yazdıysam her şey tarayıcımda iyi görünüyor. Ama web sitesi formundan bazı içerik eklediysem, veritabanındaki sonuç sadece ??????. Dikkate almam gereken bir şey var mı? Web uygulamam bir .NET MVC uygulaması.
Tchaps

Gelecekteki projeler için yararlı sorgulara kaydetme.
Manatax

Bazı otomatik düzenlemeler önerdiğim için bazı düzenlemeler önerdim. CHARACTER_MAXIMUM_LENGTH ile ilgili hala bir sorun var: Örneğin latin1_swedish_ci'den utf8_unicode_ci'ye geçtiğinizde orijinali çok yüksek olabilir.
Ruben

1
Bu mükemmel bir cevap. Üç yorum / soru var: 1) COLUMN kodunda neden "t1" kullanımı? Buna hiç bir ihtiyaç görmüyorum. 2) Neden sadece "t1.column_type" değil "t1.data_type, '(', t1.CHARACTER_MAXIMUM_LENGTH, ')'"? 3) Neden büyük harf ve küçük harf karışımı - TABLE_SCHEMA vs tablo_adı vb.?
hansfn

25

utf8Mysql'de karakter kümesinin gerçek UTF8 karakter kümesinin yalnızca bir alt kümesi olduğuna dikkat edin . Bir bayt depolama alanı kaydetmek için Mysql ekibi, tam dört bayt yerine UTF8 karakterlerinin yalnızca üç baytını depolamaya karar verdi. Bu, bazı doğu asya dili ve emojilerinin tam olarak desteklenmediği anlamına gelir. Tüm UTF8 karakterlerini depolayabildiğinizden emin olmak için utf8mb4veri türünü kullanın utf8mb4_binveya utf8mb4_general_ciMysql'de.


1
Şimdiye kadar utf8mb4_unicode_ciyerine kullanılması önerilir utf8mb4_general_ci. Bkz. Stackoverflow.com/questions/766809/… ve drupal.stackexchange.com/questions/166405/…
Robin van Baalen

6

David Whittaker ne gönderdi ekleyerek, tüm tablo ve sütunları değiştirecek her tablo dönüştürecek deyimi değiştiren bir sorgu oluşturduk. Koşmak iyi bir fikir olabilir

OTURUM AYARLA group_concat_max_len = 100000;

önce grup concat'ınızın burada görüldüğü gibi çok küçük sınırı aşmadığından emin olmak için .

     SELECT a.table_name, concat('ALTER TABLE ', a.table_schema, '.', a.table_name, ' DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci, ',
        group_concat(distinct(concat(' MODIFY ',  column_name, ' ', column_type, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ', if (is_nullable = 'NO', ' NOT', ''), ' NULL ',
        if (COLUMN_DEFAULT is not null, CONCAT(' DEFAULT \'', COLUMN_DEFAULT, '\''), ''), if (EXTRA != '', CONCAT(' ', EXTRA), '')))), ';') as alter_statement
    FROM information_schema.columns a
    INNER JOIN INFORMATION_SCHEMA.TABLES b ON a.TABLE_CATALOG = b.TABLE_CATALOG
        AND a.TABLE_SCHEMA = b.TABLE_SCHEMA
        AND a.TABLE_NAME = b.TABLE_NAME
        AND b.table_type != 'view'
    WHERE a.table_schema = ? and (collation_name = 'latin1_swedish_ci' or collation_name = 'utf8mb4_general_ci')
    GROUP BY table_name;

Burada önceki cevap arasındaki fark, ut8mb4 yerine utf8 kullanmak ve t1.CHARACTER_MAXIMUM_LENGTH ile t1.data_type kullanmak sayılar için çalışmadı. Ayrıca, bunlar ayrı ayrı değiştirilmesi gerekeceğinden, sorgum görünümleri hariç tutuyor.

Ben sadece bir dizi olarak tüm bu alters döndürmek için bir Perl betiği kullandım ve onlar üzerinde yinelenen, çok uzun olan sütunlar sabit (genellikle varchar (256) veri genellikle sadece 20 karakter vardı, bu yüzden kolay bir düzeltme oldu ).

Ben latin1 -> utf8mb4 değiştirirken bazı verilerin bozuk bulundu. Sütunlarda utf8 kodlu latin1 karakterlerinin dönüşümde bozulacağı görülüyordu. Sadece değiştirmeden önce ve sonra bellekte bir sorun olacağını bildiğim sütunlardan veri tuttum ve bunları karşılaştırdı ve verileri düzeltmek için güncelleme deyimleri oluşturdu.


4

burada süreci iyi açıklar. Ancak, latin uzayına uymayan bazı karakterler sonsuza dek yok oldu. UTF-8, latin1'in bir SUPERSET'idir. Tersi değil. Çoğu tek bayt boşluğa sığar, ancak tanımlanmamış olanlar sığmaz (latin1 listesini kontrol edin - mysql'nin latin1 tanımına bağlı olarak 256 karakterin tümü tanımlanmaz)

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.