답변:
내 가이드 MySQL 데이터베이스에서 전체 유니 코드를 지원하는 방법에서 데이터베이스, 테이블 또는 열의 문자 집합 및 데이터 정렬을 업데이트하기 위해 실행할 수있는 쿼리는 다음과 같습니다.
각 데이터베이스에 대해 :
ALTER DATABASE
database_name
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
각 테이블에 대해 :
ALTER TABLE
table_name
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
각 열에 대해 :
ALTER TABLE
table_name
CHANGE column_name column_name
VARCHAR(191)
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
(맹목적으로 복사하여 붙여 넣지 마십시오! 정확한 설명은 열 유형, 최대 길이 및 기타 속성에 따라 다릅니다. 위의 행은 VARCHAR
열의 예일뿐입니다 .)
완전히에서 변환을 자동화 할 수는 없습니다 utf8
에 utf8mb4
. 위에서 언급 한 가이드의 4 단계 에서 설명한대로 , 지정된 숫자 utf8mb4
가 대신 사용되는 경우 다른 의미를 가지므로 열 및 인덱스 키의 최대 길이를 확인해야합니다 utf8
.
MySQL 5.5 Reference Manual의 10.1.11 절에 이에 대한 자세한 정보가 있습니다.
몇 가지 명령을 실행하여 데이터베이스와 테이블을 변환하는 솔루션이 있습니다. 또한 유형의 모든 열을 변환 varchar
, text
, tinytext
, mediumtext
, longtext
, char
. 또한 문제 가 발생할 경우 데이터베이스 를 백업해야합니다 .
다음 코드를 preAlterTables.sql이라는 파일에 복사하십시오.
use information_schema;
SELECT concat("ALTER DATABASE `",table_schema,"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema, table_name;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type,"(",character_maximum_length,") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('varchar','char');
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type," CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('text','tinytext','mediumtext','longtext');
"yourDbName"의 모든 항목을 변환하려는 데이터베이스로 바꾸십시오. 그런 다음 다음을 실행하십시오.
mysql -uroot < preAlterTables.sql | egrep '^ALTER' > alterTables.sql
그러면 데이터베이스를 변환하는 데 필요한 모든 쿼리가 포함 된 새로운 alterTables.sql 파일이 생성됩니다. 다음 명령을 실행하여 변환을 시작하십시오.
mysql -uroot < alterTables.sql
table_schema의 조건을 변경하여 여러 데이터베이스를 통해 실행되도록 조정할 수도 있습니다. 예를 들어 table_schema like "wiki_%"
이름 접두어가있는 모든 데이터베이스를 변환합니다 wiki_
. 모든 데이터베이스를 변환하려면 조건을로 바꿉니다 table_type!='SYSTEM VIEW'
.
발생할 수있는 문제 mysql 키에 varchar (255) 열이 있습니다. 이로 인해 오류가 발생합니다.
ERROR 1071 (42000) at line 2229: Specified key was too long; max key length is 767 bytes
이 경우 varchar (150)과 같이 열을 더 작게 변경하고 명령을 다시 실행할 수 있습니다.
참고 :이 답변은 데이터베이스를 질문 utf8mb4_unicode_ci
대신에 로 변환합니다 utf8mb4_bin
. 그러나 간단히 이것을 바꿀 수 있습니다.
다음 쉘 스크립트를 사용했습니다. 데이터베이스 이름을 매개 변수로 사용하고 모든 테이블을 다른 문자 세트 및 데이터 정렬로 변환합니다 (스크립트에 정의 된 다른 매개 변수 또는 기본값으로 제공됨).
#!/bin/bash
# mycollate.sh <database> [<charset> <collation>]
# changes MySQL/MariaDB charset and collation for one database - all tables and
# all columns in all tables
DB="$1"
CHARSET="$2"
COLL="$3"
[ -n "$DB" ] || exit 1
[ -n "$CHARSET" ] || CHARSET="utf8mb4"
[ -n "$COLL" ] || COLL="utf8mb4_general_ci"
echo $DB
echo "ALTER DATABASE \`$DB\` CHARACTER SET $CHARSET COLLATE $COLL;" | mysql
echo "USE \`$DB\`; SHOW TABLES;" | mysql -s | (
while read TABLE; do
echo $DB.$TABLE
echo "ALTER TABLE \`$TABLE\` CONVERT TO CHARACTER SET $CHARSET COLLATE $COLL;" | mysql $DB
done
)
이 상황에 부딪쳤다; 데이터베이스를 변환하는 데 사용한 접근 방식은 다음과 같습니다.
먼저 my.cnf
기본 데이터베이스 연결 (응용 프로그램과 MYSQL 간)을 utf8mb4_unicode_ci와 호환 되도록 편집해야 합니다. 이모 지와 같은 문자가 없으면 앱에서 제출 한 유사한 문자가 올바른 바이트 / 인코딩으로 테이블에 표시되지 않습니다 (응용 프로그램의 DB CNN 매개 변수가 utf8mb4 연결을 지정하지 않는 한).
다음 SQL을 실행하십시오 (개별 열을 변경하기 위해 SQL을 준비 할 필요가 없으므로 ALTER TABLE
명령문이 그렇게합니다).
아래 코드를 실행하기 전에 "DbName"을 실제 DB 이름으로 바꾸십시오.
USE information_schema;
SELECT concat("ALTER DATABASE `",table_schema,
"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") as _sql
FROM `TABLES`
WHERE table_schema like "DbName"
GROUP BY table_schema;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,
"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as _sql
FROM `TABLES`
WHERE table_schema like "DbName"
GROUP BY table_schema, table_name;
위의 SQL 출력을 도트 SQL 파일로 수집하여 저장 한 후 실행하십시오.
#1071 - Specified key was too long; max key length is 1000 bytes.
문제가있는 테이블 이름과 같은 오류가 발생 하면 MB4 문자열로 변환되어야하는 해당 테이블의 일부 열에 대한 인덱스 키가 매우 커 Varvar 열이 <= 250이어야합니다. 인덱스 키는 최대 1000 바이트입니다. 인덱스가있는 열을 확인하고 그 중 하나가 varchar> 250 (대부분 255)이면
1 단계 : 해당 열의 데이터를 확인하여 해당 열의 최대 문자열 크기가 <= 250인지 확인하십시오.
쿼리 예 :
select `id`,`username`, `email`,
length(`username`) as l1,
char_length(`username`) as l2,
length(`email`) as l3,
char_length(`email`) as l4
from jos_users
order by l4 Desc;
2 단계 : 인덱싱 된 열 데이터의 최대 문자 길이가 250보다 작 으면 col 길이를 250으로 변경하십시오. 불가능한 경우 해당 열에서 인덱스를 제거하십시오.
3 단계 : 그런 다음 해당 테이블에 대한 테이블 변경 쿼리를 다시 실행하면 테이블이 utf8mb4로 변환됩니다.
건배!
나는이 가이드를 썼습니다 : http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4
직장에서 ALTER 데이터베이스와 테이블이 충분하지 않다는 것을 알았습니다. 나는 각 테이블로 가서 각 text / mediumtext / varchar 열을 변경해야했습니다.
운 좋게도 MySQL 데이터베이스의 메타 데이터를 감지하는 스크립트를 작성하여 테이블과 열을 반복하여 자동으로 변경했습니다.
MySQL 5.6의 긴 인덱스 :
수행 할 DBA / SUPER USER 권한이 있어야합니다. 데이터베이스 매개 변수 설정 :
innodb_large_prefix : ON innodb_file_format : 바라쿠다 innodb_file_format_max : 바라쿠다
이 질문에 대한 답변에는 위의 매개 변수를 설정하는 방법이 있습니다 : https : //.com/questions/35847015/mysql-change-innodb-large-prefix
물론, 내 기사에는 그렇게하는 지침도 있습니다.
MySQL 버전 5.7 이상 에서는 innodb_large_prefix가 기본적으로 ON이고 innodb_file_format도 기본적으로 바라쿠다입니다.
이 문제가있는 사람들에게 가장 좋은 해결책은이 표에 따라 먼저 열을 이진 유형으로 수정하는 것입니다.
그런 다음 열을 이전 유형과 원하는 문자 세트로 다시 수정하십시오.
예 :
ALTER TABLE [TABLE_SCHEMA].[TABLE_NAME] MODIFY [COLUMN_NAME] LONGBLOB;
ALTER TABLE [TABLE_SCHEMA].[TABLE_NAME] MODIFY [COLUMN_NAME] VARCHAR(140) CHARACTER SET utf8mb4;
나는 여러 latin1 테이블에서 시도했으며 모든 분음 부호를 유지했습니다.
이 작업을 수행하는 모든 열에 대해이 쿼리를 추출 할 수 있습니다.
SELECT
CONCAT('ALTER TABLE ', TABLE_SCHEMA,'.', TABLE_NAME,' MODIFY ', COLUMN_NAME,' VARBINARY;'),
CONCAT('ALTER TABLE ', TABLE_SCHEMA,'.', TABLE_NAME,' MODIFY ', COLUMN_NAME,' ', COLUMN_TYPE,' CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;')
FROM information_schema.columns
WHERE TABLE_SCHEMA IN ('[TABLE_SCHEMA]')
AND COLUMN_TYPE LIKE 'varchar%'
AND (COLLATION_NAME IS NOT NULL AND COLLATION_NAME NOT LIKE 'utf%');
나는 스크립트를 만들어 이 더 많거나 적은 자동으로 수행합니다
<?php
/**
* Requires php >= 5.5
*
* Use this script to convert utf-8 data in utf-8 mysql tables stored via latin1 connection
* This is a PHP port from: https://gist.github.com/njvack/6113127
*
* BACKUP YOUR DATABASE BEFORE YOU RUN THIS SCRIPT!
*
* Once the script ran over your databases, change your database connection charset to utf8:
*
* $dsn = 'mysql:host=localhost;port=3306;charset=utf8';
*
* DON'T RUN THIS SCRIPT MORE THAN ONCE!
*
* @author hollodotme
*
* @author derclops since 2019-07-01
*
* I have taken the liberty to adapt this script to also do the following:
*
* - convert the database to utf8mb4
* - convert all tables to utf8mb4
* - actually then also convert the data to utf8mb4
*
*/
header('Content-Type: text/plain; charset=utf-8');
$dsn = 'mysql:host=localhost;port=3306;charset=utf8';
$user = 'root';
$password = 'root';
$options = [
\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY,
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET latin1",
];
$dbManager = new \PDO( $dsn, $user, $password, $options );
$databasesToConvert = [ 'database1',/** database3, ... */ ];
$typesToConvert = [ 'char', 'varchar', 'tinytext', 'mediumtext', 'text', 'longtext' ];
foreach ( $databasesToConvert as $database )
{
echo $database, ":\n";
echo str_repeat( '=', strlen( $database ) + 1 ), "\n";
$dbManager->exec( "USE `{$database}`" );
echo "converting database to correct locale too ... \n";
$dbManager->exec("ALTER DATABASE `{$database}` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci");
$tablesStatement = $dbManager->query( "SHOW TABLES" );
while ( ($table = $tablesStatement->fetchColumn()) )
{
echo "Table: {$table}:\n";
echo str_repeat( '-', strlen( $table ) + 8 ), "\n";
$columnsToConvert = [ ];
$columsStatement = $dbManager->query( "DESCRIBE `{$table}`" );
while ( ($tableInfo = $columsStatement->fetch( \PDO::FETCH_ASSOC )) )
{
$column = $tableInfo['Field'];
echo ' * ' . $column . ': ' . $tableInfo['Type'];
$type = preg_replace( "#\(\d+\)#", '', $tableInfo['Type'] );
if ( in_array( $type, $typesToConvert ) )
{
echo " => must be converted\n";
$columnsToConvert[] = $column;
}
else
{
echo " => not relevant\n";
}
}
//convert table also!!!
$convert = "ALTER TABLE `{$table}` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
echo "\n", $convert, "\n";
$dbManager->exec( $convert );
$databaseErrors = $dbManager->errorInfo();
if( !empty($databaseErrors[1]) ){
echo "\n !!!!!!!!!!!!!!!!! ERROR OCCURED ".print_r($databaseErrors, true)." \n";
exit;
}
if ( !empty($columnsToConvert) )
{
$converts = array_map(
function ( $column )
{
//return "`{$column}` = IFNULL(CONVERT(CAST(CONVERT(`{$column}` USING latin1) AS binary) USING utf8mb4),`{$column}`)";
return "`{$column}` = CONVERT(BINARY(CONVERT(`{$column}` USING latin1)) USING utf8mb4)";
},
$columnsToConvert
);
$query = "UPDATE IGNORE `{$table}` SET " . join( ', ', $converts );
//alternative
// UPDATE feedback SET reply = CONVERT(BINARY(CONVERT(reply USING latin1)) USING utf8mb4) WHERE feedback_id = 15015;
echo "\n", $query, "\n";
$dbManager->exec( $query );
$databaseErrors = $dbManager->errorInfo();
if( !empty($databaseErrors[1]) ){
echo "\n !!!!!!!!!!!!!!!!! ERROR OCCURED ".print_r($databaseErrors, true)." \n";
exit;
}
}
echo "\n--\n";
}
echo "\n";
}
mysql -uroot -pThatrootPassWord < alterTables.sql
작동합니다. 그리고 이미 언급했듯이 utf8mb4_bin은 nextcloud가 권장하는 것입니다.