terça-feira, 15 de janeiro de 2013

Usando o comando MERGE


O comando MERGE é utilizado para selecionar linhas de uma ou mais tabelas (origem) para inserções ou alterações em uma ou mais tabelas (destino).

Este comando permite combinar várias operações para reduzir a complexidade de inserções e e atualizações. Com esse comando é possível combinar as instruções de INSERT,  UPDATE e DELETE, em uma única instrução.

Este comando é mais frequentemente utilizado em aplicações de Data Warehousing durante os processos de ETL (Extract, Transform e Load - extração, transformação e carregamento).


Requisitos mínimos

Como o comando MERGE combina operações de INSERT, UPDATE e DELETE, o usuário deverá ter os privilégios de (gravação e leitura) na tabela (destino) e claro, o privilégio de leitura na tabela (origem). Para o uso da cláusula de DELETE na tabela (origem) também é necessário o privilégio.


Sintaxe do comando

MERGE [hints] INTO [nome_tabela]
USING [nome_tabela_visão_ou_consulta]
   ON ([condição])
 WHEN MATCHED THEN [cláusula_de_update]
      DELETE [cláusula_where]
 WHEN NOT MATCHED THEN [cláusula_de_insert]
     [LOG ERRORS [cláusula_de_log_erros][REJECT LIMIT [inteiro | ilimitado]];


Criando o ambiente de testes

Para a criação do ambiente de testes foi criado o bom e velho usuário SCOTT.

CREATE USER scott IDENTIFIED BY tiger         
 DEFAULT   TABLESPACE users
 TEMPORARY TABLESPACE temp;

GRANT CONNECT, RESOURCE TO scott;

ALTER USER scott QUOTA UNLIMITED ON users;


Criação das tabelas DEPT e DEPT_ONLINE.

CREATE TABLE dept
       (DEPTNO NUMBER(2),
        DNAME  VARCHAR2(14),
        LOC    VARCHAR2(13));

INSERT INTO DEPT VALUES (10, 'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20, 'RESEARCH',  'DALLAS');
INSERT INTO DEPT VALUES (30, 'SALES',     'CHICAGO');
INSERT INTO DEPT VALUES (40, 'OPERATIONS','BOSTON');

COMMIT;

CREATE TABLE dept_online
       (DEPTNO NUMBER(2),
        DNAME  VARCHAR2(14),
        LOC    VARCHAR2(13));

INSERT INTO DEPT_ONLINE VALUES (40, 'OPERATIONS',  'BOSTON');
INSERT INTO DEPT_ONLINE VALUES (20, 'RESEARCH DEV','DALLAS');
INSERT INTO DEPT_ONLINE VALUES (50, 'ENGINEERING', 'WEXFORD');
INSERT INTO DEPT_ONLINE VALUES (60, 'MANAGER',     'MIAMI');

COMMIT;

Exemplos de utilização do comando MERGE

1o. Exemplo

Este exemplo irá mesclar os valores da tabela DEPT_ONLINE com a tabela chamada DEPT:

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON


SQL> SELECT * FROM dept_online;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        40 OPERATIONS     BOSTON
        20 RESEARCH DEV   DALLAS
        50 ENGINEERING    WEXFORD
        60 MANAGER        MIAMI

SQL> MERGE INTO dept d
     USING (SELECT deptno, dname, loc
              FROM dept_online) o
     ON (d.deptno = o.deptno)
     WHEN MATCHED THEN
          UPDATE SET d.dname = o.dname, d.loc = o.loc
     WHEN NOT MATCHED THEN
          INSERT (d.deptno, d.dname, d.loc)
          VALUES (o.deptno, o.dname, o.loc);

4 rows merged.

A tabela DEPT passou de 4 registros para 6 registros após a execução do comando, conforme apresentado abaixo:


SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH DEV   DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        50 ENGINEERING    WEXFORD
        60 MANAGER        MIAMI

6 rows selected.


2o. Exemplo

Este exemplo mesclará os valores da tabela em DEPT_ONLINE com a tabela chamada DEPT, semelhante ao 1o. exemplo, mas utilizando uma sintaxe diferente:

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON


SQL> SELECT * FROM dept_online;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        40 OPERATIONS     BOSTON
        20 RESEARCH DEV   DALLAS
        50 ENGINEERING    WEXFORD
        60 MANAGER        MIAMI

SQL> MERGE INTO dept d
     USING dept_online o
     ON (d.deptno = o.deptno)
     WHEN MATCHED THEN
          UPDATE SET d.dname = o.dname, d.loc = o.loc
     WHEN NOT MATCHED THEN
          INSERT (d.deptno, d.dname, d.loc)
          VALUES (o.deptno, o.dname, o.loc); 

4 rows merged.

A tabela DEPT passou de 4 registros para 6 registros após a execução do comando, conforme apresentado abaixo:

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH DEV   DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        50 ENGINEERING    WEXFORD
        60 MANAGER        MIAMI

6 rows selected.


3o. Exemplo

Este exemplo mesclará os valores literais (e não valores de outra tabela) usando uma instrução SQL na tabela DEPT.

Importante: A primeira vez que o comando MERGE for executado, ele irá inserir o registro novo (50). 
                  Quando executado pela segunda vez irá atualizar o registro para DEPTNO 50, uma vez que já existe.


SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

1a. Execução

SQL> MERGE INTO dept a
           USING (SELECT 50           deptno,
                         'ENGINEERING' dname,
                         'WEXFORD'     loc
                    FROM dual) b
           ON (a.deptno = b.deptno)
     WHEN NOT MATCHED THEN
          INSERT VALUES (b.deptno, b.dname, b.loc)
     WHEN MATCHED THEN
          UPDATE SET a.loc = 'WEXFORD, PA';

1 row merged.


Resultado da tabela DEPT após a execução do comando MERGE (1a. vez):


SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        50 ENGINEERING    WEXFORD

2a. Execução

SQL> MERGE INTO dept a
           USING ( SELECT 50           deptno,
                         'ENGINEERING' dname,
                         'WEXFORD'     loc
                     FROM dual) b
           ON (a.deptno = b.deptno)
     WHEN NOT MATCHED THEN
          INSERT VALUES (b.deptno, b.dname, b.loc)
     WHEN MATCHED THEN
          UPDATE SET a.loc = 'WEXFORD, PA';

1 row merged.


Resultado da tabela DEPT após a execução do comando MERGE (2a. vez):

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        50 ENGINEERING    WEXFORD, PA


4o. Exemplo

Neste exemplo, o comando MERGE é executado com uma sintaxe diferente, gerando o mesmo resultado.

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL> MERGE INTO dept
           USING dual ON (dept.deptno = 50)
     WHEN NOT MATCHED THEN
          INSERT VALUES (50, 'ENGINEERING', 'WEXFORD')
     WHEN MATCHED THEN
          UPDATE SET dept.loc = 'WEXFORD, PA';

1 row merged.

Resultado da tabela DEPT após a execução do comando MERGE (1a. vez):

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        50 ENGINEERING    WEXFORD

SQL> COMMIT;


2a. Execução

SQL> MERGE INTO dept
           USING dual ON (dept.deptno = 50)
     WHEN NOT MATCHED THEN
          INSERT VALUES (50, 'ENGINEERING', 'WEXFORD')
     WHEN MATCHED THEN
          UPDATE SET dept.loc = 'WEXFORD, PA';

1 row merged.


Resultado da tabela DEPT após a execução do comando MERGE (2a. vez):

SQL> SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        50 ENGINEERING    WEXFORD, PA

Referências:  Oracle Database SQL Language Reference, Release 2 (11.2).



MSc. Rubens Oliveira
DBA Oracle Consultor
olivert.dba@consultant.com

quarta-feira, 2 de janeiro de 2013

Como identificar a versão do Oracle (32/64 bits)


É muito comum perguntarmos qual a versão do Oracle que é necessário instalar no servidor.
32 bits ou 64 bits?

Vale lembrar que um sistema operacional de 64 bits pode suportar um banco de dados de 32 ou de 64 bits. Porém um sistema operacional de 32 bits não pode suportar um banco de dados de 64 bits. Assim, a identificação de versão do sistema operacional é necessária antes de instalar o Oracle.

Esperamos ajudá-lo com este artigo.

Para identificar a versão do sistema operacional:

Para o AIX, usar:

$ getconf -a | grep KERN
$ file /usr/lib/boot/unix*


No Solaris, usar:

$ /usr/bin/isainfo -kv
64-bit amd64 kernel modules

$ /usr/bin/isainfo -v
64-bit amd64 applications
cx16 mon sse3 pause sse2 sse fxsr mmx cmov amd_sysc cx8 tsc fpu
32-bit i386 applications
cx16 mon sse3 pause sse2 sse fxsr mmx cmov sep cx8 tsc fpu

A saída apresentada indica a co-existência de arquivos de 32 e 64-bits.

Para o Linux, usar:

$ uname -a
Linux server 2.6.18-194.3.1.el5 #1 SMP Sun May 2 04:17:42 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux

Se a saída for (x86_64) então o sistema é 64 bits e se a saída for (i686 ou similar) o sistema é 32 bits.

Para o HP-UX, usar:

#/usr/bin/getconf KERNEL_BITS

ou

#/usr/bin/file /stand/vmunix

ou

#print_manifest | grep "OS mode"


Para o Windows, usar:

Start> All Programs> Accessories> System Tools> System Information> Verificar as informações sobre resumo do sistema (System summary).


Para verificar se o software Oracle é 32 ou 64 bits:

Método 1:

Acessar o $ORACLE_HOME/bin e verificar.

$ cd $ORACLE_HOME/bin
$ file oracle
oracle: ELF 64-bit LSB executable AMD64 Version 1, dynamically linked, not stripped

Se a saída for 64 bits indica que o software da Oracle é de 64 bits. Se a saída do arquivo "oracle" comando não apresentar essa mensage então a versão é 32 bits.

A saída para a versão 32 bits seria parecida com a mensagem abaixo.

$ file oracle
oracle: setuid setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

Método 2:

Conectar no SQL*Plus Verificar o baner.

$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.1.0 Production on Wed Jan 2 11:04:41 2013
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, Real Application Clusters, Automatic Storage Management and Real Application Testing options


Método 3:

Consultar a visão V$VERSION.

$ sqlplus / as sysdba

SQL> select * from v$version;

BANNER
----------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 – Production


Método 4:

Verificar os diretórios “libs” e “lib32”.

1)$ORACLE_HOME/lib32
2)$ORACLE_HOME/lib

Se os dois diretórios $ORACLE_HOME/lib32 e $ORACLE_HOME/lib existirem, então a versão do  Oracle instalada é de 64 bits.

Se houver apenas um diretório ORACLE_HOME/lib, então a versão é de 32 bits.



MSc. Rubens Oliveira
DBA Oracle Consultor
olivert.dba@consultant.com