phpmyadmin을 사용하여 SQL DB에 CSV 테이블을 가져 왔습니다. 기본 형식은 10 진수 (8,5) 또는 적어도 그것이 나오는 방법입니다. 과잉 공격에 시달리고 나는 4,1로 줄일 수 있다고 생각했다. 문제는 약 470 개의 필드가 있다는 것입니다. 나는 한 번에 하나씩 바꾸는 방법을 안다. 그러나 이것은 오랜 시간이 걸릴 것이다. 더 빠른 방법이 있습니까?한 번에 여러 데이터베이스 열의 형식을 수정하십시오.
답변
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)
나는 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;
견적을 간다 :'-이 두 가지 이유로 necessary' ... 왜 확실하지 : (1) 당신이하지 않았다 처음에는 사용자 변수로 연결됩니다. (2) mysql은 로컬 변수를 좋아하지 않지만 사용자 변수를 좋아하는 참조 된 라인에서 매우 까다 롭습니다. – Drew
@Drew - 누군가가 그것에 대해 논평하기를 바랬습니다! 이것은 나의 첫번째 MySql 스크립트였다. 저장 프로 시저에서 로컬 변수 만 사용하려고했지만이 경우 사용자 변수가 필요하다는 것을 확인해 주셔서 감사합니다. 기본 로직은 Sql Server와 비슷하지만 변수 처리에는 시간이 걸립니다. –
예, 수동 페이지도 너무 환상적입니다. 맞습니까? – Drew