Para melhor visualização, recomendo resolução de no mínimo 1280 x 800 e navegador Mozilla Firefox


sexta-feira, 10 de outubro de 2008

Por que após ter realizado uma importação, minhas tabelas não foram para o tablespace padrão do usuário?

Por Eduardo Legatti

Olá,

Esta é uma das questões mais comuns de qualquer desenvolvedor ou de qualquer pessoa que está iniciando no banco de dados Oracle. A resposta dependerá de alguns fatores que tentarei demonstrar com exemplos práticos mais abaixo. Normalmente isto acontece quando se utiliza os tradicionais utilitários de exportação e importação (exp/imp), já que os utilitários Data Pump expdp e impdp fornecidos à partir do Oracle 10g, praticamente eliminaram esse tipo de "problema". Acredito que os tradicionais utilitários de exportação e importação (exp e imp) são umas das ferramentas mais usadas fornecidas com o software Oracle. Todos os DBAs, iniciantes ou veteranos, com certeza já se utilizaram delas. Como dito anteriormente, mesmo com o advento dos novos utilitários Data Pump Export (expdp) e Data Pump Import (impdp) fornecidos à partir do Oracle 10g, realmente eles trouxeram importantes e incríveis inovações, mas mesmo assim, acredito que eles não ofuscaram totalmente os velhos e tradicionais utilitários (exp/imp). Dentre os mais variados recursos que o Data Pump apresentou, além de incluir aprimoramentos arquitetônicos e funcionais significativos (dump baseado no formato XML) em relação aos tradicionais Export e Import, o mesmo permite parar e reiniciar jobs, ver o status dos jobs em execução e restringir de forma bastante parametrizável os dados que são exportados e importados, como a de permitir alterar valores de armazenamento (STORAGE) dos segmentos a serem importados.

Apesar de os tradicionais utilitários exp/imp ainda terem sido disponibilizados na recente versão Oracle 11g release 1, acredito que a estratégia da Oracle será de ir eliminando gradativamente o suporte aos mesmos nas futuras releases do Oracle em virtude dos utilitários Data Pump (expdp/impdp). Na verdade, nós usuários dos tradicionais utilitários exp/imp, estamos sendo encorajados a substituirmos o seu uso pelos utilitários Data pump Export e Data Pump Import desde o lançamento do Oracle 10g release 1.

Antes de abordarmos alguns exemplos práticos sobre exportação e importação de dados, vamos recapitular algumas funcionalidades dos tradicionais exp e imp de modo a fornecer uma visão geral.

Como todos nós já sabemos, a exportação e a importação permitem aos DBAs e aos desenvolvedores de aplicativos, fazerem cópias fidedignas e rápidas de dados de um banco Oracle. A exportação (usando-se o comando exp) faz uma cópia dos dados e das estruturas de dados em um arquivo de sistema operacional. A importação (usando-se o comando imp) lê os arquivos criados pela exportação e coloca os dados e as estruturas de dados nos arquivos do banco de dados. Dentre os modos disponíveis, temos tabela, usuário e exportação e importação completa de banco de dados. Ao usar a exportação de modo tabela, você diz ao Oracle os nomes de uma ou mais tabelas a serem exportadas. Na exportação de modo usuário, o Oracle exporta todos os objetos de um usuário, incluindo views, concessões do proprietário, triggers, índices, sinônimos, stored procedures, database links, tabelas, constraints e o que tiver mais dentro do schema do usuário. Na exportação completa de banco de dados, os objetos e dados de todos os usuários (exceto aqueles contidos no schema SYS), mais as declarações de criação de alguns arquivos de banco da dados também são exportadas. O Oracle 8i introduziu um parâmetro de exportação chamado QUERY que possibilitou a exportação de conjuntos de linhas baseadas em uma consulta. Isso facilitou muito a vida dos DBAs por ter dado um controle mais fino sobre os dados a serem manipulados por meio de exportação e importação. A partir do Oracle 8i, foi possível também exportar e importar as estatísticas pré-calculadas do otimizador. Outro recurso que foi incorporado na versão 8i, foram os tablespaces transportáveis na qual tornou possível a movimentação de um conjunto de tablespaces de um banco de dados Oracle para outro banco de dados Oracle (de mesma versão e O/S). Este método envolve a cópia dos arquivos de dados de um banco de dados para outro usando ao mesmo tempo os utilitários de exportação e importação para transportar os metadados do dicionário de dados associados ao tablespace.

Vale a pena salientar que o utilitário de exportação não pode ser considerado como uma ferramenta para criação de um método efetivo de backup. Eu diria que ele possibilita um backup lógico, pelo fato de que não é possível aplicar um histórico de redo log nos objetos importados provenientes de um arquivo de exportação. Um backup lógico de um banco de dados envolve a leitura de um conjunto de registros do banco de dados e a gravação destes em um arquivo. Esses registros são lidos independentes das suas localizações físicas. Acredito que uma estratégia robusta de backup possa incluir tanto backups físicos como lógicos. Em geral, bancos de dados de produção contam com backups físicos como seu principal método de backup e backups lógicos servem como um método secundário. Por outro lado, para bancos de dados de desenvolvimento e para pequenos processamentos de movimentação de dados, os backups lógicos podem ser uma solução aceitável e viável.

Portanto, os arquivos dumps gerados pelo utilitário de exportação podem ser utilizados como um recurso complementar ao backup físico de banco de dados para proteção contra erros de usuário. Por exemplo, um backup lógico pode ser útil quando um usuário elimina ou trunca uma tabela acidentalmente ou quando o DBA precisa restaurar uma tabela que apresente erros lógicos, ou uma operação qualquer que tenha afetado somente um subconjunto do banco de dados. Neste caso, um dump de exportação atualizado seria uma alternativa mais rápida e menos traumática do que realizar uma recuperação incompleta de banco de dados, seja ela gerenciada pelo usuário ou através do recovery manager (RMAN). Em todo caso, e dependendo do cenário, isso dependerá muito da versão Oracle utilizada pelo fato de a partir do Oracle 10g, nós já termos a proteção da lixeira (recyclebin) para segmentos que foram dropados e inclusive recursos da tecnologia flashback.

Não podemos esquecer que, além da exportação pelo caminho convencional, um outro recurso chamado de caminho direto (DIRECT=Y), pode ser utilizado para extrair dados muito mais rapidamente pelo fato de o utilitário de exportação fazer a leitura diretamente em uma camada de dados, em vez de passar pela camada de processamento de dados SQL. Neste caso, os dados já estarão em um formato esperado pelo utilitário de exportação, evitando assim a conversão desnecessária de dados.

Durante uma importação, os dados são processados da seguinte forma:

* Novas tabelas são criadas
* Dados são importados
* Índices são construídos
* Triggers, restrições, stored procedures, views entre outros objetos são importados
* Restrições de integridade são ativadas nas novas tabelas
* Índices funcionais e de bitmaps e/ou de domínios são construídos

Na verdade, essa seqüência impede que os dados sejam rejeitados devido à ordem em que as tabelas são importadas. Ela também impede que as triggers sejam acionadas durante a importação.

Como regra, para mover dados entre bancos de dados Oracle de versões/releases diferentes, deve-se utilizar a premissa abaixo:
  • Para mover dados de uma versão inferior de banco de dados para uma versão superior de banco de dados Oracle, é necessário usar a versão nativa do utilitário de exportação referente à versão inferior e usar o utilitário de importação da versão referente à versão superior.
  • Para mover dados de uma versão superior de banco de dados para uma versão inferior de banco de dados Oracle, é necessário usar a versão nativa do utilitário de exportação referente à versão inferior e usar o utilitário de importação também referente à versão inferior.
A tabelas abaixo mostram esta interoperabilidade de movimentação de dados entre o Oracle 10g e outras versões:

Exportando dados do Oracle 10.2 e Importando-os em versões anteriores
------------------------------------------------------------------------------
Exportar de Importar para Use Export versão Use Import versão
------------------------------------------------------------------------------
Release 10.2 Release 10.2 Release 10.2 Release 10.2
------------------------------------------------------------------------------
Release 10.2 Release 10.1 Release 10.1 Release 10.1
------------------------------------------------------------------------------
Release 10.2 Release 9.2 Release 9.2 Release 9.2
------------------------------------------------------------------------------
Release 10.2 Release 9.0.1 Release 9.0.1 Release 9.0.1
------------------------------------------------------------------------------
Release 10.2 Release 8.1.7 Release 8.1.7 Release 8.1.7
------------------------------------------------------------------------------
Release 10.2 Release 8.0.6 Release 8.0.6 Release 8.0.6
------------------------------------------------------------------------------


Exportando dados de versões anteriores ao 10.2 e Importando-os no Oracle 10.2
------------------------------------------------------------------------------
Exportar de Importar para Use Export versão Use Import versão
------------------------------------------------------------------------------
Release 10.1 Release 10.2 Release 10.1 Release 10.2
------------------------------------------------------------------------------
Release 9.2 Release 10.2 Release 9.2 Release 10.2
------------------------------------------------------------------------------
Release 8.1.7 Release 10.2 Release 8.1.7 Release 10.2
------------------------------------------------------------------------------
Release 8.0.6 Release 10.2 Release 8.0.6 Release 10.2
------------------------------------------------------------------------------
Release 7.3.4 Release 10.2 Release 7.3.4 Release 10.2
------------------------------------------------------------------------------

A tabela abaixo mostra de forma geral, as versões de utilitários a serem usadas para cada caso.

Usando diferentes versões dos utilitários Export and Import
------------------------------------------------------------------
Export de -> Importar para Use Export versão Use Import versão
------------------------------------------------------------------
8.1.6 ---> 8.1.6 Release 8.1.6 Release 8.1.6
------------------------------------------------------------------
8.1.5 ---> 8.0.6 Release 8.0.6 Release 8.0.6
------------------------------------------------------------------
8.1.7 ---> 8.1.6 Release 8.1.6 Release 8.1.6
------------------------------------------------------------------
9.0.1 ---> 8.1.6 Release 8.1.6 Release 8.1.6
------------------------------------------------------------------
9.0.1 ---> 9.2.0 Release 9.0.1 Release 9.2.0
------------------------------------------------------------------
9.2.0 ---> 10.2.0 Release 9.2.0 Release 10.2.0
------------------------------------------------------------------
9.2.0 ---> 11.1.0 Release 9.2.0 Release 11.1.0
------------------------------------------------------------------
10.2.0 ---> 9.2.0 Release 9.2.0 Release 9.2.0
------------------------------------------------------------------
10.2.0 ---> 11.1.0 Release 10.2.0 Release 11.1.0
------------------------------------------------------------------
11.1.0 ---> 9.2.0 Release 9.2.0 Release 9.2.0
------------------------------------------------------------------
11.1.0 ---> 10.2.0 Release 10.2.0 Release 10.2.0
------------------------------------------------------------------

Voltando à questão que originou este artigo, demonstrarei abaixo alguns cenários práticos na qual poderemos transferir (exportar e importar) dados em um mesmo banco de dados Oracle de forma que os segmentos criados no schema de destino sejam criados no tablespace padrão do mesmo. Vale a pena salientar que no caso do utilitário de importação tradicional (imp), ao importar dados de um arquivo dump gerado pelo utilitário de exportação (exp), o Oracle sempre tentará importar os segmentos para o tablespace especificado no arquivo de exportação se o mesmo existir no banco de dados de destino, senão, os segmnentos serão importados para o tablespace padrão (default) do usuário. Outra coisa é que os atributos de storage (INITIAL EXTENT) das tabelas provenientes do schema original, também são exportadas pelo utilitário de exportação.

Bem, após esta longa introdução, vamos então a alguns exemplos práticos.

C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 07:32:30 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Criação de um tablespace TBS_A
SYS> create tablespace tbs_a
2 logging
3 datafile 'C:\oraclexe\oradata\XE\a.dbf' size 5m
4 extent management local
5 segment space management auto;

Tablespace criado.

-- Criação de um tablespace TBS_B
SYS> create tablespace tbs_b
2 logging
3 datafile 'C:\oraclexe\oradata\XE\b.dbf' size 5m
4 extent management local
5 segment space management auto;

Tablespace criado.

-- Criação dos schemas USUARIO_A e USUARIO_B
SYS> create user usuario_a identified by senha default tablespace tbs_a;

Usuário criado.

SYS> create user usuario_b identified by senha default tablespace tbs_b;

Usuário criado.

-- Concedendo roles pré-definidas para ambos os usuários
SYS> grant connect,resource to usuario_a,usuario_b;

Concessão bem-sucedida.

-- Criação da tabela EMP no schema USUARIO_A
SYS> connect usuario_a/senha
Conectado.

-- Confirmando o tablespace padrão
USUARIO_A> select default_tablespace from user_users;

DEFAULT_TABLESPACE
------------------------------
TBS_A

-- Criando a tabela EMP com tamanho incial de extent de 3MB
USUARIO_A> create table emp (id number) storage (initial 3m);

Tabela criada.

USUARIO_A> exit
Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Realizando a exportação do schema USUARIO_A
C:\>exp usuario_a/senha file=usuario_a statistics=none

Export: Release 10.1.0.2.0 - Production on Sex Out 10 07:36:09 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.


Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Exportação executada no conjunto de caracteres de WE8PC850 e no conjunto de caracteres
de AL16UTF16 NCHAR o servidor usa WE8MSWIN1252 conjunto de caracteres
. exportando objetos e ações procedurais anteriores ao esquema
. exportando os nomes da biblioteca de função externa para usuário USUARIO_A
. exportando sinônimos do tipo PÚBLICO
. exportando sinônimos do tipo privado
. exportando definições de tipos de objeto para usuário USUARIO_A
Sobre exportar objetos de USUARIO_A ...
. exportando vínculos de banco de dados
. exportando números de seqüência
. exportando definições de cluster
. sobre exportar tabelas de USUARIO_A ... via Caminho Convencional ...
. . exportando tabela EMP 0 linhas exportadas
. exportando sinônimos
. exportando views
. exportando procedimentos armazenados
. exportando operadores
. exportando restrições referenciais de integridade
. exportando gatilhos
. exportando tipos de índices
. exportando índices funcionais, extensíveis e de bitmap
. exportando ações contabilizáveis
. exportando views materializadas
. exportando logs de snapshot
. exportando filas de serviço
. exportando filhos e grupos de renovação
. exportando dimensões
. exportando objetos e ações procedurais posteriores ao esquema
. exportando estatística
Exportação encerrada com sucesso, sem advertências.


-- Realizando a importação do dump para o USUARIO_B
C:\>imp usuario_b/senha file=usuario_a full=y

Import: Release 10.1.0.2.0 - Production on Sex Out 10 07:40:02 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Arquivo de exportação criado por EXPORT:V10.01.00 via caminho convencional

Advertência: os objetos foram exportados por USUARIO_A; não por você

importação realizada nos conjuntos de caracteres WE8PC850 e NCHAR AL16UTF16
o servidor de importação usa o conjunto de caracteres WE8MSWIN1252
. importando objetos de USUARIO_A para USUARIO_B
. . importando table "EMP" 0 linhas importadas
Importação encerrada com sucesso, sem advertências.


-- Realizando conexão com usuário DBA
C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 07:41:51 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Executando query para verificar a localização das tabelas
SYS> select owner,table_name,initial_extent,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME INITIAL_EXTENT TABLESPACE_NAME
---------------------- --------------------- -------------- ------------------------
USUARIO_A EMP 3145728 TBS_A
USUARIO_B EMP 3145728 TBS_A

Podemos verificar acima que tabela EMP foi importada para o schema USUARIO_B no tablespace TBS_A, mesmo o schema USUARIO_B tendo o seu tablespace padrão sido definido como TBS_B. Como dito anteriormente, o Oracle sempre tentará importar os segmentos para o tablespace especificado no arquivo de exportação se o mesmo existir no banco de dados de destino, senão, os segmentos serão importados para o tablespace padrão (default) do usuário. Como o banco de origem e de destino é o mesmo, então a tabela foi importada para o tablespace TBS_A.

Abaixo, podemos ver no conteúdo do arquivo de exportação, que o tablespace TBS_A é o tablespace de origem definido para a tabela EMP. A propósito, podemos verificar também, que o atributo de storage (INITIAL) definido para a tabela EMP no schema de origem (USUARIO_A), também foi exportado para o arquivo de dump. Dependendo do caso, talvez seja interessante alterar este valor de storage nas tabelas do schema de origem, ou até mesmo, gerar os comandos DDL de criação das tabelas utilizando a cláusula INDEXFILE do comando imp para então editar o valor INITIAL da clásula storage com um valor menor. Se realmente for o caso, então porque não alterar também o tablespace? Após a criação das tabelas, seria necessário apenas utilizar a cláusula IGNORE=Y ao executar com comando imp para realizar a importação.

-- Verificando o conteúdo do arquivo de dump de exportação
C:\>imp usuario_b/senha file=usuario_a.dmp show=y

Import: Release 10.1.0.2.0 - Production on Sex Out 10 08:15:43 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Arquivo de exportação criado por EXPORT:V10.01.00 via caminho convencional
importação realizada nos conjuntos de caracteres WE8PC850 e NCHAR AL16UTF16
o servidor de importação usa o conjunto de caracteres WE8MSWIN1252
. importando objetos de USUARIO_A para USUARIO_B
"BEGIN "
"sys.dbms_logrep_imp.instantiate_schema(schema_name=>SYS_CONTEXT('USERENV','"
"CURRENT_SCHEMA'), export_db_name=>'XE', inst_scn=>'431135');"
"COMMIT; END;"
"CREATE TABLE "EMP" ("ID" NUMBER) PCTFREE 10 PCTUSED 40 INITRANS 1"
"MAXTRANS 255 STORAGE(INITIAL 3145728 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL"
"DEFAULT) TABLESPACE "TBS_A" LOGGING NOCOMPRESS"
. . saltando a tabela "EMP"

Importação encerrada com sucesso, sem advertências.

-- Após conectar com o USUARIO_B, podemos verificar que realmente foram alocados
-- 3 extensões (extents) para o segmento EMP do schema USUARIO_B
USUARIO_B> select extent_id,bytes,blocks
2 from user_extents
3 where segment_name='EMP';

EXTENT_ID BYTES BLOCKS
---------- ---------- ----------
0 1048576 128
1 1048576 128
2 1048576 128

-- Alterando o valor INITIAL para o menor possível que é 64K
USUARIO_B> alter table emp move storage(initial 1);

Tabela alterada.

USUARIO_B> select extent_id,bytes,blocks
2 from user_extents
3 where segment_name='EMP';

EXTENT_ID BYTES BLOCKS
---------- ---------- ----------
0 65536 8

Voltando à questão inicial, como os dados já foram importados para o schema de destino, e se quisermos que a tabela fique alocada no tablespace padrão (TBS_B) do schema, teremos apenas que movê-la utilizando o comando ALTER TABLE MOVE ... como mostrado abaixo:

-- Movendo a tabela EMP para o tablespace TBS_B
SYS> alter table usuario_b.emp move tablespace tbs_b;

Tabela alterada.

-- Verificando a localização da tabela EMP após a movimentação da tabela EMP
SYS> select owner,table_name,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME TABLESPACE_NAME
------------------------ ------------------------ -----------------------------
USUARIO_A EMP TBS_A
USUARIO_B EMP TBS_B

Após a movimentação da tabela EMP, podemos ver acima que o mesmo foi alocado no tablespace TBS_B. Vale a pena salientar que após qualquer movimentação de tabelas utilizando o comando ALTER TABLE MOVE ... será necessário que os índices porventura existentes e associados às tabelas movidas, sejam reconstruídos com o comando ALTER INDEX ... REBUILD.

Agora a pergunta que não quer calar: É possível fazer com que a tabela seja importada para o tablespace padrão do usuário de destino? Sim, é possível. Podemos ver na saída do comando SQL abaixo, que quando criamos o usuário USUARIO_B e concedemos a role pré-definida RESOURCE, automaticamente o privilégio de sistema UNLIMITED TABLESPACE também é concedido:

SYS> select * from dba_sys_privs where grantee='USUARIO_B';

GRANTEE PRIVILEGE ADM
------------------------ ---------------------------------------- ---
USUARIO_B UNLIMITED TABLESPACE NO

Apesar do privilégio de sistema UNLIMITED TABLESPACE não fazer parte da role RESOURCE como mostrado no resultado logo abaixo, o Oracle automaticamente e de forma implícita, concede este privilégio de sistema para todo usuário que tiver a concessão da role RESOURCE diretamente, mas não porque ela faz parte da role, e sim porque este privilégio é concedido ao usuário sempre que a role também for concedida. Bem, neste caso, porque então não conceder os privilégios separadamente? Apenas para reflexão ...

Vale a pena salientar que, uma vez que o privilégio de sistema UNLIMITED TABLESPACE seja concedido ao usuário, todas as cotas de espaço de tablespace porventura concedidas a este usuário, serão explicitamente desprezadas.

-- O resultado abaixo, nos mostra que privilégio de sistema UNLIMITED TABLESPACE não
-- está presente na role RESOURCE
SYS> select privilege from role_sys_privs where role='RESOURCE';

PRIVILEGE
----------------------------------------
CREATE SEQUENCE
CREATE TRIGGER
CREATE CLUSTER
CREATE PROCEDURE
CREATE TYPE
CREATE OPERATOR
CREATE TABLE
CREATE INDEXTYPE

8 linhas selecionadas.

Portanto, irei abaixo revogar o privilégio de sistema UNLIMITED TABLESPACE do usuário USUARIO_B, conceder cota de espaço ilimitada ao tablespace TBS_B para o usuário USUARIO_B e realizar a importação novamente:

-- Revogando o privilégio de sistema UNLIMITED TABLESPACE
SYS> revoke unlimited tablespace from usuario_b;

Revogação bem-sucedida.

-- Concedendo cota ilimitada no tablespace TBS_B para o USUARIO_B
SYS> alter user usuario_b quota unlimited on tbs_b;

Usuário alterado.

-- Dropando a tabela EMP de forma a realizar a importação novamente
SYS> drop table usuario_b.emp purge;

Tabela eliminada.

SYS> exit
Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production


-- Realizando a importação novamente
C:\>imp usuario_b/senha file=usuario_a full=y

Import: Release 10.1.0.2.0 - Production on Sex Out 10 08:20:38 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Arquivo de exportação criado por EXPORT:V10.01.00 via caminho convencional

Advertência: os objetos foram exportados por USUARIO_A; não por você

importação realizada nos conjuntos de caracteres WE8PC850 e NCHAR AL16UTF16
o servidor de importação usa o conjunto de caracteres WE8MSWIN1252
. importando objetos de USUARIO_A para USUARIO_B
. . importando table "EMP" 0 linhas importadas
Importação encerrada com sucesso, sem advertências.


-- Realizando conexão com usuário DBA
C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 08:40:12 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Verificando a localização da tabela EMP após a importação
SYS> select owner,table_name,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME TABLESPACE_NAME
------------------------ ------------------------ ---------------------------
USUARIO_A EMP TBS_A
USUARIO_B EMP TBS_B

Podemos ver no resultado acima que a tabela EMP foi importada diretamente para o tablespace padrão do usuário USUARIO_B. Neste caso, podemos concluir que uma tabela não será importada para o tablespace definido no arquivo dump de exportação se o usuário de destino não tiver cota de tablespace no mesmo.

Irei agora realizar um exemplo prático utilizando os utilitários Data Pump Export/Import (expdp/impdp) disponíveis à partir do Oracle 10g. Para isso, irei dropar o usuário USUARIO_B e criá-lo novamente. Irei também gerar um novo arquivo de dump utilizando o utilitário expdp.

SYS> drop user usuario_b cascade;

Usuário eliminado.

SYS> create user usuario_b identified by senha default tablespace tbs_b;

Usuário criado.

SYS> grant connect,resource to usuario_b;

Concessão bem-sucedida.

-- Verificando o caminho para onde os arquivos dump serão gerados
SYS> select * from dba_directories;

OWNER DIRECTORY_NAME DIRECTORY_PATH
------------ --------------------- ---------------------------------------
SYS DATA_PUMP_DIR C:\oraclexe\app\oracle\admin\XE\dpdump\

-- Realizando a exportação do usuário USUARIO_A
C:\>expdp system/manager DIRECTORY=DATA_PUMP_DIR DUMPFILE=usuario_a.dp SCHEMAS=usuario_a

Export: Release 10.2.0.1.0 - Production on Sexta-Feira, 10 Outubro, 2008 08:45:12

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Iniciando "SYSTEM"."SYS_EXPORT_SCHEMA_01": system/******** DIRECTORY=DATA_PUMP_DIR
DUMPFILE=usuario_a.dp SCHEMAS=usuario_a
Estimativa em andamento com o método BLOCKS...
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE_DATA
Estimativa total usando o método de BLOCKS: 0 KB
Processando o tipo de objeto SCHEMA_EXPORT/USER
Processando o tipo de objeto SCHEMA_EXPORT/SYSTEM_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/ROLE_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/DEFAULT_ROLE
Processando o tipo de objeto SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE
. . exportou "USUARIO_A"."EMP" 0 KB 0 linhas
Tabela-mestre "SYSTEM"."SYS_EXPORT_SCHEMA_01" carregada/descarregada com sucesso
******************************************************************************
Conjunto de arquivos de dump para SYSTEM.SYS_EXPORT_SCHEMA_01 é:
C:\ORACLEXE\APP\ORACLE\ADMIN\XE\DPDUMP\USUARIO_A.DP
O job "SYSTEM"."SYS_EXPORT_SCHEMA_01" foi concluído com sucesso em 08:45:17

Após a geração do arquivo de dump, irei abaixo usar o utilitário impdp para realizar a importação do mesmo para o usuário de destino USUARIO_B utilizando as cláusulas REMAP_SCHEMA e REMAP_TABLESPACE:

-- Realizando a importação do dump de exportação
C:\>impdp system/manager DIRECTORY=DATA_PUMP_DIR DUMPFILE=usuario_a.dp
remap_schema=USUARIO_A:USUARIO_B
remap_tablespace=TBS_A:TBS_B

Import: Release 10.2.0.1.0 - Production on Sexta-Feira, 10 Outubro, 2008 08:49:03

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Tabela-mestre "SYSTEM"."SYS_IMPORT_FULL_02" carregada/descarregada com sucesso
Iniciando "SYSTEM"."SYS_IMPORT_FULL_02": system/******** DIRECTORY=DATA_PUMP_DIR
DUMPFILE=usuario_a.dp remap_schema=USUARIO_A:USUARIO_B remap_tablespace=TBS_A:TBS_B
Processando o tipo de objeto SCHEMA_EXPORT/USER
ORA-31684: O tipo de objeto USER:"USUARIO_B" já existe
Processando o tipo de objeto SCHEMA_EXPORT/SYSTEM_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/ROLE_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/DEFAULT_ROLE
Processando o tipo de objeto SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE_DATA
. . importou "USUARIO_B"."EMP" 0 KB 0 linhas
O job "SYSTEM"."SYS_IMPORT_FULL_02" foi concluído com 1 erro(s) em 15:17:06


-- Realizando conexão com usuário DBA
C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 08:55:02 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Verificando a localização da tabela EMP após a importação
SYS> select owner,table_name,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME TABLESPACE_NAME
------------------------ ------------------------ ------------------------
USUARIO_A EMP TBS_A
USUARIO_B EMP TBS_B

Podemos perceber pelo resultado acima, que apesar de o privilégio de sistema UNLIMITED TABLESPACE ter sido concedido de forma implícita através da role RESOURCE, a tabela foi importada para o tablespace padrão do usuário USUARIO_B, simplesmente pelo fato de no comando de importação eu explicitamente ter especificado a cláusula REMAP_TABLESPACE.

OBS: Vale a pena salientar que o parâmetro TRANSFORM do utilitário impdp na qual pode ter o valor SEGMENT_ATTRIBUTES ou STORAGE, também pode ser utilizado para fazer com que as tabelas também sejam criadas no tablespace padrão do usuário de destino. O valor STORAGE (transform=storage:N:table) remove a cláusula de armazenamento (STORAGE) dos comandos DDL (Data Definition Language) embutidas nos comandos de criação das tabelas. Neste caso a cláusula REMAP_TABLESPACE deverá também ser utilizada em conjunto. Já o valor SEGMENT_ATTRIBUTES (transform=segment_attributes:N) remove todos os atributos físicos de armazenamento dos segmentos, incluindo o tablespace. Neste caso não será necessário utilizar a cláusula REMAP_TABLESPACE, isto porque todas as tabelas serão criadas de acordo com o tablespace padrão do usuário de destino na qual serão usados os atributos de armazenamento definidos no mesmo.

Agora uma outra questão: E quando as tabelas contêm colunas de tipos de dados LONG RAW ou BLOB? Bem, no caso de usar os tradicionais utilitários (exp/imp), teremos problemas apenas com as tabelas que possuem colunas de tipos de dados LOB. Colunas definidas com tipo de dado LONG RAW não serão problema. Portanto, mesmo que o usuário de destino tenha cota somente no seu tablespace padrão (default), o Oracle tentará importar a tabela que possui a coluna de tipo de dado LOB para o tablespace de origem especificado no arquivo de exportação. Irei abaixo demonstrar um exemplo prático:

-- Conectando com o usurário USUARIO_B para confirmar cota ilimitada para todos os
-- tablespaces
C:\>sqlplus usuario_b/senha

USUARIO_B> select * from session_privs;

PRIVILEGE
----------------------------------------
CREATE SESSION
UNLIMITED TABLESPACE
CREATE TABLE
CREATE CLUSTER
CREATE SEQUENCE
CREATE PROCEDURE
CREATE TRIGGER
CREATE TYPE
CREATE OPERATOR
CREATE INDEXTYPE

10 linhas selecionadas.

-- Conectando com o usuário USUARIO_A
USUARIO_B> connect usuario_a/senha;
Conectado.

-- Criando a tabela DEPT com coluna de tipo de dados LONG RAW
USUARIO_A> create table dept (id long raw);

Tabela criada.

-- Criando a tabela DEPT2 com coluna de tipo de dados BLOB
USUARIO_A> create table dept2 (id blob);

Tabela criada.

USUARIO_A> exit
Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Realizando a exportação do schema USUARIO_A
C:\>exp usuario_a/senha file=usuario_a statistics=none

Export: Release 10.1.0.2.0 - Production on Sex Out 10 08:58:40 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Exportação executada no conjunto de caracteres de WE8PC850 e AL16UTF16 NCHAR
co servidor usa WE8MSWIN1252 conjunto de caracteres
. exportando objetos e ações procedurais anteriores ao esquema
. exportando os nomes da biblioteca de função externa para usuário USUARIO_A
. exportando sinônimos do tipo PÚBLICO
. exportando sinônimos do tipo privado
. exportando definições de tipos de objeto para usuário USUARIO_A
Sobre exportar objetos de USUARIO_A ...
. exportando vínculos de banco de dados
. exportando números de seqüência
. exportando definições de cluster
. sobre exportar tabelas de USUARIO_A ... via Caminho Convencional ...
. . exportando tabela DEPT 0 linhas exportadas
. . exportando tabela DEPT2 0 linhas exportadas
. exportando sinônimos
. exportando views
. exportando procedimentos armazenados
. exportando operadores
. exportando restrições referenciais de integridade
. exportando gatilhos
. exportando tipos de índices
. exportando índices funcionais, extensíveis e de bitmap
. exportando ações contabilizáveis
. exportando views materializadas
. exportando logs de snapshot
. exportando filas de serviço
. exportando filhos e grupos de renovação
. exportando dimensões
. exportando objetos e ações procedurais posteriores ao esquema
. exportando estatística
Exportação encerrada com sucesso, sem advertências.


-- Realizando a importação do dump gerado para o schema USUARIO_B
C:\>imp usuario_b/senha file=usuario_a full=y

Import: Release 10.1.0.2.0 - Production on Sex Out 10 09:05:40 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.


Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Arquivo de exportação criado por EXPORT:V10.01.00 via caminho convencional

Advertência: os objetos foram exportados por USUARIO_A; não por você

importação realizada nos conjuntos de caracteres WE8PC850 e NCHAR AL16UTF16
o servidor de importação usa o conjunto de caracteres WE8MSWIN1252
. importando objetos de USUARIO_A para USUARIO_B
. . importando table "DEPT" 0 linhas importadas
. . importando table "DEPT2" 0 linhas importadas
Importação encerrada com sucesso, sem advertências.


C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 09:08:01 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Verificando a localização das tabela DEPT e DEPT2 após a importação
SYS> select owner,table_name,initial_extent,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME INITIAL_EXTENT TABLESPACE_NAME
-------------------- -------------------- -------------- -----------------------
USUARIO_A DEPT 65536 TBS_A
USUARIO_A DEPT2 65536 TBS_A
USUARIO_B DEPT 65536 TBS_A
USUARIO_B DEPT2 65536 TBS_A

Podemos ver acima como já esperado, que as tabelas foram importadas para o tablespace especificado no arquivo dump de exportação (TBS_A). Isso porque o usuário USUARIO_B possui cota ilimitada para todos os tablespaces. Abaixo, irei recriar o usuário USUARIO_B novamente de forma a conceder cota de espaço apenas no seu tablesapce padrão (TBS_B). Após realizar essas operações irei importar novamente o arquivo dump de exportação.

SYS> drop user usuario_b cascade;

Usuário eliminado.

SYS> create user usuario_b identified by senha default tablespace tbs_b;

Usuário criado.

SYS> grant connect,resource to usuario_b;

Concessão bem-sucedida.

SYS> alter user usuario_b quota 0 on tbs_a;

Usuário alterado.

SYS> revoke unlimited tablespace from usuario_b;

Revogação bem-sucedida.

SYS> alter user usuario_b quota unlimited on tbs_b;

Usuário alterado.

SYS> exit
Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production


-- Realizando a importação para o usuario USUARIO_B
C:\>imp usuario_b/senha file=usuario_a full=y

Import: Release 10.1.0.2.0 - Production on Sex Out 10 09:12:35 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Arquivo de exportação criado por EXPORT:V10.01.00 via caminho convencional

Advertência: os objetos foram exportados por USUARIO_A; não por você

importação realizada nos conjuntos de caracteres WE8PC850 e NCHAR AL16UTF16
o servidor de importação usa o conjunto de caracteres WE8MSWIN1252
. importando objetos de USUARIO_A para USUARIO_B
. . importando table "DEPT" 0 linhas importadas
IMP-00017: a instrução a seguir falhou com o erro 1536 ORACLE:
"CREATE TABLE "DEPT2" ("ID" BLOB) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS"
" 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAUL"
"T) TABLESPACE "TBS_A" LOGGING NOCOMPRESS LOB ("ID") STORE AS (TABLESPACE ""
"TBS_A" ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10 NOCACHE STORAGE(INIT"
"IAL 65536 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT))"
IMP-00003: Erro Oracle: 1536 encontrado
ORA-01536: cota de espaço excedida para o tablespace 'TBS_A'
Importação encerrada com êxito, com advertências.

Podemos ver acima, que a tabela DEPT que contém a coluna de tipo de dado LONG RAW foi importada sem problemas, mas no caso da tabela DEPT2 que contém a coluna de tipo de dado BLOB, não foi importada. O erro "ORA-01536: cota de espaço excedida para o tablespace 'TBS_A'" que foi emitida no processo acima nos diz que mesmo que o usuário só tenha cota de espaço para um tablespace específico, mesmo assim o Oracle irá tentar de qualquer forma criar a tabela que contém a coluna do de tipo de dado BLOB no tablespace especificado no arquivo dump de exportação. Podemos ver abaixo que somente a tabela DEPT foi importada com sucesso:

C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 09:20:14 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SYS> select owner,table_name,initial_extent,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME INITIAL_EXTENT TABLESPACE_NAME
-------------------- -------------------- -------------- -----------------------
USUARIO_A DEPT 65536 TBS_A
USUARIO_A DEPT2 65536 TBS_A
USUARIO_B DEPT 65536 TBS_B

Como fazer então para resolver este problema? Bem, a solução mais viável é criar todas as tabelas que contém colunas de tipo de dado LOB (BLOB, CLOB) antes de realizar a importação do arquivo. Ao realizar a importação, será necessário incluir a cláusula IGNORE=Y do comando imp. Veja o exemplo abaixo:

C:\>sqlplus usuario_b/senha

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Criando a tabela DEPT2 no schema USAURIO_B
USUARIO_B> create table dept2 (id blob);

Tabela criada.

USUARIO_B> exit
Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Realizando a importação
C:\>imp usuario_b/senha file=usuario_a full=y ignore=y

Import: Release 10.1.0.2.0 - Production on Sex Out 10 09:28:04 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.


Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Arquivo de exportação criado por EXPORT:V10.01.00 via caminho convencional

Advertência: os objetos foram exportados por USUARIO_A; não por você

importação realizada nos conjuntos de caracteres WE8PC850 e NCHAR AL16UTF16
o servidor de importação usa o conjunto de caracteres WE8MSWIN1252
. importando objetos de USUARIO_A para USUARIO_B
. . importando table "DEPT" 0 linhas importadas
. . importando table "DEPT2" 0 linhas importadas
Importação encerrada com sucesso, sem advertências.


C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 09:32:16 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Verificando a localização das tabelas DEPT e DEPT2 após a importação
SYS> select owner,table_name,initial_extent,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME INITIAL_EXTENT TABLESPACE_NAME
-------------------- -------------------- -------------- -----------------------
USUARIO_A DEPT 65536 TBS_A
USUARIO_A DEPT2 65536 TBS_A
USUARIO_B DEPT 65536 TBS_B
USUARIO_B DEPT2 65536 TBS_B

Podemos ver acima que a tabela DEPT2 caso tivesse registros, teria os seus dados populados sem problemas. Uma outra maneira que não é muito ortodoxa, seria a de editar o arquivo dump de exportação com um editor hexadecimal como o Editpad, ou o Frhed de forma a substituir o tablespace original pelo tablespace de destino. Outra alteração que poderia ser feita seria a de informar um novo valor para INITAL EXTENT para as tabelas existentes no arquivo dump de exportação. Como dito anteriormente, esta não é uma prática comum e nem suportada pela Oracle. Portanto, faça por sua própria conta e risco. No mais, na minha experiência, nunca tive problemas ao editar o arquivo dump.


Voltando novamente à questão original, caso você seja um usuário da versão Oracle 10g ou superior, faça uso dos utilitários Data Pump. Como você verá abaixo, não teremos nenhum problema ao importar dados de tabelas com colunas LOB. Abaixo irei demonstrar a exportação e importação utilizando o Data Pump. Para isso, irei novamente recriar o usuário USUARIO_B.

SYS> drop user usuario_b cascade;

Usuário eliminado.

SYS> create user usuario_b identified by senha default tablespace tbs_b;

Usuário criado.

SYS> grant connect,resource to usuario_b;

Concessão bem-sucedida.


-- Realizando a exportação do schema USAURIO_A utilizando o Export Data Pump
C:\>expdp system/manager DIRECTORY=DATA_PUMP_DIR DUMPFILE=usuario_a.dp SCHEMAS=usuario_a

Export: Release 10.2.0.1.0 - Production on Sexta-Feira, 10 Outubro, 2008 09:33:20

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Iniciando "SYSTEM"."SYS_EXPORT_SCHEMA_01": system/******** DIRECTORY=DATA_PUMP_DIR
DUMPFILE=usuario_a.dp SCHEMAS=usuario_a
Estimativa em andamento com o método BLOCKS...
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE_DATA
Estimativa total usando o método de BLOCKS: 0 KB
Processando o tipo de objeto SCHEMA_EXPORT/USER
Processando o tipo de objeto SCHEMA_EXPORT/SYSTEM_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/ROLE_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/DEFAULT_ROLE
Processando o tipo de objeto SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE
. . exportou "USUARIO_A"."DEPT" 0 KB 0 linhas
. . exportou "USUARIO_A"."DEPT2" 0 KB 0 linhas
Tabela-mestre "SYSTEM"."SYS_EXPORT_SCHEMA_01" carregada/descarregada com sucesso
******************************************************************************
Conjunto de arquivos de dump para SYSTEM.SYS_EXPORT_SCHEMA_01 é:
C:\ORACLEXE\APP\ORACLE\ADMIN\XE\DPDUMP\USUARIO_A.DP
O job "SYSTEM"."SYS_EXPORT_SCHEMA_01" foi concluído com sucesso em 09:33:25


-- Realizando a importação para o usuário USAURIO_B utilizando o Import Data Pump
C:\>impdp system/manager DIRECTORY=DATA_PUMP_DIR DUMPFILE=usuario_a.dp
remap_schema=USUARIO_A:USUARIO_B
remap_tablespace=TBS_A:TBS_B

Import: Release 10.2.0.1.0 - Production on Sexta-Feira, 10 Outubro, 2008 09:40:31

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Tabela-mestre "SYSTEM"."SYS_IMPORT_FULL_02" carregada/descarregada com sucesso
Iniciando "SYSTEM"."SYS_IMPORT_FULL_02": system/******** DIRECTORY=DATA_PUMP_DIR
DUMPFILE=usuario_a.dp remap_schema=USUARIO_A:USUARIO_B remap_tablespace=TBS_A:TBS_B
Processando o tipo de objeto SCHEMA_EXPORT/USER
ORA-31684: O tipo de objeto USER:"USUARIO_B" já existe
Processando o tipo de objeto SCHEMA_EXPORT/SYSTEM_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/ROLE_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/DEFAULT_ROLE
Processando o tipo de objeto SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE_DATA
. . importou "USUARIO_B"."DEPT" 0 KB 0 linhas
. . importou "USUARIO_B"."DEPT2" 0 KB 0 linhas
O job "SYSTEM"."SYS_IMPORT_FULL_02" foi concluído com 1 erro(s) em 13:48:34


C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 09:42:03 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Verificando a localização das tabelas DEPT e DEPT2 após a importação
SYS> select owner,table_name,initial_extent,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME INITIAL_EXTENT TABLESPACE_NAME
-------------------- ----------------------- -------------- -----------------------
USUARIO_A DEPT 65536 TBS_A
USUARIO_A DEPT2 65536 TBS_A
USUARIO_B DEPT 65536 TBS_B
USUARIO_B DEPT2 65536 TBS_B

Podemos ver no resultado acima que utilizando a cláusula REMAP_TABLESPACE do utilitário impdp, não teremos nenhum problema.


MODO DE IMPORTAÇÃO VIA REDE

O mais interessante vou deixar por último. Abaixo irei demonstrar como podemos realizar uma exportação e uma importação ao mesmo tempo (on the fly) utilizando o Import Data Pump. No modo de importação via rede (Network Mode Import), eu utilizarei a cláusula NETWORK_LINK do utilitário de importação Data Pump a fim de exportar o schema USUARIO_A e importar os seus dados para o schema USAURIO_B sem a necessidade de gerar um arquivo de exportação e sem a necessidade de criar o schema de destino USUARIO_B. O utilitário impdp fará todo este trabalho para mim. A cláusula NETWORK_LINK é usada para informamos o serviço TNS ou um link de banco de dados (DATABASE LINK) do servidor remoto onde está o usuário que desejamos exportar. Portanto, podemos realizar este tipo de exportação/importação entre bancos que estão localizados em servidores distintos. Logicamente, os mesmos deverão estar usando a mesma versão de banco de dados (Oracle 10g). Como no meu caso o banco remoto e o banco local é o mesmo, utilizarei o serviço de rede XE definido no arquivo TNSNAMES.ORA.

-- Dropando o schema USUARIO_B
SYS> drop user usuario_b cascade;

Usuário eliminado.

SYS> exit
Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production


-- Realizando a exportação/importação no modo de rede
C:\>impdp system/manager schemas=usuario_a
network_link=XE remap_schema=USUARIO_A:USUARIO_B
remap_tablespace=TBS_A:TBS_B

Import: Release 10.2.0.1.0 - Production on Sexta-Feira, 10 Outubro, 2008 09:44:51

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Conectado a: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Iniciando "SYSTEM"."SYS_IMPORT_SCHEMA_01": system/******** schemas=usuario_a
network_link=XE remap_schema=usuario_a:usuario_b remap_tablespace=tbs_a:tbs_b
Estimativa em andamento com o método BLOCKS...
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE_DATA
Estimativa total usando o método de BLOCKS: 0 KB
Processando o tipo de objeto SCHEMA_EXPORT/USER
Processando o tipo de objeto SCHEMA_EXPORT/SYSTEM_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/ROLE_GRANT
Processando o tipo de objeto SCHEMA_EXPORT/DEFAULT_ROLE
Processando o tipo de objeto SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processando o tipo de objeto SCHEMA_EXPORT/TABLE/TABLE
. . importou "USUARIO_B"."DEPT" 0 linhas
. . importou "USUARIO_B"."DEPT2" 0 linhas
O job "SYSTEM"."SYS_IMPORT_SCHEMA_01" foi concluído com sucesso em 09:44:55


C:\>sqlplus / as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Sex Out 10 09:45:41 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Verificando a localização das tabelas DEPT e DEPT2 após a importação
SYS> select owner,table_name,initial_extent,tablespace_name
2 from dba_tables
3 where owner in ('USUARIO_A','USUARIO_B');

OWNER TABLE_NAME INITIAL_EXTENT TABLESPACE_NAME
-------------------- ----------------------- -------------- -----------------------
USUARIO_A DEPT 65536 TBS_A
USUARIO_A DEPT2 65536 TBS_A
USUARIO_B DEPT 65536 TBS_B
USUARIO_B DEPT2 65536 TBS_B

Podemos ver no resultado acima que o utilitário impdp exportou os dados do schema USUARIO_A, criou o usuário USUARIO_B e importou os dados para o mesmo no tablespace TBS_B. Irei abaixo conectar com o usuário USUARIO_B.

SYS> connect usuario_b/senha
ERROR:
ORA-01017: invalid username/password; logon denied

Advertência: Você não está mais conectado ao ORACLE.

Podemos ver acima que a conexão falhou mesmo os usuários USUÁRIO_A e USAURIO_B estarem utilizando a mesma senha. Isto ocorre pelo fato de o Oracle utilizar o nome do usuário em seu algoritmo interno para geração da senha hash. Portanto, será necessário definirmos uma nova senha para o usuário USUARIO_B

@> connect / as sysdba
Conectado.

SYS> alter user usuario_b identified by senha;

Usuário alterado.

SYS> connect usuario_b/senha
Conectado.

Pronto. Para ficar claro com relação ao problema da senha que foi copiada do usuário USUARIO_A para o usuário USUARIO_B, veja a demonstração abaixo:

SYS> create user legatti identified by minhasenha;

Usuário criado.

-- Verificando o valor hash criado para a senha
SYS> select password from dba_users where username='LEGATTI';

PASSWORD
------------------------------
C5942314C0B20883

-- Criando o usuário LEGATTI2 utilizando a senha hash do usuário LEGATTI
SYS> create user legatti2 identified by values 'C5942314C0B20883';

Usuário criado.

SYS> grant create session to legatti,legatti2;

Concessão bem-sucedida.

-- Testando a conexão com o usuário LEGATTI
SYS> connect legatti/minhasenha;
Conectado.

-- Testando a conexão com o usuário LEGATTI2
LEGATTI> connect legatti2/minhasenha;
ERROR:
ORA-01017: invalid username/password; logon denied

Advertência: Você não está mais conectado ao ORACLE.

Podemos então concluir que para a geração do valor hash da senha de um usuário de banco de dados Oracle, o nome do usuário é utilizado juntamente com a senha informada para geração do valor hash da senha.



11 comentários:

Anônimo disse...

Eduardo! Rapaz! Parabéns, ficou muito boa a sua explicação.

RodrigoAlmeida disse...

Eduardo,

Parabéns cara! Ficou bem claro como funciona o processo de import/export. Super bacana.

Abraços,

Rodrigo Almeida

Anônimo disse...

Parabéns pela sua paciência em escrever com tantos detalhes.

Seu blog virou meu jornal diários.

Abs,
JP

Eduardo Legatti disse...

Olá a todos,

Quero apenas agradecer os comentários postados por vocês. Obrigado. Realmente este artigo me tomou um pouco mais de tempo pelo fato de querer tentar ao máximo compartilhar toda a minha experiência em relação ao assunto.

Até mais ...

Anônimo disse...

Parabéns pelo artigo...Me ajudou bastante! Sem ele não teria conseguido.

Flávio Soares disse...

Muito bom o post Eduardo ficou extramente claro! Muito boa a explicação

Parabéns ...

Eduardo Legatti disse...

Olá Flávio,

Obrigado pela visita ;-)

Abraços e até mais...

Anônimo disse...

Parabéns pelo o artigo Legatti!
Uma duvida: Estou tentando fazer um dump pelo o expdp, porém no banco de destino, há alguns campos que o tamanho está diferente está menor que o banco de origem, há alguma forma de subir estes dados mesmo com o tamanho da coluna menor no banco de destino, algum parâmetro no impdp?Para forçar a carga?
Muito obrigado.

Eduardo Legatti disse...

Olá Anônimo,

Você está querendo realizar um APPEND (TABLE_EXISTS_ACTION) em uma tabela existente? A tabela de destino tem o mesmo nome e mesma estrutura da tabela de origem, o que diferencia é o tamanho das colunas? Talvez seja mais prático você importar em uma tabela com outro nome e depois fazer um INSERT SELECT? Dá uma olhada nas cláusulas REMAP_TABLE e REMAP_DATA do impdp.

Abraços,

Legatti

Airton Roos disse...

Boa tarde, tudo beleza?

Muito legal a sua explicação, mas fiquei com uma dúvida. Usando o EXPDP faço a exportação de um schema que esta na base A, e utilizando o IMPDP importo os objetos em outro schema que esta na base B, com tablespace diferente do schema de origem, os índices que pertencem ao schema de origem serão criados na tablespace do schema de destino?

Ou será necessário fazer um rebuild dos índices?

Obrigado.

Airton

Eduardo Legatti disse...

Olá Airton,

Nesse caso você terá que usar a cláusula rema_schema em conjunto com a cláusula remap_tablespace do comando impdp para mapear as tablespaces de origem no destino. Não precisa efetuar rebuild dos índices, porque eles já são criados na importação.

Abraços,

Legatti

Postagens populares