2016-09-20 5 views
0

誤った照合順序(照合エラーの不正な組み合わせを引き起こしているように見える)のデータベーステーブルに複数の格納関数がある状況があります。私が読んだところでは、 "インプレース"の関数の照合順序を変更することはできません。それらを削除して再作成する必要があります。mysql:新しい照合を一括で行う関数を削除して再作成する

新しい照合順序を一括して削除して再作成する方法を探しています。つまり、既存の関数定義をDBから直接読み込み、照合順序を変更して再作成できる必要があります。私はプロセスの構成部分を知っていて、関数ごとにそれを行うことができますが、私はDB全体でこれを一括して行う有効な方法を考え出すのが難しいです。

答えて

1

次のスクリプトは、同時に彼らは、今SHOW CREATE FUNCTIONに類似しているとして、あなたは、データベース内のすべてのあなたの機能を再作成するためのスクリプトを生成するが、実際の結果セットなど、すべての機能のためになります。

select sql_stmt 
from (
    select p.db, p.name, p.type, 1 as intord, p.character_set_client, 
    concat('drop ',p.type, ' if exists ', p.db,'.`', p.name,'`;') as sql_stmt 
    from mysql.proc p 
    union all 
    select p.db, p.name, p.type, 2 as intord, p.character_set_client, 
    'delimiter $$' as sql_stmt 
    from mysql.proc p 
    union all 
    select p.db, p.name, p.type, 3 as intord, p.character_set_client, 
    concat('CREATE DEFINER=`',replace(p.definer,'@','`@`'),'` ', 
     p.type, 
     ' ',p.db,'.`',p.name, 
     '`(',convert(p.param_list USING utf8),') ', 
     case 
     when length(p.returns) > 1 
     then concat(' RETURNS ', convert(p.returns USING utf8)) 
     else '' 
     end, ' \n', 
     case 
     when p.is_deterministic = 'YES' then '\tDETERMINISTIC\n' 
     else '' 
     end, 
     case 
     when p.language = 'SQL' THEN '' 
     else concat('\tLANGUAGE ',p.language, '\n') 
     end, 
     case 
     when p.sql_data_access = 'CONTAINS_SQL' THEN '' 
     when p.sql_data_access = 'NO_SQL' THEN '\tNO SQL\n' 
     when p.sql_data_access = 'READS_SQL_DATA' THEN '\tREADS SQL DATA\n' 
     when p.sql_data_access = 'MODIFIES_SQL_DATA' THEN '\tMODIFIES SQL DATA\n' 
     else concat('\t',replace(p.sql_data_access,'_', ' '), '\n') 
     end, 
     case when p.security_type <> 'DEFINER' 
     then concat('\tSQL SECURITY ', p.security_type, '\n') 
     else '' 
     end, 
     case when p.comment <> '' 
     then concat('\tCOMMENT ''', 
      replace(replace(p.comment,'''',''''''),'\n','\\n') 
      ,'''') 
     else '' 
     end, '\n', 
     convert(p.body USING utf8), 
     '$$' 
    ) as sql_stmt 
    from mysql.proc p 
    union all 
    select p.db, p.name, p.type, 4 as intord, p.character_set_client, 
    'delimiter ;' as sql_stmt 
    from mysql.proc p 

) sql_stmts 
where db = <yourdbname> 
and type = 'function' 
and character_set_client = 'utf8' 
order by db, name, type, intord; 

結果は、あなたがbashのからコマンドラインクライアントを必要としているように見えるので、あなたがスクリプトを実行することができ、フォーム

drop function if exists a; 
delimiter $$ 
CREATE DEFINER=`root`@`127.0.0.1` FUNCTION yourdb.`a`(... 
delimiter ; 
drop function if exists b; 
delimiter $$ 
... 

になります例えば

mysql -u root -p -N -r <thisscript.sql> recreatefunctions.sql 

パラメータ-N-rであり、結果に表示されるヘッダを防ぐために、我々は実行可能なスクリプトとして直接結果を扱いたいので、'\n'\nの翻訳を防ぐためです。

実行するとします。ワークベンチでは、結果(Copy rows (unquoted))を新しいウィンドウにコピーしてください。

作成したスクリプトを必要に応じて編集したり、エディタで手作業で作成したり、スクリプトなどで自動的に編集することができます。 charset latin1charset utf8で置き換えてください。

また、上記のスクリプトでこれを行うこともできますが、これは簡単に行うことができます。調整しなければならないことを詳しく説明していませんが、たとえばutf8latin1から戻りパラメータの文字セットを変更したい、あなたはスクリプトを変更し、あなたが使用できるファイルを、編集した後、最終的にあなたの機能を更新するには

then concat(' RETURNS ', replace(convert(p.returns USING utf8),'latin1', 'utf8')) 

によって

then concat(' RETURNS ', convert(p.returns USING utf8)) 

を置き換えることができます

mysql -u root -p < recreatefunctions.sql 

スクリプトはコード(mysql.procテーブル内のブロブフィールドではなく、変更したい文字セットと仮定し)はutf8として保存されます。これは通常の場合ですが、予防策として、utf8という名前で保存された関数だけを読み込み(そして置き換えます)、他の場合でも機能するはずです。テーブルmysql.proc、列character_set_clientでこれを確認してください。 convert(p.param_list USING utf8))convert(p.returns USING utf8))convert(p.body USING utf8)を正しいエンコードで置き換えたり、複数のエンコードを使用している場合はcaseを使用したりすることができます。

ところで、これを試す前に、create functionは動的SQL文では使用できないため、mysql(ストアドプロシージャの動的SQL)内で完全に行うことはできません。

そして、それを試す前に、バックアップを作成してください!

+0

はい、show create関数を使用して関数を取得するのは、私が得る限りです。私はbashでスクリプトを作成しており、クエリ結果からcreate関数 "column"を抽出する簡単な方法はありません。それは最大の困難がどこにあるかのようです。 – lcdservices

+0

@lcdservices 'show create function'を必要としないバージョンを書きました。必要なコードを作成して、すべての機能を再作成し、必要に応じて変更することができます(または、必要に応じて変更をスクリプトに移すことができます)。 – Solarflare

+0

うわー - それは大きな助けです。ありがとう!私はいくつかのテストを今すぐ実行するつもりです。 – lcdservices

関連する問題