2016-09-20 1 views
0

У меня есть ситуация, когда у меня есть несколько хранимых функций по таблицам базы данных, которые имеют неправильную сортировку (и, кажется, запускают незаконное смешивание ошибок сопоставления). Из того, что я прочитал, вы не можете изменить сортировку для функций «на месте» - вы должны сбросить и воссоздать их.mysql: отбрасывать и воссоздавать функции с новой сортировкой навалом

Я ищу способ сбросить и воссоздать с новой сортировкой навалом. Это означает, что мне нужно иметь возможность «читать» существующие определения функций непосредственно из БД, изменять сортировку и воссоздавать ее. Хотя я знаю составные части процесса и могу делать это по принципу «за собой», мне трудно понять эффективный способ сделать это навалом - по всей БД.

ответ

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; 

Результат будет в виде

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 latin1 на charset utf8 или все, что вам нужно.

Возможно, вы также можете сделать это в приведенном выше скрипте, это может быть проще сделать. Вы не определились с тем, что нужно отрегулировать, но если вы, например, Чтобы изменить кодировку возвращаемого параметра из latin1 в utf8, вы можете изменить сценарий и заменить

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

по

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

Чтобы, наконец, обновить свои функции после того, как вы отредактировали файл, вы можете использовать

mysql -u root -p < recreatefunctions.sql 

сценарий предполагает, что код (BLOB-поля в mysql.proc таблице, а не набор символов вы хотите чан e) сохраняется как utf8. Обычно это происходит, но в качестве меры предосторожности он только считывает (и заменяет) функции, которые сохраняются как utf8, хотя он должен работать и в других случаях. Вы должны это проверить в таблице mysql.proc, колонка character_set_client. Вы можете заменить convert(p.param_list USING utf8)), convert(p.returns USING utf8)) и convert(p.body USING utf8) правильной кодировкой или, если у вас есть несколько кодировок, используйте заявку case.

Кстати, перед тем, как вы это попробуете, это невозможно сделать полностью внутри mysql (динамический sql в хранимой процедуре), потому что create function не разрешен в динамическом SQL-заявлении.

И, кстати, перед тем, как попробовать, сделайте резервную копию!

+0

Да, получение функции через функцию создания шоу до тех пор, пока я не получил. Я пишу скрипт в bash, и нет простого способа извлечь функцию «столбец» из результатов запроса. Кажется, это самая трудная проблема. – lcdservices

+0

@lcdservices Я написал версию, которая не требует 'show create function'. Он создаст требуемый код для воссоздания всех ваших функций, которые затем вы сможете модифицировать в соответствии с вашими потребностями (или пусть уже сценарий изменится в зависимости от ваших требований - вы не объяснили, что именно вам нужно изменить). – Solarflare

+0

Вау - это огромная помощь. благодаря! Сейчас я проведу некоторые тесты. – lcdservices

Смежные вопросы