Oracle에서 MySQL로 변환 - Oracle 스크립트를 사용하는 방법
최근에 Oracle의 데이터베이스를 MySQL로 변환하고 Oracle의 데이터도 MySQL로 이전해야 하는 프로젝트가 있습니다.ORM 프레임워크는 Hibernate를 사용합니다.여러 가지 방법을 시도했다.
Navicat Premium 데이터 전송 기능
전송 실패
DB Convert Studio 주종 복제 기능
기본적으로 성공할 수 있고 문제가 많다.
DB Convert 사용에 관해서는 블로거의 또 다른 기사를 참고할 수 있다.
사용자 정의 스크립트 변환
오랫동안 고생한 후에 스스로 각본을 써서 이 일을 완성하기로 결정했다.Hibernate는 자동으로 실체 클래스에 따라 데이터베이스 테이블 필드/인덱스/외부 키를 업데이트할 수 있기 때문에 자동으로 메인 키를 추가하는 것은 지원되지 않습니다.따라서 스크립트는 테이블의 생성 문구, 메인 키 문구 추가, 데이터 삽입 문구만 생성하면 되며, 자바 프로젝트가 시작되면 Hibernate는 자동으로 키/인덱스 등 정보를 업데이트합니다.자신이 쓴 스크립트는 맞춤형화 정도가 높고 프로젝트의 특징과 결합하여 지속적으로 업데이트할 수 있다.
DECLARE
l_user VARCHAR(255) := 'YOUR_USER_HERE'; --
row_data_cur SYS_REFCURSOR; --
l_cur NUMBER;
l_ret NUMBER;
l_col_cnt NUMBER;
l_rec_tab dbms_sql.desc_tab;
cons_varchar2_code NUMBER := 1;
cons_number_code NUMBER := 2;
cons_date_code NUMBER := 12;
cons_clob_code NUMBER := 112;
cons_blob_code NUMBER := 113;
cons_timestamp_code NUMBER := 180;
l_varchar2_col VARCHAR2(32767); --1
l_number_col NUMBER; --2
l_date_col DATE; --12
l_clob_col CLOB; --112
l_blob_col BLOB; --113
l_timestamp_col TIMESTAMP(9); --180
cons_timestamp_frm VARCHAR2(32) := 'YYYY-MM-DD HH24:MI:SS';
CURSOR tabcur IS -- -
SELECT table_name,
owner,
tablespace_name,
initial_extent,
next_extent,
pct_used,
pct_free,
pct_increase,
degree
FROM sys.dba_tables
WHERE owner = Upper(l_user)
-- AND table_name IN( 'USER', 'ORG' )
;
--
colcount NUMBER(5); --
maxcol NUMBER(5); --
fillspace NUMBER(5); -- ( + =40)
collen NUMBER(5); --
pk_column VARCHAR(255); -- ( )
pk_column_count NUMBER(2); --
row_count NUMBER(2); --
row_count_sql VARCHAR(255); -- sql
insert_into_sql_start VARCHAR(2000); -- sql
insert_into_sql_full VARCHAR(32767); -- sql
select_sql VARCHAR(2000); -- sql
col_name_append_quot1 VARCHAR(2000); -- , `
col_name_append_quot2 VARCHAR(2000); -- , "
col_array dbms_sql.varchar2_table; --
--
BEGIN
dbms_output.ENABLE(buffer_size => NULL);
maxcol := 0;
--
FOR tabrec IN tabcur LOOP
--
SELECT Count(column_id)
INTO maxcol
FROM sys.dba_tab_columns
WHERE table_name = tabrec.table_name
AND data_type <> 'RAW'
AND owner = tabrec.owner;
--
dbms_output.Put_line('CREATE TABLE '
|| tabrec.table_name);
dbms_output.Put_line('( ');
--
colcount := 0;
row_count := 0;
col_name_append_quot1 := '';
col_name_append_quot2 := '';
insert_into_sql_start := 'insert into '
|| tabrec.table_name
|| '(';
FOR item IN (SELECT column_name
col1,
Decode(data_type, 'BLOB', 'longblob ',
'CLOB', 'longtext ',
'DATE', 'datetime ',
'FLOAT', 'DECIMAL(10, 2) ',
'TIMESTAMP(6)', 'datetime ',
'NVARCHAR2', 'VARCHAR'
|| '('
|| char_length
|| ') ',
'VARCHAR2', 'VARCHAR'
|| '('
|| char_length
|| ') ',
'NUMBER', 'DECIMAL'
||
Decode(Nvl(data_precision, 0), 0, ' ',
' ('
||
data_precision
||
Decode(Nvl(data_scale, 0), 0, ') ',
','
|| data_scale
|| ') ')))
col2
FROM sys.dba_tab_columns
WHERE owner = Upper(l_user)
AND table_name = tabrec.table_name
AND data_type <> 'RAW'
ORDER BY column_id) LOOP
collen := Length(item.col1);
fillspace := 40 - collen;
dbms_output.Put('`'
|| item.col1
|| '`');
--
FOR i IN 1 .. fillspace LOOP
dbms_output.Put(' ');
END LOOP;
--
IF item.col2 LIKE 'DECIMAL (19) ' THEN -- id
dbms_output.Put('bigint ');
ELSIF item.col2 = 'DECIMAL (1) ' THEN -- bool
dbms_output.Put('tinyint ');
ELSE
dbms_output.Put(item.col2);
END IF;
colcount := colcount + 1;
Col_array(colcount) := item.col1;
--
IF ( colcount < maxcol ) THEN
dbms_output.Put_line(',');
col_name_append_quot1 := col_name_append_quot1
|| '`'
|| item.col1
|| '`'
|| ', ';
col_name_append_quot2 := col_name_append_quot2
|| '"'
|| item.col1
|| '"'
|| ', ';
ELSE
dbms_output.Put_line(') ;');
col_name_append_quot1 := col_name_append_quot1
|| '`'
|| item.col1
|| '`';
col_name_append_quot2 := col_name_append_quot2
|| '"'
|| item.col1
|| '"';
END IF;
END LOOP;
pk_column_count := 0;
pk_column := '';
SELECT Count(cols.column_name)
INTO pk_column_count
FROM all_constraints cons,
all_cons_columns cols
WHERE cons.constraint_type = 'P'
AND cols.table_name = tabrec.table_name
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner
AND cons.owner = tabrec.owner;
IF pk_column_count > 0 THEN
FOR pk_name IN (SELECT cols.column_name
INTO pk_column
FROM all_constraints cons,
all_cons_columns cols
WHERE cons.constraint_type = 'P'
AND cols.table_name = tabrec.table_name
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner
AND cons.owner = tabrec.owner) LOOP
pk_column := pk_column
|| pk_name.column_name
|| ',';
END LOOP;
END IF;
IF pk_column_count > 0 THEN
pk_column := Substr(pk_column, 1, Length(pk_column) - 1);
dbms_output.Put_line('ALTER TABLE '
|| tabrec.table_name
|| ' ADD CONSTRAINT '
|| tabrec.table_name
|| '_PK_'
|| ' PRIMARY KEY ('
|| pk_column
||');');
END IF;
select_sql := 'select '
|| col_name_append_quot2
|| ' from '
|| l_user
|| '.'
|| tabrec.table_name
|| '';
-- dbms_output.Put_line(select_sql);
insert_into_sql_start := insert_into_sql_start
|| col_name_append_quot1
|| ') values(';
l_cur := dbms_sql.open_cursor;
dbms_sql.Parse(l_cur, select_sql, dbms_sql.native);
dbms_sql.Describe_columns(l_cur, l_col_cnt, l_rec_tab);
FOR i IN 1..l_rec_tab.count LOOP
IF L_rec_tab(i).col_type = cons_varchar2_code THEN --
dbms_sql.Define_column(l_cur, i, l_varchar2_col,
L_rec_tab(i).col_max_len);
ELSIF L_rec_tab(i).col_type = cons_number_code THEN --
dbms_sql.Define_column(l_cur, i, l_number_col);
ELSIF L_rec_tab(i).col_type = cons_date_code THEN --date
dbms_sql.Define_column(l_cur, i, l_date_col);
ELSIF L_rec_tab(i).col_type = cons_clob_code THEN --clob
dbms_sql.Define_column(l_cur, i, l_clob_col);
ELSIF L_rec_tab(i).col_type = cons_blob_code THEN --clob
dbms_sql.Define_column(l_cur, i, l_blob_col);
ELSIF L_rec_tab(i).col_type = cons_timestamp_code THEN --timestamp
dbms_sql.Define_column(l_cur, i, l_timestamp_col);
ELSE
Raise_application_error(-20001, 'Column: '
||L_rec_tab(i).col_name
||'Type not supported: '
||L_rec_tab(i).col_type);
END IF;
END LOOP;
l_ret := dbms_sql.EXECUTE(l_cur);
LOOP
insert_into_sql_full := insert_into_sql_start;
l_ret := dbms_sql.Fetch_rows(l_cur);
exit WHEN l_ret = 0;
FOR i IN 1..l_rec_tab.count LOOP
IF L_rec_tab(i).col_type = cons_varchar2_code THEN
--
dbms_sql.Column_value(l_cur, i, l_varchar2_col);
IF l_varchar2_col IS NULL THEN
insert_into_sql_full := insert_into_sql_full
|| 'NULL,';
ELSE
insert_into_sql_full := insert_into_sql_full
|| ''''
|| Replace(To_char(l_varchar2_col),
''''
,
'\''')
|| ''','; --
END IF;
ELSIF L_rec_tab(i).col_type = cons_number_code THEN
--
dbms_sql.Column_value(l_cur, i, l_number_col);
IF l_number_col IS NULL THEN
insert_into_sql_full := insert_into_sql_full
|| 'NULL,';
ELSE
insert_into_sql_full := insert_into_sql_full
|| To_char(l_number_col)
|| ',';
END IF;
ELSIF L_rec_tab(i).col_type = cons_date_code THEN --date
dbms_sql.Column_value(l_cur, i, l_date_col);
IF l_date_col IS NULL THEN
insert_into_sql_full := insert_into_sql_full
|| 'NULL,';
ELSE
insert_into_sql_full := insert_into_sql_full
|| ''''
||
To_char(l_date_col, cons_timestamp_frm)
|| ''',';
END IF;
ELSIF L_rec_tab(i).col_type = cons_clob_code THEN --Clob
dbms_sql.Column_value(l_cur, i, l_clob_col);
IF l_clob_col IS NULL THEN
insert_into_sql_full := insert_into_sql_full
|| 'NULL,';
ELSE
-- insert_into_sql_full := insert_into_sql_full || '''' || dbms_lob.substr(l_clob_col) || ''',';
insert_into_sql_full := insert_into_sql_full
|| ''''
|| 'CLOB HERE, SKIP'
|| ''',';
END IF;
ELSIF L_rec_tab(i).col_type = cons_blob_code THEN --Blob
dbms_sql.Column_value(l_cur, i, l_blob_col);
IF l_blob_col IS NULL THEN
insert_into_sql_full := insert_into_sql_full
|| 'NULL,';
ELSE
insert_into_sql_full := insert_into_sql_full
|| '0x'
|| dbms_lob.Substr(l_blob_col)
|| ',';
END IF;
ELSIF L_rec_tab(i).col_type = cons_timestamp_code THEN
--timestamp
dbms_sql.Column_value(l_cur, i, l_timestamp_col);
IF l_timestamp_col IS NULL THEN
insert_into_sql_full := insert_into_sql_full
|| 'NULL,';
ELSE
insert_into_sql_full := insert_into_sql_full
|| ''''
||
To_char(l_timestamp_col, cons_timestamp_frm)
|| ''',';
END IF;
ELSE
Raise_application_error(-20001, 'Column: '
||L_rec_tab(i).col_name
||'Type not supported: '
||L_rec_tab(i).col_type);
END IF;
END LOOP;
insert_into_sql_full := Substr(insert_into_sql_full, 1, Length(
insert_into_sql_full) - 1);
-- ,
insert_into_sql_full := insert_into_sql_full
|| ');';
dbms_output.Put_line(insert_into_sql_full);
END LOOP;
END LOOP;
END;
스크립트 밟기 설명
내 프로젝트에서 데이터베이스 전환의 수요를 완전히 만족시켰다.다른 항목을 사용하려면 다음과 같은 몇 가지를 주의해야 한다
지원되는 데이터 유형
스크립트 239-259 줄, 항목에 나타난 필드 형식만 지원합니다.다음 스크립트를 사용하여 프로젝트 데이터베이스의 모든 유형을 확인할 수 있습니다.
SELECT
DATA_TYPE, DATA_SCALE, COUNT(*) QTY
FROM
sys.dba_tab_columns
WHERE
owner = UPPER( 'YOUR_USER_HERE' )
and table_name not in (select view_name from all_views where owner = 'YOUR_USER_HERE')
GROUP BY DATA_TYPE, DATA_SCALE
ORDER BY DATA_TYPE ASC, QTY DESC;
유형 코드는 Oracle 문서를 참조하십시오.https://docs.oracle.com/cd/E11882_01/server.112/e41085/sqlqr06002.htm#SQLQR959
스크립트 실행 속도
스크립트에서 dbms 사용output.Put_line은 생성된 스크립트를 출력합니다. 라이브러리 데이터가 많으면 실행이 매우 느립니다. UTL 을 통해FILE.put_line 방식으로 파일에 출력하면 실행 속도가 훨씬 빨라집니다
Blob 및 Clob
Blob 및 Clob 유형은 스크립트 320, 332에서 처리됩니다. Putline은 최대 32767자를 지원합니다. 이 제한을 초과하면 문장 실행이 잘못됩니다.이 문제에 관해서 인터넷에서 정의 함수를 순환 인쇄한다고 언급한 적이 있는데 이것은 시도해 본 적이 없다. 그러나 가능할 것이다. 단지 순환 인쇄는 여분의 줄을 바꿀 수 있지만 실행이 끝난 후에 정규를 통해 여분의 줄을 삭제하면 된다.
dbms_sql.Describe_columns ORA-06502 예외 사항
이것은 Oracle 테이블의 필드가 32자를 초과하기 때문에 발생합니다. 구체적으로 제 다른 글을 참고하십시오.https://blog.csdn.net/jiangshanwe/article/details/106530155DBA/Java 개발자와 소통해 이 필드의 길이를 32비트 이내로 줄이면 된다.
기타 데이터베이스 지원
SQL Server 또는 다른 데이터베이스로 변환해야 하는 경우 대상 데이터베이스의 구문에 따라 용도를 변경할 수 있습니다.
참고 자료
https://stackoverflow.com/questions/937398/how-to-get-oracle-create-table-statement-in-sqlplus https://github.com/teopost/oracle-scripts/blob/master/fn_gen_inserts.sql https://docs.oracle.com/cd/E11882_01/server.112/e41085/sqlqr06002.htm#SQLQR959 https://stackoverflow.com/questions/1649183/generating-sql-insert-into-for-oracle
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Oracle 생성 향후 3일간의 전체 시점 (단계 상세)수요: X 좌표축 시간은 모두 정시 시간으로 앞으로 3일 동안의 예측을 보여준다(x 축은 앞으로 3일 동안의 정시 시간을 보여준다), 3시간마다 한 눈금, 가로 좌표는 모두 24개의 눈금을 보여준다 1단계: 현재 시...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.