Arquivo mensal: setembro 2014

ORACLE 12C – Renomear Datafile Online

Antes da versão 12c do Oracle, a tarefa de renomear ou mudar um datafile de local, era necessário por a tablespace OFFLINE.

Os passos necessários para essa tarefa são:

  • Colocar a tablespace offline.
  • Mover or renomear a tablespace (comando do S.O.)
  • Renomear o datafile pelo Oracle (Alter Database datafile rename file)
  • Colocar a tablespace online.

Esses passos não se aplicam as tablespaces SYSTEM e UNDO, que requerem que a base esteja em mount para  renomear ou mover datafiles ou dependendo do tamanho desses arquivos o uso do RMAN também pode ser necessário para esta tarefa.

O Oracle 12c trás uma nova funcionalidade, na qual é possível realizar esta atividade online, ou seja, enquanto os usuários estão acessando o datafile. Esta tarefa pode ser feita por um único comando.
O comando “ALTER DATABASE MOVE DATAFILE” copia/renomeia o datafile para a nova localização, atualiza o control file e exclui o datafile antigo.

Algumas tarefas comuns que agora podem ser feitas de forma online:

  • Mover datafiles de um tipo de storage para outro;
  • Mover datafiles que não são acessados frequentemente para um storage de menor custo ;
  • Mover o database para dentro do Oracle Automatic Storage Management (Oracle ASM)

Nesse post vou mostrar como mover ou simplesmente mudar o nome de um datafile online.

  1. Verificando a localização dos datafiles
    SQL>  select name from v$datafile;

    NAME
    ——————————————————————————–
    /u01/app/oracle/oradata/rdba/system01.dbf
    /u01/app/oracle/oradata/rdba/sysaux01.dbf
    /u01/app/oracle/oradata/rdba/undotbs01.dbf
    /u01/app/oracle/oradata/rdba/users01.dbf
    SQL>

  2. Mudando a localização do datafile

    SQL> alter database move datafile ‘/u01/app/oracle/oradata/rdba/users01.dbf’ to
    2  ‘/u01/app/oracle/oradata/users01.dbf’;

    Database altered.
    SQL>

  3. Verificando a localização dos datafiles novamente(localização do datafile alterada)

    SQL> select name from v$dbfile;

    NAME
    ——————————————————————————–
    /u01/app/oracle/oradata/rdba/undotbs01.dbf
    /u01/app/oracle/oradata/rdba/sysaux01.dbf
    /u01/app/oracle/oradata/rdba/system01.dbf
    /u01/app/oracle/oradata/users01.dbf
    SQL>

  4. Mudando a localização do datafile para a localização anterior

    SQL>  alter database move datafile  ‘/u01/app/oracle/oradata/users01.dbf’ to
    2   ‘/u01/app/oracle/oradata/rdba/users01.dbf’ keep;

    Database altered.
    SQL>

    OBS: o uso da opção keep no comando de mover datafile remove o arquivo físico do diretório antigo

  5. verificando a localização do arquivo pelo S.O
    a – No Diretório antigo
    ls -l /u01/app/oracle/oradata/users01.dbf
    ls: cannot access /u01/app/oracle/oradata/users01.dbf: No such file or direct
    b – No Diretório atual
    ls -l /u01/app/oracle/oradata/rdba/users01.dbf
    -rw-r—– 1 oracle dba 24911872 Sep 15 20:01 /u01/app/oracle/oradata/rdba/us01.dbf

    OBS: No caso de mover o datafile para um local aonde tenha uma cópia antiga do arquivo de dados, você pode usar a opção REUSE para substituí-lo.
    Tenha muito cuidado com esta opção para não substituir o arquivo de dados com o mesmo nome que esteja em uso por outro banco de dados.

Export Remoto com Datapump

Neste artigo irei demonstrar como é possível fazer a importação de uma tabela acessando o banco de dados de forma remota. Para efetuar devemos usar o opção NETWORK_LINK com datapump.

Para usar NETWORK_LINK você deve seguir estes passos:

1 – Crie uma entrada de TNS para o banco que se deseja exportar no arquivo tnsnames.ora
2 – Teste com tnsping
3 – Criar um  database link para o banco de dados remoto
4 – Especifique o database link como NETWORK_LINK na sua sintaxe expdp ou impdp

Uma vantagem da opção NETWORK_LINK é que você não precisa de exportação e importação, a exportação e importação é feita num único tiro da origem para o destino.

Para estes testes foram criados o usuário teste no servidor de origem , e o usuario teste2 no servidor de destino (Servidor2).  No banco de dados origem (Servidor1), foram criadas algumas tabelas com conteúdos.

Servidor 1
SO Linux
Versão Oracle 12cr1

Servidor 2
SO Linux
Versão Oracle 11gr2

No servidor 1 (12c)

1 – foi criado um usuário chamado teste e 3 tabelas chamadas t1,t2,t3 com carga nas tabelas.

SQL>  BEGIN
FOR v_Count IN 1..5 LOOP
INSERT INTO teste.t1 (X1)
VALUES (v_count);
END LOOP;
END;
/   2    3    4    5    6    7

PL/SQL procedure successfully completed.
SQL> commit;

Commit complete.

SQL> select count(1) from teste.t1;
COUNT(1)
———-
5

SQL> BEGIN
FOR v_Count IN 1..10 LOOP
INSERT INTO teste.t2 (X1)
VALUES (v_count);
END LOOP;
END;
/  2    3    4    5    6    7

PL/SQL procedure successfully completed.
SQL> commit;

Commit complete.

SQL> BEGIN
FOR v_Count IN 1..20 LOOP
INSERT INTO teste.t3 (X2)
VALUES (v_count);
END LOOP;
END;
/  2    3    4    5    6    7

PL/SQL procedure successfully completed.
SQL> commit;

Commit complete.

No servidor 2 (11g)

2 – criar um database link para conexao com a base no servidor 1

SQL> create public database link teste connect to teste identified by teste
2  using ‘db12c’;
Database link created.

3 – teste de acesso usando DBLINK

SQL> select count(*) from t3@teste;
COUNT(*)
———-
20

4 – export remoto do esquema teste remoto (ambiente 12c) com datapump usando dblink

SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 – 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options
oracle@linux-g4wa:~> expdp system/teste  tables=teste.t1,teste.t2,teste.t3 remap_schema=teste:teste2  logfile=teste.log schemas=teste NETWORK_LINK=teste DIRECTORY=DATA_PUMP_DIR

Import: Release 11.2.0.1.0 – Production on Wed Aug 6 13:27:50 2014

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 – 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Starting “SYSTEM”.”SYS_IMPORT_TABLE_01″:  system/******** tables=teste.t1,teste.t2,teste.t3 remap_schema=teste:teste2 DIRECTORY=DATA_PU
MP_DIR network_link=teste
Estimate in progress using BLOCKS method…
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 192 KB
Processing object type TABLE_EXPORT/TABLE/TABLE
. . imported “TESTE2”.”T1″                                    5 rows
. . imported “TESTE2”.”T2″                                   10 rows
. . imported “TESTE2”.”T3″                                   20 rows
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Job “SYSTEM”.”SYS_IMPORT_TABLE_01″ successfully completed at 13:28:06

5 – testes com a tabela importada

oracle@linux-g4wa:~> sqlplus / as sysdba

SQL*Plus: Release 11.2.0.1.0 Production on Fri Aug 1 15:10:11 2014
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 – 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> desc teste2.t1
Name                                      Null?    Type
—————————————– ——– —————————-
X1                                                 NUMBER

SQL> select count(*) from teste2.t3;
COUNT(*)
———-
20

Antes de fazer este tipo de operação deve ser avaliado qual melhor método, se o método tradicional com exportação tradicional para um arquivo dmp,  seguido de um FTP ou a exportação remota via remote_link, pois o tamanho da base e do link de dados devem ser levados em consideração, pois o método tradicional pode ser uma solução mais rápida se você uma conexão de rede com a largura de banda limitada

Para mais informações sobre as importações utilizando dblink, consultar o manual “Oracle Database Utilities, 11g Release 2 (11.2)“.

ORACLE 12C – Colunas Identity – Parte 2

No último post, começamos a falar sobre colunas Identity, uma nova funcionalidade do Oracle 12c, no post de hoje estaremos continuando e concluindo sobre este tema.

4 – Criação de uma tabela com a cláusula By Default com restrição Not Null.

Esta definição de uma coluna, permite a utilização de valores externos e gera
valores  quando se insere um valor null a uma  coluna criada com a cláusula By Default Not Null;

SQL> Create Table  teste.Identity_Default_Not_Null_1
(Col_1  Number Generated By Default On Null As Identity,
Col_2 Varchar2(50));  2    3

Table created.
SQL>

SQL> Insert Into  teste.Identity_Default_Not_Null_1
Values  (Null,’Prova’);   2

1 row created.
SQL>

SQL>   Select * From  teste.Identity_Default_Not_Null_1;

COL_1 COL_2
———- ————————————————–
1 Prova

SQL>

Como podemos ver neste caso,um erro não é gerado pelo insert como no ultimo exemplo do post anterior.  Esta cláusula  gera valores para a coluna pare que esta não contenha valores nulos, sem levar em consideração que os valores de entrada sejam consecutivos.

5 – Opções sobre o uso da cláusula Identity

O exemplo abaixo mostra como criar uma Tabela  com a cláusula Identity com um valor inicial de 100 e com um incremento de 10.

SQL> Create Table  teste.Identity_Start_Increment
( Col_1 Number Generated Always As Identity  (Start With 100
Increment By 10),   Col_2 Varchar2(50));
2    3
Table created.

SQL>

Realizamos un Insert de 10 registros

SQL> Insert Into  teste.Identity_Start_Increment (Col_2)
Select Level||’ Numero’
From Dual
Connect by level<=10;  2    3    4

10 rows created.
SQL>

Vemos o resultado da cláusula Insert

SQL>  Select *  From  teste.Identity_Start_Increment;

COL_1 COL_2
———- ————————————————–
100 1 Numero
110 2 Numero
120 3 Numero
130 4 Numero
140 5 Numero
150 6 Numero
160 7 Numero
170 8 Numero
180 9 Numero
190 10 Numero

10 rows selected.

SQL>

Como mostrado o valor da coluna col_1 começa em 100 e vai aumentando em 10.

Verificando as colunas IDENTITY

SQL>  Select Table_Name, Column_Name,Data_Default From Dba_Tab_Columns
Where  Table_Name=’IDENTITY_DEFAULT_NOT_NULL_1′;

TABLE_NAME                     COLUMN_NAME          DATA_DEFAULT
—————————— ——————– ——————————
IDENTITY_DEFAULT_NOT_NULL_1    COL_2
IDENTITY_DEFAULT_NOT_NULL_1    COL_1                “TESTE”.”ISEQ$$_92301″.nextval

SQL>

SQL> Select  Last_Number, Increment_By, Cache_Size,  Max_Value
From  dba_Sequences
Where  Sequence_Name=’ISEQ$$_92301′;  2    3

LAST_NUMBER INCREMENT_BY CACHE_SIZE  MAX_VALUE
———– ———— ———- ———-
21            1         20 1.0000E+28
SQL>

6 – deletando tabelas com coluna Identity

6.1 – deletando uma tabela com uma coluna Identity a sequencia não é deletada.

drop table teste.IDENTITY_DEFAULT_NOT_NULL_1;

Table dropped.

SQL> Select  Last_Number, Increment_By, Cache_Size,  Max_Value
From  dba_Sequences
Where  Sequence_Name=’ISEQ$$_92301′;  2    3

LAST_NUMBER INCREMENT_BY CACHE_SIZE  MAX_VALUE
———– ———— ———- ———-
21            1         20 1.0000E+28
SQL>

6.2 – Restaurando a tabela e dropando a mesma com a opção purge

SQL> FLASHBACK TABLE  teste.IDENTITY_DEFAULT_NOT_NULL_1 to before drop;

Flashback complete.

SQL> SQL> desc  teste.IDENTITY_DEFAULT_NOT_NULL_1
Name                                      Null?    Type
—————————————– ——– —————————-
COL_1                                     NOT NULL NUMBER
COL_2                                              VARCHAR2(50)
SQL>

SQL> drop table teste.IDENTITY_DEFAULT_NOT_NULL_1 purge;

Table dropped.

SQL> Select  Last_Number, Increment_By, Cache_Size,  Max_Value
From  dba_Sequences
Where  Sequence_Name=’ISEQ$$_92301′;  2    3

no rows selected
SQL>

Colocando a cláusula purge a sequencia também é deletada.

7 – Comparando tempo de resposta entre insert com colunas Identity e uso de sequences

Agora iremos mostrar o tempo de resposta da cláusula Identity.  Vamos inserir 100.000 registros numa tabela, vamos tomar o tempo cada um:

7.1 –  carregando uma tabela com campo de Identity Allways.

SQL> Create Table  teste.Identity
( Col_1 Number Generated Always As Identity, Col_2 Varchar2(50));  2

Table created.

SQL> Set Timing On
Insert Into teste.Identity   (Col_2)
Select ‘Numero de registro ‘|| Level
From Dual
Connect By  Level<=100000;SQL>   2    3    4

100000 rows created.

Elapsed: 00:00:01.96
SQL>

7.2 – uma nova carga em uma tabela com a coluna definida com By Default

SQL> Insert Into teste.Identity_Default  (Col_2)
Select ‘Numero de registro ‘|| Level
From Dual
Connect By Level<=100000;  2    3    4

100000 rows created.

Elapsed: 00:00:01.76
SQL>

7.3 – Comparando  o tempo de resposta durante a inserção de uma tabela com a opção allways e outra BY DEFAULT ON NULL

Primeiro carregar uma tabela com campo de Identity Allways.

SQL> Insert Into teste.Identity   (Col_2)
Select ‘Numero de registro ‘|| Level
From Dual
Connect By  Level<=100000;  2    3    4

100000 rows created.

Elapsed: 00:00:01.69
SQL>

7.4 –  Carregar uma tabela com uma coluna definida por By Default On Null

SQL>  Create Table  teste.Identity_Default_On_Null
2  (Col_1  Number Generated By Default On Null As Identity, Col_2 Varchar2(50));

Table created.
SQL>

SQL> Insert Into  teste.Identity_Default_On_Null (Col_2)
Select ‘Numero de registro ‘|| Level
From Dual
Connect By  Level<=100000;  2    3    4

100000 rows created.

Elapsed: 00:00:02.01
SQL>

Por ultimo utilizaremos o velho método, já utilizado antes da versão 12c
7.5 – Criando uma tabela sem colunas Identitity e uma sequence para avaliamos o tempo.

SQL> Create Table  teste.Tabela_com_sequence (Col_1 Number,
Col_2 Varchar2(50 Char));  2

Table created.
SQL>

agora vamos criar uma sequencia

SQL>  Create Sequence  teste.Seq_teste
2  Start With 1 Increment By 1;

Sequence created.
SQL>

Agora vamos inserir registros nessa tabela

SQL> Insert Into teste.Tabela_com_sequence
Select  teste.Seq_teste.nextval, ‘Numero de registro ‘|| Level
From Dual
Connect By  Level<=100000;
2    3    4
100000 rows created.

Elapsed: 00:00:01.83
SQL>

8 – Alguns pontos devem  ser observados:

8.1 – Dado uma coluna definida como Identity está vinculada a uma sequencia,no caso de uma instrução insert for abortada, os números da sequência serão perdidos.

8.2 – Caso uma tabela seja exportada com todos os seus valores, devemos observar que a coluna de identity esteja em by default, porque de outra forma teremos um erro.

Conclusão

A inclusão de colunas de Identity é um avanço importante, já que a mesma encapsula a instrução nextval de uma sequência.
Por outro lado, a inclusão de opções,  By Default e By Default On Null, permitem que os valores a serem inseridos possam  ser internos ou externos.
A coisa mais importante neste post  é que demonstramos isso sem quase perder desempenho.

bibliografia

ORACLE-BASE
ASK-TOM                                                                                                                                                             ORACLE Documentation

ORACLE 12C – Colunas Identity – Parte 1

Ola pessoal, depois de alguns dias ausente por conta de muito trabalho estou de volta postando um novo assunto, que por sinal é bem interessante. Falaremos sobre colunas de auto incremento (colunas Identity), presente na  versão 12c do Oracle Database.

Nas Versões anteriores ao ORACLE 12c, as funções de auto incremento de colunas eram feitas a partir de sequences ou de triggers.
A versão 12c introduz um novo conceito, chamado colunas de auto incremento (coluna identity)
O que vem a ser uma coluna identity?
É uma coluna com propriedade auto numérica

Com o Oracle 12c, podemos atribuir diretamente uma sequência nextval como um valor padrão para uma coluna, assim  não é mais necessário  criar uma trigger para preencher a coluna com o valor seguinte da seqüência ou utlizar uma sequence para gerar o proximo sequencial para coluna. Você só precisa declará-la na definição da tabela .

Sintaxe para criação de colunas identity

COLUMN_NAME  GENERATED [ ALWAYS | BY DEFAULT [ ON NULL ] ]AS
IDENTITY  [ ( identity_options ) ]

onde:

ALWAYS – Indica que você deve digitar um valor para essa coluna em uma instrução de inserção,
caso o valor indicado seja um valor nulo, a instrucao retorna um erro ORA-32795.
BY DEFAULT – Permite que você use um valor especificado ao invés do valor identity.
Caso a coluna identity não seja referenciada nas instruções de inserção, um valor para esta coluna é espeficicado automaticamente (identity).
A tentativa de especificar o valor NULL neste caso resulta em um erro, porque as colunas identity são sempre NOT NULL.
BY DEFAULT, se em uma sentença um valor NULL é inserido será gerado um valor nulo [ON NULL],
uma mudanca ocorrerá nesta coluna, e um valor para esta coluna será inserido automaticamente (identity).

Abaixo estaremos demonstrando como funciona a coluna de auto incremento e comparação

1 – Criação de uma tabela com a clausula ALWAYS:

SQL> CREATE TABLE teste.TEST(COL_1 NUMBER GENERATED ALWAYS
AS IDENTITY,
COL_2  VARCHAR2(50));  2    3

Table created.
SQL>

1.1 – Inserção de dados

SQL> Insert Into teste.TEST(col_2) Values  (‘Prova’ );

1 row created.
SQL>

Isso indica que um valor para coluna identity para cada linha inserida é gerado automaticamente.

1.2 – Insert com a coluna identity com valor nulo

SQL> Insert Into teste.Test(col_1,col_2)  Values  (99,’Prova’ );
Insert Into teste.Test(col_1,col_2)  Values  (99,’Prova’ )
*
ERROR at line 1:
ORA-32795: cannot insert into a generated always identity column
SQL>

Esta inserção é realizada, mas retorne um erro;

A cláusula always numa coluna identity cria uma restrição NOT NULL e não permite inserir valores externos nulos.

2 – Criação de tabela com a cláusula BY DEFAULT.

Esta definição da coluna com a cláusula BY DEFAULT permite que você use um valor externo de inserção
e na ausência de um valor para inserir nesta coluna, o valor gerado pela identity será usado.
Esta cláusula não permite valores nulos.

SQL> Create Table teste.Identity_Default (Col_1  Number Generated By Default As Identity,
Col_2 Varchar2(50));  2

Table created.
SQL>

SQL>   Insert Into  teste.Identity_Default values (99,’prova’);

1 row created.
SQL>

SQL>   Select * From teste.Identity_Default;

COL_1 COL_2
———- ————————————————–
99 prova
SQL>

SQL>  Insert Into  teste.Identity_Default(col_2) values (‘Prova2′);

1 row created.
SQL>

SQL> Select * From teste.Identity_Default;

COL_1 COL_2
———- ————————————————–
99 prova
1 Prova2
SQL>

SQL> Insert Into  teste.Identity_Default Values (Null,’Prova’);
Insert Into  teste.Identity_Default Values (Null,’Prova’)
*
ERROR at line 1:
ORA-01400: cannot insert NULL into (“TESTE”.”IDENTITY_DEFAULT”.”COL_1″)

Como podemos ver a primeira instrução Insert inclui um valor para a coluna que tem valor definido.
No segundo insert colocamos o valor inserido como NULL e o valor desta coluna foi gerado pela identity.
Na terceiro insert, inserimos um  valor NULL para a coluna identity, isso produz um erro no qual por características da coluna identity  valores NULL não são permitidos.

Podemos usar a cláusula BY DEFAULT em uma coluna de chave primária, tendo em mente que nenhum valor para esta coluna deve ser inserido por uma instrução INSERT, já que não podemos ter valores duplicados, senão um erro sera gerado pela identity.

3 – Criação de tabela com a clausula BY DEFAULT com restrição Not Null

Esta definição de coluna identity, permite a utilização de valores externos e irá gerar valores quando um valor nulo é inserido uma coluna criada com a cláusula BY DEFAULT NOT NULL.

SQL> Create Table  teste.Identity_Default_Not_Null
(Col_1  Number Generated By Default On Null As Identity,
Col_2 Varchar2(50));  2    3

Table created.
SQL>

SQL> Insert Into  teste.Identity_Default_Not_Null
Values  (Null,’Prova’);
2
1 row created.
SQL>

SQL>   Select * From  teste.Identity_Default_Not_Null;

COL_1 COL_2
———- ————————————————–
1 Prova
SQL>

Neste caso, podemos ver no  exemplo acima  que um erro não foi gerado. Com esta cláusula um valor é gerado para que a coluna não tenha valores nulos, independentemente dos valores já contidos nesta coluna , os novos valores inseridos não serão consecutivos.

SQL> select * from teste.Identity_Default;

COL_1 COL_2
———-    ————————————————–
99       prova
1        Prova2

SQL> Insert Into  teste.Identity_Default Values (Null,’prova3′);
Insert Into  teste.Identity_Default Values (Null,’prova3′)
*
ERROR at line 1:
ORA-01400: cannot insert NULL into (“TESTE”.”IDENTITY_DEFAULT”.”COL_1″)

O erro acima acontece porque tentamos inserir um valor NULL para uma coluna identity.

Usando da cláusula By Default em uma coluna Primary Key, devemos  ter em  mente que nenhum valor deve ser inserido por uma instrução INSERT,  já que não pode haver valores duplicados ou seja, o mesmo valor inserido por uma instrução  e outro produzido pela Identity.

No próximo post veremos a continuação deste assunto.