- Overview
- Environment
- Quick Start
- Configuration
- Commands
- mtk
- init-project
- config
- license
- mig
- show
- sync
- sync-schema
- sync-sequence
- sync-object-type
- sync-domain
- sync-wrapper
- sync-server
- sync-user-mapping
- sync-queue
- sync-table
- sync-nickname
- sync-rule
- sync-table-data
- sync-table-data-estimate
- sync-index
- sync-constraint
- sync-db-link
- sync-view
- sync-mview
- sync-function
- sync-procedure
- sync-package
- sync-trigger
- sync-synonym
- sync-table-data-com
- sync-alter-sequence
- sync-coll-statistics
- check-table-data
- gen
- gen completion
- encrypt
- convert-plsql
- report
- self
- mvd
- usql
- Graphical
- Faqs
- Release
Migrating Data from DB2 to openGauss/MogDB Using MTK
Supported Versions
- 9.7
- 10.5
- 11.1
- 11.5
Precautions
Character Set
During data migration from DB2 to openGauss/MogDB, keep the following environment variables consistent with those of the database.
- LANG
- DB2CODEPAGE
If you run db2set -all
on a DB2 server, the command output shows that the environment variables are inconsistent with those of the database. In this case, you need to configure them consistent.
DB2 character set can be divided into three types, including OS Locale, DB2CODEPAGE, and DATABASE CODEPAGE.
-
OS Locale
OS-level code page configuration, which determines the default code page of an application program
- Unix/Linux
# Chinese export LANG="zh_CN.UTF-8" # English export LANG="en_US.UTF-8"
- Windows: Configure language setting in Control Panel > Regional Options.
-
DB2CODEPAGE
DB2 instance-level code page configuration, which influences determination of DB2-related applications on code page conversion
# View the data string. db2 get db cfg |grep cfg # DB2CODEPAGE supports environment variable settings. db2set db2codepage=1208 # Environment variable Linux export DB2CODEPAGE=1208 # Environment variable Windows set DB2CODEPAGE=1208
-
DATABASE CODEPAGE
DB2 database-level code page configuration, which must be set during database creation
db2 "create database db_name using CODESET UTF-8 TERRITORY CN"
Empty String and Null Problems
In DB2, null is not equal to an empty string.
The compatibility type A in openGauss is different from that in DB2 in that the property NOT NULL
of a column will be converted to " "
and will be converted to NULL
if permitted in openGauss.
The compatibility type PG in openGauss is the same as that in DB2 in that NULL
!=''
does not need to be processed.
DBCOMPATIBILITY [ = ] compatibility_type
Specifies the type of the database to be compatible with.
Value range: A, B, C, and PG
- A indicates that MogDB is compatible with Oracle.
- B indicates that MogDB is compatible with MySQL.
- C indicates that MogDB is compatible with Teradata.
- PG indicates that MogDB is compatible with PostgreSQL.
However, C is not supported currently. Therefore, the values A, B, and PG are commonly used.
Note:
- For the compatibility type of A, the database considers an empty string as
NULL
and replace the data type DATE with TIMESTAMP(0) WITHOUT TIME ZONE.- For the compatibility type of B, when a string is converted to an integer type, if an illegal value is entered, it will be converted to 0. However, for other compatibility types, an error will be reported.
- For the compatibility type of PG, CHAR and VARCHAR use character as the string unit. For other compatibility types, byte is used as the string unit. For example, as for UTF-8 character set, CHAR(3) can hold 3 Chinese characters in the compatibility type of PG but only one Chinese character in the other compatibility types.
Sequence
-
Defining types is not supported
- SMALLINT
- INTEGER
- BIGINT
- DECIMAL
-
maximum
The maximum value of the openGauss sequence is that of bigint. However, the maximum value of the DB2 sequence is greater than this value.
-
RESTART
IBM DB2 openGauss/MogDB ALTER SEQUENCE MTK1.SEQUENCE_BIGINT RESTART WITH 1 SELECT SETVAL('DB2_MTK1.SEQUENCE_BIGINT',1,true)
Table
-
The system table
ADVISE_*
/EXPLAIN_*
in DB2 is automatically ignored. -
Partition table
DB2
PARTITION BY RANGE("SALES_MONTH") ( PART "PART0" ENDING(1) IN "USERSPACE1", PART "PART1" ENDING(2) IN "USERSPACE1", PART "PART2" ENDING(3) IN "USERSPACE1", PART "PART3" ENDING(4) IN "USERSPACE1", PART "PART4" ENDING(5) IN "USERSPACE1", PART "PART5" ENDING(6) IN "USERSPACE1", PART "PART6" ENDING(7) IN "USERSPACE1", PART "PART7" ENDING(8) IN "USERSPACE1", PART "PART8" ENDING(9) IN "USERSPACE1", PART "PART9" ENDING(10) IN "USERSPACE1", PART "PART10" ENDING(11) IN "USERSPACE1", PART "PART11" ENDING(12) IN "USERSPACE1" )
openGauss
PARTITION BY RANGE (SALES_MONTH) ( PARTITION PART0 VALUES LESS THAN(2), PARTITION PART1 VALUES LESS THAN(3), PARTITION PART2 VALUES LESS THAN(4), PARTITION PART3 VALUES LESS THAN(5), PARTITION PART4 VALUES LESS THAN(6), PARTITION PART5 VALUES LESS THAN(7), PARTITION PART6 VALUES LESS THAN(8), PARTITION PART7 VALUES LESS THAN(9), PARTITION PART8 VALUES LESS THAN(10), PARTITION PART9 VALUES LESS THAN(11), PARTITION PART10 VALUES LESS THAN(12) )
-
The range partition property of DB2 can define whether the partition value is included in the partition (
INCLUSIVE
/EXCLUSIVE
). Because the range partition in openGauss defines that the partition value is less than a value (less than
), an error will be reported when the range partition property of DB2 is set toENDING INCLUSIVE
.DB2
PARTITION BY RANGE("SALES_MONTH") ( PART "PART0" STARTING(1) IN "USERSPACE1", PART "PART1" STARTING(2) IN "USERSPACE1", PART "PART2" STARTING(3) IN "USERSPACE1", PART "PART3" STARTING(4) IN "USERSPACE1", PART "PART4" STARTING(5) IN "USERSPACE1", PART "PART5" STARTING(6) IN "USERSPACE1", PART "PART6" STARTING(7) IN "USERSPACE1", PART "PART7" STARTING(8) IN "USERSPACE1", PART "PART8" STARTING(9) IN "USERSPACE1", PART "PART9" STARTING(10) IN "USERSPACE1", PART "PART10" STARTING(11) IN "USERSPACE1", PART "PART11" STARTING(12) ENDING(12) IN "USERSPACE1" -> This partition will be removed because the ending value of PART11 is the same as that of the previous partition. )
openGauss
An error information or warning is prompted
the part PART11 is included high value for db2 inclusive option
.PARTITION BY RANGE (SALES_MONTH) ( PARTITION PART0 VALUES LESS THAN(2), PARTITION PART1 VALUES LESS THAN(3), PARTITION PART2 VALUES LESS THAN(4), PARTITION PART3 VALUES LESS THAN(5), PARTITION PART4 VALUES LESS THAN(6), PARTITION PART5 VALUES LESS THAN(7), PARTITION PART6 VALUES LESS THAN(8), PARTITION PART7 VALUES LESS THAN(9), PARTITION PART8 VALUES LESS THAN(10), PARTITION PART9 VALUES LESS THAN(11), PARTITION PART10 VALUES LESS THAN(12) )
-
The
MINVALUE
partition is auto convertMAXVALUE
partition -
The
MAXVALUE
partition is automatically added. autoAddMaxvaluePart -
The partition with its
ENDING
that is the same as that of the previous partition will be ignored.DB2
PARTITION BY RANGE(SALES_DATE) ( PART PART1 STARTING(MINVALUE) ENDING(10000) IN USERSPACE1, PART PART2 STARTING(10000) ENDING(20000) IN USERSPACE1, PART PART3 STARTING(20000) ENDING(30000) IN USERSPACE1, PART PART3_1 STARTING(30000) ENDING(30000) INCLUSIVE IN USERSPACE1, --->Partition ignored PART PART4 STARTING(30000) EXCLUSIVE ENDING(40000) IN USERSPACE1, PART PART5 STARTING(40000) ENDING(50000) IN USERSPACE1, PART PART_MAX STARTING(60000) ENDING(MAXVALUE) IN USERSPACE1 )
openGauss
An error information or warning is prompted
the part PART11 is included high value for db2 inclusive option
.PARTITION BY RANGE (SALES_DATE) ( PARTITION PART1 VALUES LESS THAN(10000), PARTITION PART2 VALUES LESS THAN(20000), PARTITION PART3 VALUES LESS THAN(30000), PARTITION PART4 VALUES LESS THAN(40000), PARTITION PART5 VALUES LESS THAN(50000), PARTITION PART_MAX VALUES LESS THAN(MAXVALUE) )
-
-
Global temporary table
- Support
ON COMMIT { PRESERVE ROWS | DELETE ROWS }
syntax - Not Support
ON ROLLBACK
syntax - Declarative temporary tables in storage procedures are not supported
- Support
-
Local temporary not supported
-
Not supported
- H = Hierarchy table
- L = Detached table
- U = Typed table
Column
Column Comparison Between DB2 and openGauss/MogDB
DB2 Column Type | DB Length | Scale | openGauss Column Type | data_length | data_precision | data_scal |
---|---|---|---|---|---|---|
BOOLEAN | 1 | 0 | boolean | |||
SMALLINT | 2 | 0 | smallint | 16 | ||
INTEGER | 4 | 0 | integer | 32 | ||
BIGINT | 8 | 0 | bigint | 64 | ||
DECIMAL | 5 | 0 | numeric | 5 | ||
REAL | 4 | 0 | real | 24 | ||
DOUBLE | 8 | 0 | double precision | 53 | ||
DECFLOAT | 16 | 0 | numeric | |||
CHARACTER | 1 | 0 | character | 1 | ||
VARCHAR | 20 | 0 | character varying | 20 | ||
LONG VARCHAR | 0 | text | ||||
CLOB | 0 | text/clob | ||||
DBCLOB | 0 | text/clob | ||||
BINARY | 10 | 0 | bytea | |||
VARBINARY | 10 | 0 | bytea | |||
BLOB | 0 | bytea/blob | ||||
GRAPHIC | 30 | 0 | text | |||
VARGRAPHIC | 10 | 0 | text | |||
LONG VARGRAPHIC | 0 | text | ||||
DATE | 4 | 0 | timestamp without time zone | |||
TIME | 3 | 0 | time without time zone | |||
TIMESTAMP | 10 | 6 | timestamp without time zone | |||
XML | 0 | 0 | text |
Virtual column
-
virtualColToNormalCol is supported that virtual columns can be converted to common columns.
-
virtualColConv is supported that the expressions of virtual columns can be converted.
-
GENERATED ALWAYS
-
GENERATED BY DEFAULT
is changed to a sequence after migration. -
GENERATED ALWAYS/DEFAULT AS IDENTITY
MTK will automatically create sequences in the background for db2 IDENTITY. Therefore, the default value NEXTVAL(seq) will be automatically added in openGauss.
-- DB2 "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY ( START WITH +1 INCREMENT BY +1 MINVALUE +10 MAXVALUE +2147483647 NO CYCLE CACHE 20 NO ORDER ) -- openGauss id int4 NOT NULL DEFAULT nextval('mtk1.sql210309122906550'::regclass), -- DB2 ID2 INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH +1 INCREMENT BY +1 MINVALUE +10 MAXVALUE +2147483647 CYCLE CACHE 20 NO ORDER ) , -- openGauss id2 int4 NOT NULL DEFAULT nextval('mtk1.sql210309121230480'::regclass),
-
timestamp
GENERATED ALWAYS FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP
not supported
Conversion of column names
Original Column Name | New Column Name | Upper Case or Lower Case |
---|---|---|
COMPACT | compact | |
FENCED | fenced | |
AUTHID | authid | |
TID | "TID" | Upper case |
Default value of the column
- current timestamp -> current_timestamp
FOR BIT DATA
-
The FOR BIT DATA field type is converted to the varchar type and stored in hexadecimal. The column length is changed to the original column length multiplied by 2 plus 4.
-
CHARACTER
-
VARCHAR
-
"C_CHARBIT" CHAR(5 OCTETS) FOR BIT DATA --> c_charbit CHARACTER(14)
hehel --> \x686568656c
Constraints
-
Primary key constraint
-
Unique constraint
-
Check
-
Foreign key constraint
-
NOT ENFORCED
is not supported in openGauss.NOT ENFORCED
recommends that the column is not forcibly checked when data is inserted or updated in DB2. openGauss does not support this function. -
The virtual column is automatically skipped and then the check constraint is created.
Index
- A column of a single index has a maximum of 32 fields.
- Partition index
- Partition -> local
- Not Partition -> Global
- The following index types are not supported:
XML path index
XML region index
Page map index for a column-organized table
Modification state index
View
- Views that depend on
nickname
are automatically skipped. - Views that are created using function indexes are automatically skipped.
WITH [NO] ROW MOVEMENT
Not SupportWITH [LOCAL|CASCADED] CHECK OPTION
Not Support
Objects not migrated
NickName
object
Function
Built-in functions
IBM DB2 | openGauss/MogDB |
---|---|
CURRENT TIMESTAMP |
CURRENT_TIMESTAMP |
CURRENT DATE |
CURRENT_DATE |
CURRENT_TIME |
CURRENT_TIME |
MONTH(SALES_DATE) |
date_part('month', sales_date) |
MINUTE(SALES_DATE) |
date_part('minute', sales_date) |
YEAR(CURRENT TIMESTAMP) |
date_part('year', current_timestamp) |
MONTH(CURRENT TIMESTAMP) |
date_part('month', current_timestamp) |
DAY(CURRENT TIMESTAMP) |
date_part('day', current_timestamp) |
HOUR(CURRENT TIMESTAMP) |
date_part('hour', current_timestamp) |
HOUR(TONGJITIME_END) HOURS |
date_part('hour', tongjitime_end) * interval '1 hours' |
MINUTE(CURRENT TIMESTAMP) |
date_part('minute', current_timestamp) |
SECOND(CURRENT TIMESTAMP) |
date_part('second', current_timestamp) |
MICROSECOND(CURRENT TIMESTAMP) |
date_part('microsecond', current_timestamp) |
WEEK(CURRENT TIMESTAMP) |
date_part('week', current_timestamp) |
VALUE(NULL,1) |
nvl(null,1) |
LCASE('SYSIBM.SYSDUMMY1') |
lower('sysibm.sysdummy1') |
DATE(CURRENT TIMESTAMP) |
current_date |
TIME(CURRENT TIMESTAMP) |
localtime(0) |
TIMESTAMP(CURRENT TIMESTAMP) |
current_timestamp::timestamp |
TO_CHAR(TIMESTAMP('2012-5-25 21:18:12'),'YYYY-MM-DD') |
to_char('2012-5-25 21:18:12'::timestamp,'yyyy-mm-dd') |
TO_CHAR(TIMESTAMP('2012-5-25 21:18:12'),'YYYY-MM-DD HH:MI:SS') |
to_char('2012-5-25 21:18:12'::timestamp,'yyyy-mm-dd hh:mi:ss') |
TO_CHAR(TIMESTAMP('2012-5-25 21:18:12'),'YYYY-MM-DD HH24:MM:SS') |
to_char('2012-5-25 21:18:12'::timestamp,'yyyy-mm-dd hh24:mm:ss') |
TO_CHAR(TIMESTAMP('2012-5-25 21:18:12'),'YYYY-MM-DD HH24:MI:SS') |
to_char('2012-5-25 21:18:12'::timestamp,'yyyy-mm-dd hh24:mi:ss') |
DAYS(CURRENT DATE)-DAYS(CURRENT DATE-1000 DAY) |
(extract('day' from ((current_date)::date - '0001-01-01bc'))-365)-(extract('day' from ((current_date-interval '1000 day')::date - '0001-01-01bc'))-365) |
DAYOFYEAR(CURRENT TIMESTAMP) |
extract(doy from (current_timestamp)::timestamp) |
WEEK_ISO('2016-01-02') |
extract(week from ('2016-01-02')::timestamp) |
DAYOFWEEK_ISO('2016-01-02') |
extract(isodow from ('2016-01-02')::timestamp) |
DAYOFWEEK('2016-01-02') |
extract(dow from ('2016-01-02')::timestamp)+1 |
MONTHNAME('2016-01-02') |
to_char(('2016-01-02')::timestamp,'month') |
DAYNAME('2016-01-02') |
to_char(('2016-01-02')::timestamp,'day') |
POSSTR('NAME','A') |
position('a' in 'name') |
INSERT('NAME',1,2,'GHK') |
substring('name',0,1) |
INSERT('AHBTYOGFD',3,2,'GHK') |
substring('ahbtyogfd',0,3) |
TRUNC_TIMESTAMP
IBM DB2 | openGauss/MogDB |
---|---|
TRUNC_TIMESTAMP(SNAPTIME, 'SYYYY') |
date_trunc('year',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'SYEAR') |
date_trunc('year',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'YEAR') |
date_trunc('year',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'Y') |
date_trunc('year',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'YY') |
date_trunc('year',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'YYY') |
date_trunc('year',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'YYYY') |
date_trunc('year',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'IY') |
date_trunc('year',SNAPTIME) + interval '1day' * (8 - extract('dow' from date_trunc('year', SNAPTIME))) % 7 |
TRUNC_TIMESTAMP(SNAPTIME, 'IYY') |
date_trunc('year',SNAPTIME) + interval '1day' * (8 - extract('dow' from date_trunc('year', SNAPTIME))) % 7 |
TRUNC_TIMESTAMP(SNAPTIME, 'IYYY') |
date_trunc('year',SNAPTIME) + interval '1day' * (8 - extract('dow' from date_trunc('year', SNAPTIME))) % 7 |
TRUNC_TIMESTAMP(SNAPTIME, 'i') |
date_trunc('year',SNAPTIME) + interval '1day' * (8 - extract('dow' from date_trunc('year', SNAPTIME))) % 7 |
TRUNC_TIMESTAMP(SNAPTIME, 'Q') |
date_trunc('quarter',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'MONTH') |
date_trunc('month',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'MON') |
date_trunc('month',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'MM') |
date_trunc('month',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'RM') |
date_trunc('month',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'IW') |
date_trunc('week',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'DAY') |
date_trunc('week',SNAPTIME) - interval '1 day' |
TRUNC_TIMESTAMP(SNAPTIME, 'DY') |
date_trunc('week',SNAPTIME) - interval '1 day' |
TRUNC_TIMESTAMP(SNAPTIME, 'D') |
date_trunc('week',SNAPTIME) - interval '1 day' |
TRUNC_TIMESTAMP(SNAPTIME, 'IW') |
date_trunc('week',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'DDD') |
date_trunc('day',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'DD') |
date_trunc('day',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'J') |
date_trunc('day',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'WW') |
date_trunc('day',SNAPTIME) - interval '1day' * (extract('doy' from SNAPTIME) % 7 - 1) |
TRUNC_TIMESTAMP(SNAPTIME, 'HH') |
date_trunc('hour',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'HH12') |
date_trunc('hour',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'HH24') |
date_trunc('hour',SNAPTIME) |
TRUNC_TIMESTAMP(SNAPTIME, 'MI') |
date_trunc('minute',SNAPTIME) |
Interval
IBM DB2 | openGauss/MogDB |
---|---|
1 YEAR |
interval '1 YEAR' |
1 YEARS |
interval '1 YEARS' |
1 MONTH |
interval '1 MONTH' |
1 MONTHS |
interval '1 MONTHS' |
1 DAYS |
interval '1 DAYS' |
1 DAY |
interval '1 DAY' |
1 HOURS |
interval '1 HOURS' |
1 HOUR |
interval '1 HOUR' |
1 MINUTE |
interval '1 MINUTE' |
1 MINUTES |
interval '1 MINUTES' |
1 SECONDS |
interval '1 SECONDS' |
1 SECOND |
interval '1 SECOND' |
Other Problems
-
When the data of the VARCHAR(5 OCTETS) FOR BIT DATA type in the COLVALUE column of the SYSIBM.SYSCOLDIST table is migrated, the error message "invalid byte sequence for encoding "UTF8": 0x00"" will be reported.
Currently, there is no proper method to handle with it.
The data is stored in hexadecimal in the database, such as 2700000002FF00FFFF27
-
SYSIBM.SYSCOLUMNS.HIGH2KEY