2016-06-20 4 views
0

Я импортировал таблицу csv в sql db, используя phpmyadmin. Я предполагаю, что формат по умолчанию десятичный (8,5), или, по крайней мере, так оно и есть. Кажется, избыток, и я думал, что могу уменьшить до 4,1. Проблема в том, что существует около 470 полей. Я знаю, как менять по одному, но это займет много времени. Есть ли более быстрый способ?изменить формат сразу нескольких столбцов базы данных

ответ

0

У меня только Sql Server 2008 R2, но похоже, что решение MySQL может быть похоже. Я попытался выровнять его как можно ближе к MySQL, но без механизма MySQL я не могу его проверить ... Итак, для чего это стоит, вот мой сценарий (протестирован на Sql Server):

-- I believe this is 'CREATE TEMPORARY TABLE' in MySql 
create table #tbl 
(
    ownerName sysname -- `sysname` is nvarchar(128) the max identifier length 
    , tableName sysname 
    , colName sysname 
    , colType sysname 
    , colPrecision int 
    , colScale int 
) 
insert #tbl 
select table_schema, table_name, column_name, data_type, numeric_precision, numeric_scale 
FROM information_schema.columns 
where data_type = 'decimal' and numeric_precision = 8 and numeric_scale = 5 

-- Note: It is 'MODIFY COLUMN' in MySQL 
declare @newPrecision int = 4, @newScale int = 1 
DECLARE @sql varchar(max) = '' 
select @sql = @sql + CHAR(13) + CHAR(10) + 'ALTER TABLE ' + ownerName + '.' + tableName + ' ALTER COLUMN ' 
    + colName + ' decimal(' + cast(@newPrecision as varchar(max)) + ',' + cast(@newScale as varchar(max)) + ')' 
from #tbl 
/** 
    -- In MySql, GROUP_CONCAT() may work 
    select @sql = GROUP_CONCAT('ALTER TABLE ' + ownerName + '.' + tableName + ' MODIFY COLUMN ' 
    + colName + ' decimal(' + cast(@newPrecision as varchar(max)) + ',' + cast(@newScale as varchar(max)) + ')' SEPARATOR ' ') 
    from #tbl 
**/ 

print @sql 
execute (@sql) 
0

Я никогда раньше не использовал SqlFiddle, поэтому подумал, что самое время начать, чтобы дать полный ответ специально для MySQL 5.6. См. http://sqlfiddle.com/#!9/19f46/1

В нижней части панели «Схема сборки» выберите «Разделитель = [//]. SqlFiddle использует это, чтобы решить, когда отправлять кусок кода в MySQL. Это необходимо, потому что ПРОЦЕДУРА СОЗДАНИЯ должна быть отправлена ​​как один кусок. Если вы используете разделитель по умолчанию = [; ], то он отправит только часть ПРОЦЕДУРЫ СОЗДАНИЯ до первого найденного ;.

В таблице cols выбираются столбцы типа decimal с точностью и масштабированием, которые вы хотите изменить. В настоящее время жестко запрограммированы как 8 и 5 по запросу ОП, но при необходимости изменяются, чтобы идентифицировать только те столбцы, которые вы хотите изменить. Было бы хорошей идеей, прежде чем выполнять изменения таблицы для запуска этого выбора, чтобы проверить, какие столбцы вы будете изменять.

Хранимая процедура exec_multiple использует таблицу cols для генерации операторов ALTER TABLE, которые затем динамически выполняются.

EXECUTE обрабатывает только одно заявление за раз, поэтому вам необходимо выполнить итерацию по строкам cols и применить каждый ALTER TABLE отдельно. Столбец auto_increment id в cols позволяет вам выбирать каждую строку поочередно без использования курсора.

В таблице test_log отображается любая отладочная информация, которую вы можете проверить после завершения сборки схемы.

На панели «Схема сборки» слева. Вся эта логика должна быть на этой панели, потому что SqlFiddle не позволяет использовать язык определения данных или инструкции вставки таблицы/обновления/удаления в панели «Запуск SQL».

create table if not exists cols 
(
    id int auto_increment primary key 
    , ownerName varchar(128) 
    , tblName varchar(128) 
    , colName varchar(128) 
    , colType varchar(128) 
    , colPrecision int 
    , colScale int 
) // 

create table if not exists test_table 
(
    testDecimal1 decimal(8,5) 
    , testDecimal2 decimal(8,5) 
) // 

create table if not exists test_table2 
(
    testDecimal3 decimal(8,5) 
    , testDecimal4 decimal(8,5) 
) // 

create table if not exists test_log 
(
    msg varchar(1024) 
) // 

INSERT INTO cols 
(ownerName, tblName, colName, colType, colPrecision, colScale) 
SELECT TABLE_SCHEMA, `TABLE_NAME`, COLUMN_NAME, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE DATA_TYPE = 'decimal' AND NUMERIC_PRECISION = 8 AND NUMERIC_SCALE = 5 // 

insert test_log(msg) select database() // 

CREATE PROCEDURE `exec_multiple` (newPrecision int, newScale int) 
BEGIN 
    declare n int; 
    declare nrows int; 
    declare sql_stmt varchar(1024); 
    set n = 1; 
    select count(*) from cols into nrows; 

    while n <= nrows do 

     select CONCAT('ALTER TABLE ' 
     , ownerName, '.', tblName, ' MODIFY COLUMN ' 
     , colName, ' decimal(', newPrecision, ',' 
     , newScale, ')') into sql_stmt from `cols` where id = n; 

     SET @sql_stmt := sql_stmt; -- not sure why this is necessary 

     insert test_log(msg) select @sql_stmt; 

     PREPARE dynamic_statement FROM @sql_stmt; 
     EXECUTE dynamic_statement; 
     DEALLOCATE PREPARE dynamic_statement; 

     set n = n + 1; 
    end while; 
END // 

call exec_multiple(4, 1) // 

Это идет на панели Run SQL на правой

select * from test_log; 

SELECT TABLE_SCHEMA, `TABLE_NAME`, COLUMN_NAME, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE DATA_TYPE = 'decimal' 
; 

select * from cols; 
+1

Ваша цитата: '- не знаю, почему это necessary' ... по 2 причинам: (1) вы не сделали сначала concat в пользовательскую переменную. (2) mysql исправлен прямо на той строке, на которую вы ссылались, что не нравится Локальные переменные, но любит переменные пользователя. – Drew

+0

@Drew - Я надеялся, что кто-то прокомментирует это! Это был мой первый скрипт MySql. Я хотел использовать только локальные переменные в сохраненном proc, но спасибо за подтверждение того, что в этом случае необходима пользовательская переменная. Основная логика похожа на Sql Server, однако для работы с переменной потребовалось некоторое время. –

+0

Да, и страницы руководства так фантастичны в этом тоже, верно ?! – Drew

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