Is there a way to Oracle expdp not inherit char type nls semantics on DDL?
Question
expdp, by default, generated internal DDL to create table observing current NLS_LENGTH_SEMANTICS of each column.
If a column as BYTE (the default and most used) NLS_LENGTH_SEMANTICS, the internal DDL would be like:
CREATE TABLE BDATA.Artikel(
Key VARCHAR2(3 BYTE) NOT NULL,
Name VARCHAR2(60 BYTE) NOT NULL,
Abkuerzung VARCHAR2(5 BYTE) NOT NULL
);
But I want an option to force expdp to not get/inherit the CHAR_USED value from DBA_TAB_COLUMNS, resulting into the following DDL:
CREATE TABLE BDATA.Artikel(
Key VARCHAR2(3) NOT NULL,
Name VARCHAR2(60) NOT NULL,
Abkuerzung VARCHAR2(5) NOT NULL
);
The reason is because the target database has a AL32UTF8 charset and NLS_LENGTH_SEMANTICS set as CHAR. So I want the tables be converted from BYTE to CHAR (accordingly to NLS_LENGTH_SEMANTICS parameter value).
Solution
I made a quick and dirty solution which worked for me today (Oracle 12.1), no reason to wait for the next 11 years.
create or replace trigger T_mutate_len_semantics after create on database
when (SYS.DICTIONARY_OBJ_TYPE = 'TABLE' and SYS.DICTIONARY_OBJ_OWNER not in ('SYS','SYSTEM'))
declare
stmt varchar2(2000);
begin
--debug
dbms_system.ksdwrt(2,'T_mutate_len_semantics: After creating table '||SYS.DICTIONARY_OBJ_NAME);
for r in (select column_name, data_length, data_type
from dba_tab_columns
where table_name = SYS.DICTIONARY_OBJ_NAME
and owner = SYS.DICTIONARY_OBJ_OWNER
and data_type in ('VARCHAR2','CHAR')
and DATA_LENGTH = CHAR_LENGTH
)
loop
stmt := 'alter table '||SYS.DICTIONARY_OBJ_OWNER||'.'||SYS.DICTIONARY_OBJ_NAME||' modify ('||r.column_name||' '||r.data_type||'('||r.data_length||' CHAR))';
dbms_system.ksdwrt(2,'T_mutate_len_semantics: '||stmt);
execute immediate stmt;
end loop;
end;
/
OTHER TIPS
This feature was requested 11 years ago, and it is still not implemented:
Bug 5034478 : ENH: ADD PARAMETER TO IMPDP TO OVERWRITE NLS_LENGTH_SEMANTICS
At the moment there is no way of moving all data, or single columns/tables from BYTE to CHAR with expdp/impdp.