2016-06-20 2 views
0

phpmyadmin을 사용하여 SQL DB에 CSV 테이블을 가져 왔습니다. 기본 형식은 10 진수 (8,5) 또는 적어도 그것이 나오는 방법입니다. 과잉 공격에 시달리고 나는 4,1로 줄일 수 있다고 생각했다. 문제는 약 470 개의 필드가 있다는 것입니다. 나는 한 번에 하나씩 바꾸는 방법을 안다. 그러나 이것은 오랜 시간이 걸릴 것이다. 더 빠른 방법이 있습니까?한 번에 여러 데이터베이스 열의 형식을 수정하십시오.

답변

0

SQL Server 2008 R2 만 있지만 SQL 솔루션과 비슷할 수 있습니다. 가능한 한 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에 코드 덩어리를 보내는시기를 결정합니다. CREATE PROCEDURE는 하나의 청크로 보내야하기 때문에 필요합니다. 기본 구분 기호 = [; ]를 선택하면 CREATE PROCEDURE의 일부만이 처음 발견되는 ;까지 전송됩니다.

cols은 변경할 정밀도와 눈금이있는 decimal 유형의 열을 선택합니다. 요청 된 OP로 현재 8 및 5로 하드 코드되어 있지만 수정하려는 열만 식별하는 데 필요한만큼 변경됩니다. 이 선택을 실행하여 수정할 열을 확인하기 위해 테이블 ​​수정을 수행하기 전에 좋습니다.

저장 프로 시저 exec_multiple은 테이블 cols을 사용하여 ALTER TABLE 문을 생성 한 다음 동적으로 실행합니다.

EXECUTE는 한 번에 하나의 명령문 만 처리하므로 cols 행을 반복하고 각 ALTER TABLE을 개별적으로 적용해야합니다. 의 auto_increment 열을 사용하면 커서를 사용하지 않고 차례로 각 행을 선택할 수 있습니다.

테이블 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) // 

은 오른쪽에있는 실행 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' ... 왜 확실하지 : (1) 당신이하지 않았다 처음에는 사용자 변수로 연결됩니다. (2) mysql은 로컬 변수를 좋아하지 않지만 사용자 변수를 좋아하는 참조 된 라인에서 매우 까다 롭습니다. – Drew

+0

@Drew - 누군가가 그것에 대해 논평하기를 바랬습니다! 이것은 나의 첫번째 MySql 스크립트였다. 저장 프로 시저에서 로컬 변수 만 사용하려고했지만이 경우 사용자 변수가 필요하다는 것을 확인해 주셔서 감사합니다. 기본 로직은 Sql Server와 비슷하지만 변수 처리에는 시간이 걸립니다. –

+0

예, 수동 페이지도 너무 환상적입니다. 맞습니까? – Drew