Como dropar um usuário com sessão ativa

Olá, depois de algum tempo estou voltando a postar.

Veremos como dropar um usuário com sessão ativa no banco de dados.

Para esse post, criei um usuário nomeado no banco chamado TESTE.

Depois de criar o usuário, fiz uma conexão ao banco com o usuário recém criado e logo após tentei excluir o usuário que estava conectado.

Para excluir um usuário conectado, podemos fazer isso utilizando o bloco PL/SQL abaixo :

Criei um script chamado deleteuser.sql e vamos testá-lo.

O usuario TESTE está conectado ao banco:

Agora vamos testar o funcionamento do script e verificar se o usuario foi dropado.

Podemos verificar que o script funcionou, vamos verificar em outra sessão na qual o usuario TESTE estava conectado que o usuario foi realmente excluído.

Ao fazer uma consulta na DBA_USERS, verificamos que o usuario TESTE não existe mais.

Um abraço e até o próximo post.

Hint – IGNORE_ROW_ON_DUPKEY_INDEX

Ola!! Depois de algum tempo sem publicar, estou colocando um novo post.
Encontrei um hint muito interessante, que fornece uma abordagem alternativa ao inserir dados onde valores duplicados podem vir a ser um problema.

Nas versões mais antigas do Oracle, eram usados em uma rotina PL/SQL, além de manipuladores de exceção ou instruções SQL que impediam a duplicação.
Como o Oracle 10g, o problema podia ser combatido com uma instrução MERGE,
embora o MERGE existisse desde a versão 9i, ele ainda precisava lidar com WHEN MATCHED e WHEN NOT MATCHED, o que em muitas aplicações isso não é viável.

O Oracle na versão 11.2.0.1 possui um recurso que permite silenciosamente inserir SQL para aceitar linhas duplicadas com o hint ignore_row_on_dupkey_index .
Quando hint ignore_row_on_dupkey_index é usado em uma instrução insert numa tabela com um índice de chave exclusivo, quaisquer linhas duplicadas serão silenciosamente ignoradas, em vez de causar o tradicional erro, ORA-00001 unique constraint violated .

Abaixo farei um cenário para testes, onde mostraremos o uso de hint ignore_row_on_dupkey_index :

I – USO DO HINT

Neste Cenário de testes, usarei uma tabela com 15 linhas com um índice de chave exclusiva, aonde tentarei inserir novas linhas a fim de ilustrar o uso do hint.

1 – Criando uma tabela de testes

postdezembro1

2 – Verificar índice único criado

postdezembro2

3 – Adicionar linhas a tabela

postdezembro3

4 – Verificar as linhas adicionadas na tabela

postdezembro4

5 – Adicionar linhas com valores duplicados

postdezembro5

Obs: Obviamente recebemos um erro de violação de restrição exclusiva e não ocorreu inserção na tabela.

Neste momento usarei o hint IGNORE_ROW_ON_DUPKEY_INDEX para adicionar linhas a tabela de testes, mesmo com registros duplicados. Assim poderemos verificar que o uso do hint IGNORE_ROW_ON_DUPKEY_INDEX , lidará silenciosamente com os erros de violação exclusivas de restrição, simplesmente ignorando e não inserindo nenhuma linha na qual os valores exclusivos já existam na tabela.

6 – Inserindo linha usando hint IGNORE_ROW_ON_DUPKEY_INDEX

postdezembro6

Observe que os 15 valores duplicados (1 – 15) foram ignorados e não foram inseridos na tabela, mas os valores 16 a 20 que não existiam anteriormente foram inseridos com êxito na tabela.

postdezembro7

No próximo exemplo, tentaremos inserir os valores de 1 a 21 na tabela, embora atualmente os valores entre 1 a 20 já existam. Desta vez, usaremos um segundo formato da usando o hint que nos permite estipular a coluna que contém valores exclusivos que devem ser ignorados se já existirem:

postdezembro8
Note que na figura abaixo, os valores entre 1 e 20 foram silenciosamente ignorados com apenas o valor 21 inserido desta vez na tabela.

postdezembro9

II – RESTRIÇÕES

O hint IGNORE_ROW_ON_DUPKEY_INDEX não pode ser usado dentro de uma instrução UPDATE.

postdezembro10

OBS: Uma diferença interessante no comportamento deste hint. Geralmente, os hints “inválidos” são apenas ignorados e tratados como comentários, mas para este hint, se uma operação ilegal for tentada, um erro ocorre.

Abaixo repetiremos os testes, mas dessa vez criaremos uma tabela sem chave primária por meio de um índice não-exclusivo.

postdezembro11

Observe novamente que um erro será invocado aqui, bem como verificaremos que esse hint só pode ser aplicado por meio de uma restrição policiada por um índice exclusivo. Um índice não exclusivo, mesmo com uma restrição Unique ou PK em vigor, não é suficiente e gerará o erro abaixo:

postdezembro12

Atualmente, apesar da conveniência associada ao uso do hint IGNORE_ROW_ON_DUPKEY_INDEX, há também outras limitações. Portanto, o índice fornecido no hint deve existir. Caso contrário o hint não é ignorada como de costume, mas um erro ocorrerá. Além disso, os INSERTs que usam a este hint não podem se beneficiar de Paralelismo, Direct Path ou NOLOGGING.

CONCLUSÃO

É claramente muito mais eficiente evitar inserir linhas duplicadas do que inseri-las e manipular a exceção ou usar o hint IGNORE_ROW_ON_DUPKEY_INDEX. Portanto, ainda é muito mais eficiente evitar inserir linhas duplicadas em primeiro lugar. Caso isso não seja possível, use o hint IGNORE_ROW_ON_DUPKEY_INDEX, mas leve em consideração as restrições acima citadas.

Privilégios insuficientes ao criar view materializada em um esquema diferente

Recentemente um analista me trouxe uma questão interessante.  Ele reclamava que estava recebendo a mensagem ORA-01031: privilégios insuficientes ao criar uma view materializada sob um esquema diferente.

Eu também tentei criar a view materializada usando o usuário SYSTEM,  mas obtive o mesmo erro.

Depois de pesquisar no MOS, encontrei uma nota muito interessante: ORA-01031: Privilégios insuficientes quando criar um Mview em um esquema  diferente (Doc ID 749112.1) .

Segundo a nota do MOS, este não é um erro de código. Este é um comportamento esperado.
Conforme explicado acima,  ao owner da tabela base deve ser concedido  o privilégio ‘create table’ explicitamente.  Conceder o privilégio de ‘create table’ explicitamente ao owner do esquema nos permite criar views materializadas em um outro esquema.

Apos o grant, a instrução CREATE MATERIALIZED VIEW funciona como esperado:

1- Testes de criação de Visão Materializada sem o grant

No SQLPLUS tentei criar uma visão:

SQL> create materialized view SERGIO.MV_TESTE_POST
2 refresh force on demand
3 as
4 Select a.NI_ID, a.DT_TRANSACAO
5 from sergio.vw_arquivo a
6 where a.DT_TRANSACAO > to_date (’20/10/2016′) and
7 a.VALOR >= 100;

ERROR na linha 1:
ORA-01031: privilégios insuficientes

2 – Testes de criação de Visão Materializada como grant

No SQLPLUS após o grant,  criei a visão acima:

SQL> grant create table to SERGIO;

Grant succeeded

SQL>
SQL> create materialized view SERGIO.MV_TESTE_POST
2 refresh force on demand
3 as
4 Select a.NI_ID, a.DT_TRANSACAO
5 from sergio.vw_arquivo a
6 where a.DT_TRANSACAO > to_date (’20/10/2016′) and
7 a.VALOR >= 100;

Materialized view created

SQL>

Depois que o problema foi resolvido o analista me fez a seguinte pergunta:
“A função RESOURCE contém o privilégio CREATE TABLE, por que eu tenho que conceder esse privilégio de forma explícita?”.

Pesquisando no MOS, encontrei no documento 11740.1 (restrições de Roles)  a resposta para esta questão:

“Um usuário não pode criar um objeto usando privilégios recebidos por meio de uma role.
Por exemplo, um usuário não pode criar uma visão com base na tabela caso ele tenha recebido a permissão de select nesta tabela por meio de uma função.
Isso também se aplica a procedures, triggers e referências a tabela de outros usuários.
…Essa restrição é necessária porque as funções podem ser ativadas ou
desativadas dinamicamente, tornando a verificação de segurança em tempo de
execução ambígua.
…As roles são destinadas a serem usadas como uma ferramenta para administrar
privilégios para usuários finais.
Eles não são destinados a serem usados pelos desenvolvedores de aplicativos.

Espero que esta postagem seja útil.

Um abraço a todos!!!

Duplicando o controlfile usando o RMAN

Neste post mostrarei como duplicar um arquivo de configuração do banco de dados utilizando o utilitário do Oracle chamado RMAN. Você pode se encontrar em uma situação em que pode ser necessário multiplexar o arquivo de controle em vários diskgroups (no caso de ASM) ou em diferentes filesystems, especialmente depois que o banco de dados é criado.

É altamente recomendável configurar o  banco de dados Oracle com vários arquivos de controle a fim de reduzir o risco de perder um arquivo de controle devido a corrupção, remoção acidental.

A multiplexação é o processo de efetuar uma cópia dos mesmos arquivos de controle em diferentes drivers de disco ou em diferentes diskgroups no caso do ASM.

Abaixo, mostraremos como efetuar uma multiplexação de um controlfile usando o RMAN:

1 –  Multiplexando um controlfile em ambiente com o filesystem

1.1 – Entrar no SQLPLUS 

[oracle@local ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.1.0.6.0 – Production on Wed Oct 25 21:41:22 2017 Copyright (c) 1982, 2007, Oracle.  All rights reserved.   Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 – Production With the Partitioning, OLAP, Data Mining and Real Application Testing options

1.2 – Verificando o parametro control_files

SQL> show parameter control_files

NAME                                 TYPE        VALUE

———————————— ———– ——————————

control_files                        string      /u01/app/oracle/oradata/orcl/                                               control01.ctl,  /u01/app/oracle/oradata/orcl/control02.ctl,   01/app/oracle/oradata/orcl/control03.ctl

SQL>

SQL> select name from v$controlfile;

NAME

——————————————————————————–

/u01/app/oracle/oradata/orcl/control01.ctl

/u01/app/oracle/oradata/orcl/control02.ctl

/u01/app/oracle/oradata/orcl/control03.ctl

SQL>

1.3 – Configurar o parâmetro control_files no arquivo de inicialização

SQL> alter system set control_files=’/u01/app/oracle/oradata/orcl/control01.ctl’,’/u01/app/oracle/oradata/orcl/control02.ctl’,’/u01/app/oracle/oradata/orcl/control03.ctl’,’/u01/app/oracle/oradata/orcl/control04.ctl’ scope=spfile;

System altered.

1.4 – Baixar a instancia e inicia-la em modo nomount

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL>

SQL> startup nomount

ORACLE instance started.

Total System Global Area  422670336 bytes

Fixed Size                  1300352 bytes

Variable Size             297797760 bytes

Database Buffers          117440512 bytes

Redo Buffers                6131712 bytes

SQL>

1.5 – Entrar no RMAN 

[oracle@local ~]$ rman target /

Recovery Manager: Release 11.1.0.6.0 – Production on Wed Oct 25 21:54:05 2017

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

connected to target database: ORCL (not mounted)

1.6 – Efetuar uma cópia do controlfile

RMAN> restore controlfile from ‘/u01/app/oracle/oradata/orcl/control01.ctl’;

Starting restore at 25-OCT-17

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=152 device type=DISK

channel ORA_DISK_1: copied control file copy

output file name=/u01/app/oracle/oradata/orcl/control01.ctl

output file name=/u01/app/oracle/oradata/orcl/control02.ctl

output file name=/u01/app/oracle/oradata/orcl/control03.ctl

output file name=/u01/app/oracle/oradata/orcl/control04.ctl

Finished restore at 25-OCT-17

1.7 – Sair do RMAN

RMAN> exit

Recovery Manager complete.

[oracle@local ~]$ exit

exit

1.8 – Voltar ao SQLPLUS e efetuar um shutdown na instância

SQL> shutdown

ORA-01507: database not mounted

ORACLE instance shut down.

SQL>

SQL> shutdown

ORA-01507: database not mounted

ORACLE instance shut down.

1.9 – Efetuar  startup na instância

SQL> startup

ORACLE instance started.

Total System Global Area  422670336 bytes

Fixed Size                  1300352 bytes

Variable Size             297797760 bytes

Database Buffers          117440512 bytes

Redo Buffers                6131712 bytes

Database mounted.

Database opened.

SQL>

1.10 – Verificar os controlfiles 

SQL> select name from v$controlfile;

NAME

——————————————————————————–

/u01/app/oracle/oradata/orcl/control01.ctl

/u01/app/oracle/oradata/orcl/control02.ctl

/u01/app/oracle/oradata/orcl/control03.ctl

/u01/app/oracle/oradata/orcl/control04.ctl

SQL> show parameter control_files

NAME                                 TYPE        VALUE

———————————— ———– ——————————

control_files                        string      /u01/app/oracle/oradata/orcl/c

                                                 ontrol01.ctl, /u01/app/oracle/

                                                 oradata/orcl/control02.ctl, /u01/app/oracle/oradata/orcl/con

                                                 trol03.ctl, /u01/app/oracle/oradata/orcl/control04.ctl

SQL>

2 – Multiplexando um controlfile em ambiente com o ASM

2.1 – Entrar no SQLPLUS 

[oracle@LNXORA ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.3.0 Production on Wed Oct 25 08:01:09 2017

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

Conectado a: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – 64bit Production With the Partitioning, Real Application Clusters, Automatic Storage Management,OLAP,Data Mining and Real Application Testing options

2.2 – Verificando o parametro control_files

SQL> show parameter control_files

NAME                                 TYPE        VALUE

———————————— ———– ——————————

control_files                        string      +REDO/mtrbildc/controlfile/current.260.945000645

SQL> select name from v$asm_diskgroup;

NAME

——————————

REDO

DATA

RECO

SQL> select name from v$controlfile;

NAME

——————————————————————————–

+REDO/mtrbildc/controlfile/current.260.945000645

2.3 – Configurar o parâmetro control_files no arquivo de inicialização

SQL> alter system set control_files=’+REDO/mtrbildc/controlfile/current.260.945000645′,’+DATA’ scope=spfile;

Sistema alterado.

2.4 – Baixar a instancia e inicia-la em modo nomount

SQL> shutdown immediate

SQL> startup nomount

2.5 – Entrar no RMAN 

[oracle@LNXORA ~]$ rman target /

Recovery Manager: Release 11.2.0.3.0 – Production on Wed Oct 25 13:27:59 2017

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

connected to target database: MTRBILDC (not mounted)

2.6 – Efetuar uma cópia do controlfile

RMAN> restore controlfile from ‘+REDO/mtrbildc/controlfile/current.260.945000645’;

Starting restore at 25-OCT-17

using target database control file instead of recovery catalog allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=8 device type=DISK

channel ORA_DISK_1: copied control file copy

output file name=+REDO/mtrbildc/controlfile/current.260.945000645

output file name=+DATA/mtrbildc/controlfile/current.394.958310919

Finished restore at 25-OCT-17

RMAN>

2.7 – Sair do RMAN

RMAN> exit

Recovery Manager complete.

2.8 – voltar ao SQLPLUS e configurar o arquivo de inicialização com o nome correto do controlfile

SQL> alter system set control_files=’+REDO/mtrbildc/controlfile/current.260.945000645′,’+DATA/mtrbildc/controlfile/current.394.958310919′ scope=spfile;

Sistema alterado.

SQL>

2.9 – Efetuar um shutdown e um startup na instância

SQL> shutdown immediate

ORA-01507: banco de dados n?o montado

Instancia ORACLE desativada.

SQL> startup

Instancia ORACLE iniciada.

Total System Global Area 4275781632 bytes

Fixed Size                  2235208 bytes

Variable Size            2667578552 bytes

Database Buffers         1577058304 bytes

Redo Buffers               28909568 bytes

Banco de dados montado.

Banco de dados aberto.

SQL>

SQL>

2.10. – Verificar os controlfiles 

SQL> show parameter control_files

NAME                                 TYPE        VALUE

———————————— ———– ——————————

control_files                        string      +REDO/mtrbildc/controlfile/current.260.945000645, +DATA/mtrbildc/controlfile/current.394.958310919

SQL>

Conforme podemos verificar com os procedimentos acima, o processo de cópia do controlfile é basicamente o mesmo entre sistemas de arquivos em file system ou ASM.

Configurando Schedule e Gerando Relatórios com o STATSPACK

No último post eu mostrei como instalar e configurar o STATSPACK, neste post mostrarei como configurar uma coleta automática de dados para o STATSPACK.

Statspack não é um processo automático. Ele requer configuração manual, um DBA precisa configurar um scheduler para Statspack Collection e Statspack purge.

Podemos automatizar a tomada de snapshots do STATSPACK executando DBMS_JOB ou programando-o através do crontab. No exemplo que usaremos mostraremos a configuração do scheduler para o STATSPACK  via DBMS_JOB.

Cabe ao DBA, descobrir quantas vezes precisa estar executando o STATSPACK. Como os dados devem ser coletados e escritos em algum lugar, certifique-se de que você não está coletando dados com muita freqüência, a coleta de dados em excesso pode tornar o servidor de banco de dados mais lento.

Abaixo mostraremos como configurar uma coleta  automática para o STATSPACK.

Depois do STATSPACK  instalado e funcionando, podemos agendar a coleta automática de dados. O script spauto.sql pode ser usado para agendar coletas de snapshots do sistema a cada hora.

SQL> @?/rdbms/admin/spauto.sql

OBS: De acordo com a necessidade do ambiente é possível alterar o intervalo de execução deste job.

Para uma coleta manual usamos o comando abaixo, conectados com o usuário perfstat.

SQL> EXEC STATSPACK.snap

 PL/SQL procedure successfully completed.

SQL>

 1 – Gerando Relatórios

Após mais de um snapshot coletado, estarei gerando um relatório com a análise do ambiente. Assim como no AWR, para gerar o relatório do STATSPACK, devemos selecionar um snapshot inicial e um snapshot final e posteriormente definimos o nome do arquivo a ser gerado, que pode ser precedido pelo local de destino.

Segue abaixo a sintaxe da execução do relatório de coleta  STATSPACK.

SQL> @?/rdbms/admin/spreport.sql

Segue abaixo um modelo do relatório STATSPACK (como o relatório é extenso somente coloquei a parte inicial).

STATSPACK report for

Database    DB Id    Instance     Inst Num  Startup Time   Release     RAC

~~~~~~~~ ———– ———— ——– ————— ———– —

           196335337  orcl               1 20-Apr-17 12:52 11.2.0.1.0  NO

Host Name             Platform                CPUs Cores Sockets   Memory (G)

~~~~ —————- ———————- —– —– ——- ———

     localhost.locald Linux x86 64-bit           2     2       1     2.0

Snapshot       Snap Id     Snap Time      Sessions Curs/Sess Comment

~~~~~~~~    ———- —————— ——– ——— ———–

Begin Snap:          3 20-Apr-17 16:00:03       40       5.1

  End Snap:          4 20-Apr-17 17:00:05       40       5.1

   Elapsed:      60.03 (mins) Av Act Sess:       0.4

   DB time:      25.94 (mins)      DB CPU:      13.92 (mins)

Cache Sizes            Begin        End

~~~~~~~~~~~       ———- ———-

    Buffer Cache:       188M              Std Block Size:         8K

     Shared Pool:       288M                  Log Buffer:     2,160K

Load Profile              Per Second    Per Transaction    Per Exec    Per Call

~~~~~~~~~~~~      ——————  —————– ———-  ——

      DB time(s):                0.4                0.0        0.01   0.06

       DB CPU(s):                0.2                0.0        0.00   0.03

       Redo size:           20,766.2            2,092.1

   Logical reads:              548.5               55.3

   Block changes:              138.3               13.9

  Physical reads:               22.9                2.3

Physical writes:               16.5                1.7

      User calls:                7.0                0.7

          Parses:                9.2                0.9

     Hard parses:                0.0                0.0

W/A MB processed:                1.8                0.2

          Logons:                0.1                0.0

        Executes:               62.6                6.3

       Rollbacks:                0.0                0.0

    Transactions:                9.9

2 – Purgar/remover dados desnecessários

É possível limpar dados desnecessários do esquema PERFSTAT usando sppurge.sql. Este script exclui snapshots que estão entre o intervalo inicial e final do Snapshot Id especificado. Segue abaixo a sintaxe de execução:

@?/rdbms/admin/sppurge.sql

OBS: O script acima executa uma remoção manual dos snapshots coletados, esse procedimento pode ser feito de forma automática pelo DBA.

3 – Desinstalando o STATSPACK

Para remover o statspack, basta executar o comando spdrop.sql.

@?/rdbms/admin/spdrop.sql

Referências:

Documentação Oracle

Oracle FAQ

AKADIA

Criando um repositório com statspack

Com a adição da feature Active  Workload Repository  (AWR) e Active Session History (ASH) no Oracle Database 10g e versões posteriores, pode parecer um pouco estranho ainda estar falando em Statspack. Ambas as funcionalidades requerem uma licença de  Diagnostics Pack, que se limita ao banco de dados Enterprise Edition.

Por que usar statspack quando existe o AWR? O statspack é free, e também fácil de implementar. Você pode usá-lo sem ter o Grid Control instalado. Mesmo com o Grid Control instalado no ambiente, ainda existem bancos de dados na versão 9i para uma aplicação específica, e a migração (ainda) não é possível. Então para o monitoramento de desempenho do banco de dados e recursos históricos você tem que implementar o Statspack. O Statspack também está disponível nas versões do Oracle 10g, 11g e 12c.

Podemos, então, usar essas informações para análise de desempenho, este artigo irá detalhar a configuração interativa de Statspack.

Passos para criação do repositório

1- Criar uma tablespace para o repositório

Neste exemplo chamarei a tablespace de statspack

SQL> create tablespace statspack datafile ‘/home/oracle/app/oracle/oradata/orcl/statspack.dbf’ size 100m autoextend on next 100m maxsize 2G;

Tablespace created.

2 – Executar a procedure spcreate  para  criar o repositório 

Executar a procedure spcreate e inserir as informações solicitadas.

SQL> @?/rdbms/admin/spcreate.sql

Choose the PERFSTAT user’s password

———————————–

Not specifying a password will result in the installation FAILING

Enter value for perfstat_password: perfstat

perfstat

Choose the Default tablespace for the PERFSTAT user

—————————————————

Below is the list of online tablespaces in this database which can store user data.  Specifying the SYSTEM tablespace for the user’s default tablespace will result in the installation FAILING, asusing SYSTEM for performance data is not supported.

Choose the PERFSTAT users’s default tablespace.  This is the tablespace

in which the STATSPACK tables and indexes will be created.

TABLESPACE_NAME                CONTENTS  STATSPACK DEFAULT TABLESPACE

—————————— ——— —————————-

STATSPACK                      PERMANENT

SYSAUX                         PERMANENT *

USERS                          PERMANENT

Pressing  will result in STATSPACK’s recommended default

tablespace (identified by *) being used.

Enter value for default_tablespace: STATSPACK

Using tablespace STATSPACK as PERFSTAT default tablespace.

Choose the Temporary tablespace for the PERFSTAT user

—————————————————–

Below is the list of online tablespaces in this database which canstore temporary data (e.g. for sort workareas).  Specifying the SYSTEMtablespace for the user’s temporary tablespace will result in theinstallation FAILING, as using SYSTEM for workareas is not supported.

Choose the PERFSTAT user’s Temporary tablespace.

TABLESPACE_NAME                CONTENTS  DB DEFAULT TEMP TABLESPACE

—————————— ——— ————————–

TEMP                           TEMPORARY *

Pressing  will result in the database’s default Temporary

tablespace (identified by *) being used.

Enter value for temporary_tablespace: TEMP

Após entrar com as informações solicitadas aguardar a criação do repositório.

Creating Package STATSPACK…

Package created.

No errors.

Creating Package Body STATSPACK…

Package body created.

No errors.

NOTE:

SPCPKG complete. Please check spcpkg.lis for any errors.

No próximo post estarei mostrando a criação de um schedule   de trabalho para automatizar o processo de coleta instantânea do banco de dados com o statspack.

Um abraço a todos!!!

 

Operadores PIVOT e UNPIVOT

Este post mostra como usar os operadores PIVOT e UNPIVOT no Oracle Database a partir da versão 11g.

Como sabemos, as tabelas relacionais são apresentadas em pares de coluna e valor.
Vamos tomar por exemplo uma tabela chamada CUSTOMERS.

SQL> desc sh.customers
Name Type Nullable Default Comments
———————- ———— ——– —————- ————————————————–
CUST_ID NUMBER primary key
CUST_FIRST_NAME VARCHAR2(20) first name of the customer
CUST_LAST_NAME VARCHAR2(40) last name of the customer
CUST_GENDER CHAR(1) Y gender; low cardinality attribute
CUST_YEAR_OF_BIRTH NUMBER(4) Y customer year of birth
CUST_MARITAL_STATUS VARCHAR2(20) Y customer marital status; low cardinality attribute
CUST_STREET_ADDRESS VARCHAR2(40) customer street address
CUST_POSTAL_CODE VARCHAR2(10) postal code of the customer
CUST_CITY VARCHAR2(30) city where the customer lives
CUST_STATE_PROVINCE VARCHAR2(40) Y customer geography: state or province
COUNTRY_ID CHAR(2) foreign key to the countries table (snowflake)
CUST_MAIN_PHONE_NUMBER VARCHAR2(25) Y customer main phone number
CUST_INCOME_LEVEL VARCHAR2(30) Y customer income level
CUST_CREDIT_LIMIT NUMBER Y customer credit limit
CUST_EMAIL VARCHAR2(30) Y customer email id
CUST_TOTAL VARCHAR2(14) Y ‘Customer total’

Ao fazer um select nesta tabela temos o resultado abaixo:

SQL> select t.cust_id,t.country_id,t.cust_income_level from sh.customers t;

CUST_ID COUNTRY_ID CUST_INCOME_LEVEL
———- ———- ——————————
1550 US I: 170,000 – 189,999
1560 US C: 50,000 – 69,999
1570 US H: 150,000 – 169,999
1590 US C: 50,000 – 69,999
1600 UK C: 50,000 – 69,999
1610 US I: 170,000 – 189,999
1620 NL F: 110,000 – 129,999
1630 DE B: 30,000 – 49,999
1640 NL E: 90,000 – 109,999
1650 NL F: 110,000 – 129,999
1660 DE H: 150,000 – 169,999
1670 NL D: 70,000 – 89,999
1680 NL F: 110,000 – 129,999
1690 NL F: 110,000 – 129,999
1700 US E: 90,000 – 109,999
1710 UK E: 90,000 – 109,999
1720 UK H: 150,000 – 169,999
1730 US C: 50,000 – 69,999
1740 US C: 50,000 – 69,999
1750 UK F: 110,000 – 129,999

Observe que os dados são representados como linhas de valores: para cada cliente,
o registro mostra seu pais de origem e a faixa de renda a que esse cliente pertence.

Abaixo veremos como poderia se obter um relatório da frequência de compras por pais, por faixa de renda,isto é, quantos clientes compraram algo só uma vez, duas vezes, três vezes, etc.
Em uma instrução SQL comum, executamos a seguinte instrução:

SQL> select t.country_id,t.cust_income_level, count(1) from sh.customers t
2 group by t.country_id,t.cust_income_level;

COUNTRY_ID CUST_INCOME_LEVEL COUNT(1)
———- —————————— ———-
AR A: Below 30,000 20
AR B: 30,000 – 49,999 12
AR C: 50,000 – 69,999 24
AR D: 70,000 – 89,999 23
AR E: 90,000 – 109,999 35
AR F: 110,000 – 129,999 61
AR G: 130,000 – 149,999 22
AR H: 150,000 – 169,999 22
AR I: 170,000 – 189,999 24
AR J: 190,000 – 249,999 10
AU A: Below 30,000 66
AU B: 30,000 – 49,999 33
AU C: 50,000 – 69,999 64
AU D: 70,000 – 89,999 67
AU E: 90,000 – 109,999 100
AU F: 110,000 – 129,999 204
AU G: 130,000 – 149,999 69
AU H: 150,000 – 169,999 67
AU I: 170,000 – 189,999 65
AU J: 190,000 – 249,999 32

Essas são as informações que você precisa, mas seu formato torna a leitura difícil.
Uma melhor maneira de apresentar os mesmos dados pode ser mediante relatórios com referências cruzadas, nos quais os dados podem ser organizados verticalmente e a lista de estados, horizontalmente, como em uma folha de cálculo.

1 – OPERADOR PIVOT

Antes do surgimento do Oracle Database 11 g, para realizar essa ação era necessário usar algum tipo de função de decodificação para cada valor e escrever cada valor como coluna independente.
Felizmente, agora há uma nova e útil característica, PIVOT, para reordenar dados e apresentar os resultados das consultas como tabela de referências cruzadas, com o operador pivot.

Na consulta abaixo apresentaremos a baseada na query executada acima um exemplo a praticidade do operador pivot.

SQL> select * from (
2 select t.country_id,t.cust_income_level
3 from sh.customers t
4 )
5 pivot
6 (
7 count(country_id)
8 for country_id in (‘AR’,’BR’,’JP’,’FR’,’NZ’,’AU’,’ES’)
9 )
10 order by cust_income_level
11 ;

Os valores de country_id são apresentados na linha de cabeçalho, e não em uma coluna.

CUST_INCOME_LEVEL ‘AR’ ‘BR’ ‘JP’ ‘FR’ ‘NZ’ ‘AU’ ‘ES’
—————————— ———- ———- ———- ———- ———- ———- ———-
A: Below 30,000 20 66 53 102 18 66 92
B: 30,000 – 49,999 12 34 27 221 9 33 99
C: 50,000 – 69,999 24 65 52 283 17 64 158
D: 70,000 – 89,999 23 67 51 410 22 67 198
E: 90,000 – 109,999 35 102 80 573 29 100 308
F: 110,000 – 129,999 61 192 152 639 59 204 368
G: 130,000 – 149,999 22 64 49 446 21 69 196
H: 150,000 – 169,999 22 68 50 396 20 67 207
I: 170,000 – 189,999 24 68 53 240 18 65 173
J: 190,000 – 249,999 10 32 26 147 9 32 79
K: 250,000 – 299,999 0 0 0 182 0 0 62
L: 300,000 and above 0 1 0 112 0 0 46

12 rows selected

Em um relatório com referências cruzadas, deseja-se transferir a coluna country_id para a linha de cabeçalho, como ilustrado no exemplo acima.  A coluna(country_id) é transformada em linha, como se fosse rotada 90 graus no sentido anti-horário, e passa a ser o cabeçalho.

Os cabeçalhos de cada coluna são os dados da própria tabela, ou seja, os códigos de pais. Embora esses códigos sejam bastante conhecidos, alguém poderia preferir mostrar os nomes dos Países em lugar dos códigos (“Brasil” em lugar de “BR”).
Nesse caso, é necessário fazer um pequeno ajuste na cláusula FOR da consulta, segundo o exemplo mostrado abaixo:

SQL> select * from (
2 select t.cust_income_level as “Faixa salarial”, t.country_id
3 from sh.customers t
4 )
5 pivot
6 (
7 count(country_id)
8 for country_id in (‘AR’ as “Argentina”,’AU’ “Australia”,’JP’
9 “Japao”,’FR’ “Franca”,’ES’ as “Espanha”)
10 )
11 order by 1;

Faixa salarial Argentina Australia Japao Franca Espanha
—————————— ———- ———- ———- ———- ———-
A: Below 30,000 20 66 53 102 92
B: 30,000 – 49,999 12 33 27 221 99
C: 50,000 – 69,999 24 64 52 283 158
D: 70,000 – 89,999 23 67 51 410 198
E: 90,000 – 109,999 35 100 80 573 308
F: 110,000 – 129,999 61 204 152 639 368
G: 130,000 – 149,999 22 69 49 446 196
H: 150,000 – 169,999 22 67 50 396 207
I: 170,000 – 189,999 24 65 53 240 173
J: 190,000 – 249,999 10 32 26 147 79
K: 250,000 – 299,999 0 0 0 182 62
L: 300,000 and above 0 0 0 112 46

12 rows selected

OBS: A cláusula FOR pode incluir pseudônimos para esses valores, que serão transformados nos cabeçalhos de coluna.

2 – OPERADOR UNPIVOT

O operador UNPIVOT converte os dados baseados em colunas em linhas separadas.
usarei como base a tabela CUSTOMERS, que é a mesma utilizada nos exemplos anteriores(pivot).

Para tornar simples mostrar esta operação com um exemplo: Primeiro, vou criar uma tabela de referências cruzadas com a operação pivot:

SQL> create table exemplo_post as
2 select * from (
3 select t.cust_income_level as “Faixa salarial”, t.country_id
4 from sh.customers t
5 )
6 pivot
7 (
8 count(country_id)
9 for country_id in (‘AR’ as “Argentina”,’AU’ “Australia”,’JP’
10 “Japao”,’FR’ “Franca”,’ES’ as “Espanha”)
11 )
12 order by 1;

Table created

Depois de criada a tabela vou conferir os dados:

SQL> select * from exemplo_post;

Faixa salarial Argentina Australia Japao Franca Espanha
—————————— ———- ———- ———- ———- ———-
A: Below 30,000 20 66 53 102 92
B: 30,000 – 49,999 12 33 27 221 99
C: 50,000 – 69,999 24 64 52 283 158
D: 70,000 – 89,999 23 67 51 410 198
E: 90,000 – 109,999 35 100 80 573 308
F: 110,000 – 129,999 61 204 152 639 368
G: 130,000 – 149,999 22 69 49 446 196
H: 150,000 – 169,999 22 67 50 396 207
I: 170,000 – 189,999 24 65 53 240 173
J: 190,000 – 249,999 10 32 26 147 79
K: 250,000 – 299,999 0 0 0 182 62
L: 300,000 and above 0 0 0 112 46

12 rows selected

Vamos conferir a estrutura da tabela:

SQL> desc exemplo_post
Name Type Nullable Default Comments
————– ———— ——– ——- ——–
Faixa salarial VARCHAR2(30) Y
Argentina NUMBER Y
Australia NUMBER Y
Japao NUMBER Y
Franca NUMBER Y
Espanha NUMBER Y

Na consulta abaixo, os dados da tabela deverão ser separados para que as linhas só mostrem o código de país e o total para cada país.
Isto é possível utilizando o operador unpivot conforme mostrado abaixo:

SQL> select *
2 from exemplo_post
3 unpivot
4 (
5 Total
6 for Pais in (“Argentina”,”Australia”,”Japao”,”Franca”,”Espanha”)
7 )
8 order by “Faixa salarial”, Pais ;

Faixa salarial PAIS TOTAL
—————————— ——— —–
A: Below 30,000 Argentina 20
A: Below 30,000 Australia 66
A: Below 30,000 Espanha 92
A: Below 30,000 Franca 102
A: Below 30,000 Japao 53
B: 30,000 – 49,999 Argentina 12
B: 30,000 – 49,999 Australia 33
B: 30,000 – 49,999 Espanha 99
B: 30,000 – 49,999 Franca 221
B: 30,000 – 49,999 Japao 27
C: 50,000 – 69,999 Argentina 24
C: 50,000 – 69,999 Australia 64
C: 50,000 – 69,999 Espanha 158
C: 50,000 – 69,999 Franca 283
C: 50,000 – 69,999 Japao 52
D: 70,000 – 89,999 Argentina 23
D: 70,000 – 89,999 Australia 67
D: 70,000 – 89,999 Espanha 198
D: 70,000 – 89,999 Franca 410
D: 70,000 – 89,999 Japao 51

Observe-se que cada nome de coluna se transformou em um valor na coluna PAIS.
CONCLUSÃO

O operador Pivot adiciona uma funcionalidade muito importante a linguagem SQL, em lugar de criar um código complicado e pouco intuitivo com muitas funções de decodificação,  é possível usar a função pivot para criar um relatório com referências cruzadas a partir de qualquer tabela relacional.
Da mesma forma, é possível transformar qualquer relatório com referências cruzadas para ser armazenado como tabela relacional mediante o uso de operador unpivot.

Referências:

Documentação Oracle   Documentação Oracle2    ORACLE-BASE

 

EXTERNAL TABLES

Esse post mostra um conceito básico de tabelas externas. Uma External Table é uma funcionalidade presente em uma serie de SGBDs, cada um com o seu nome e sintaxe próprias. As tabelas externas, estão disponíveis desde a versão Oracle9i. Uma tabela externa nada mais é do que uma tabela criada no banco de dados, cuja sua origem de dados está vinculada a um arquivo de texto, eliminando imediatamente a necessidade de carregar arquivos de texto em tabelas intermediárias visando economia no processamento de tempo e em espaço de armazenamento.

As tabelas externas são muito utilizadas em ambientes de data warehouse, extração, transformação e carregamento (ETL), no qual, esses processos podem ler o arquivo de texto de uma tabela externa direta e posteriormente carregar os dados em tabelas de resumo. Conforme dito acima, os processos ETL elimina a etapa de carregar os arquivos de texto em armazenamento intermediário, economizando espaço e tempo significativo, ou seja , isto é feito atraves da utilizaçao de arquivos “FLAT FILES” e Tabelas Relacionais sem a necessidade de uma ferramenta específica de ETL.

Quando criamos uma tabela simples no banco de dados Oracle podemos utilizar as instruções DML (ex. INSERT, UPDATE, DELETE) para manipular as informações. Uma conseqüência disso é que você não pode criar um índice em uma tabela externa.

Abaixo veremos como criar tabela externas em ambiente de banco de dados Oracle.Para esse teste o ambiente utilizado é linux com banco de dados Oracle 11g R2.

1 – Criar um diretório no sistema operacional

Como os dados de uma tabela externa está no sistema operacional, o arquivo de dados precisa estar em um lugar aonde o Oracle pode acessá-lo. Então o primeiro passo é criar um diretório e conceder acesso a ele. Primeiro, crie o diretório no sistema operacional ou escolha um diretório existente. Ele deve ser um diretório real, não um link simbólico. Certifique se o acesso de leitura e escrita do usuário oracle estão com as devidas permissões neste diretório.

No sistema operacional foi criado uma pasta chamada post no diretório /home/oracle.

[oracle@localhost]$ mkdir -p /home/oracle/post

[oracle@ localhost ]$ ls -l *

total 17520
-rw-rw-r– 1 oracle oracle       68 Jul 25 18:09 afiedt.buf
drwxr-xr-x 4 oracle oracle     4096 Jun 1 2013 ap
drwxrwxr-x 5 oracle oracle     4096 Jun 12 14:05 backup
drwxrwxr-x 3 oracle oracle     4096 Dez 5 2011 oradiag_oracle
drwxrwxr-x 2 oracle oracle     4096 Jul 27 14:57 post
drwxrwxr-x 2 oracle oracle     4096 Jun 12 14:38 scripts
-rw-rw-r– 1 oracle oracle     1750 Dez 7 2013 Untitled.sql

2 – Criar um diretório no banco de dados Oracle

As tabelas externas usam diretórios do Oracle. Um diretório Oracle é uma referência interna no dicionário de dados. Um diretório   mapeia um nome de diretório exclusivo para um diretório físico no sistema operacional local.

Para criar um diretório no banco de dados, é necessário ter acesso SYSDBA. O “diretório” será uma pasta mapeada em seu servidor, onde, haverá uma vinculo direto com o banco de dados e será possível determinar privilégios de acesso a determinados usuários/schemas. Antes de criar um diretório de banco de dados, é necessário criar uma pasta fisicamente no servidor. Conforme citado acima o diretório sera criado em ‘/home/oracle/post’.

SQL> create directory external as ‘/home/oracle/post’;

Directory created.

SQL> grant read, write on directory external to hr;

Grant succeeded.

3 – Criando uma tabela externa

A última etapa de preparação para criação de uma tabela externa exige que um arquivo de texto simples seja criado no diretório físico criado no S.O. e no banco de dados respectivamente.

           3.1 – Criando um arquivo texto

No diretório ‘/home/oracle/post’ foi criado um arquivo texto chamado empregado.csv. Segue abaixo o conteudo deste arquivo que usaremos para testes.

[oracle@localhost post]$ cat empregado.csv

001,Hutt,Jabba,jabba@thecompany.com
002,Simpson,Homer,homer@thecompany.co
03,Kent,Clark,superman@thecompany.com
004,Kid,Billy,billythkid@thecompany.com
005,Stranger,Perfect,nobody@thecompany.com
006,Zoidberg,Dr,crustacean@thecompany.com
007,Lane,Lois,loislane@thecompany.com
008,Bane,David,hulk@thecompany.com
009,Stark,Tony,ironman@thecompany.com
010,House,Gregory,drhouse@thecompany.com
011,Wayne,Bruce,batman@thecompany.com
012,Park,Peter,spiderman@thecompany.com

[oracle@localhost post]$

3.2 – Criando uma tabela externa

A sintaxe para criação de uma tabela externa é muito parecida com a sintaxe de criação de uma tabela normal. A primeira parte é como um CREATE TABLE normal, tem o nome da tabela e das colunas. Depois é seguido por um bloco de sintaxe específica para tabelas externas, o que permite que você informe o Oracle como interpretar os dados no arquivo externo.

A cláusula DEFAULT DIRECTORY, especifica o diretório padrão a ser usado para todos os arquivos de entrada e saída.

A cláusula LOCATION, lista todos os arquivos de dados para a tabela externa.

A cláusula ACCESS PARAMETERS é onde os arquivos de saída são nomeados.

SQL> connect hr/hr

Connected.

SQL> create table empregados

2   ( emp_id varchar2(3),

3   last_name varchar2(50),

4   first_name varchar2(50),

5   email varchar2(100)

6 )

7   organization external

8   ( default directory external

9   access parameters

10   ( records delimited by newline

11   fields terminated by ‘,’

12 )

13   location (‘empregado.csv’)

14 );

Table created.

Apos criada a tabela, vamos conferir os dados criados:

SQL> select count(*) from empregados;

COUNT(*)

———-

12

SQL> select * from empregados;

EMP LAST_NAME FIRST_NAME EMAIL

— ———- ———- ——————————

001 Hutt       Jabba     jabba@thecompany.com

002 Simpson   Homer     homer@thecompany.com

003 Kent       Clark     superman@thecompany.com

004 Kid       Billy     billythkid@thecompany.com

005 Stranger   Perfect   nobody@thecompany.com

006 Zoidberg   Dr         crustacean@thecompany.com

007 Lane       Lois       loislane@thecompany.com

008 Bane       David     hulk@thecompany.com

009 Stark     Tony       ironman@thecompany.com

010 House     Gregory   drhouse@thecompany.com

011 Wayne     Bruce     batman@thecompany.com

012 Parker       Peter     spiderman@thecompany.com

12 rows selected.

SQL>

Conforme falamos acima, uma tabela externa não aceita comandos DML, ela deve ser feita somente no arquivo texto. Caso tente realizar essas alterações utilizando DMLs, o resultado será:

SQL> insert into empregados values

2 (‘013′,’Steven’,’Rogers’,’capitaoamerica@thecompany.com’)

SQL> /

insert into empregados values

*

ERROR at line 1:

ORA-30657: operation not supported on external organized table

como vimos acima, a operação apresentou o erro ORACLE ORA-30657.

3.3 – Alterando uma tabela externa

Você pode usar o commando ALTER TABLE para alterar os parâmetros de acesso sem dropa-la e redefinir a tabela inteira:

SQL> alter table empregados

2       access parameters

3             ( records delimited by newline

4               badfile ‘empregado.bad’

5               logfile ‘empregado.log’

6               discardfile ‘empregado.dsc’

7             fields terminated by ‘,’

8           )

SQL> /

Table altered.

SQL>

3.4 – Visualizando o dicionários de dados

Os metadados são armazenadas em duas visões, chamadas USER_EXTERNAL_TABLES e USER_EXTERNAL_LOCATIONS (que, naturalmente, podem ser vistas nas visões ALL_ ou DBA_). O diretório virtual é armazenada na visão USER_EXTERNAL_TABLES, enquanto o nome do arquivo físico é armazenado na exibição USER_EXTERNAL_LOCATIONS.

3.4.1 – Consultando a visão USER_EXTERNAL_LOCATIONS

SQL> select * from user_external_locations where table_name = ‘EMPREGADOS’;

TABLE_NAME   LOCATION             DIR DIRECTORY_NAME

———— ——————– — ——————————

EMPREGADOS   empregado.csv       SYS EXTERNAL

3.4.2 – Consultando a visão USER_EXTERNAL_TABLES

SQL>select * from user_external_tables where table_name = ‘EMPREGADOS’;

TABLE_NAME   TYP TYPE_NAME       DEF DEFAULT_DIRECTORY_NAME         REJECT_LIMIT ACCESS_

———— — ————— — —————————— ————- ——-

ACCESS_PARAMETERS                                                               PROPERTY

——————————————————————————– ———-

EMPREGADOS   SYS ORACLE_LOADER   SYS EXTERNAL                      0           CLOB

records delimited by newline                                                   ALL

badfile ‘empregado.bad’

4 – Criando tabela externa apartir de tabela do banco de dados

O Oracle permite criar uma nova tabela externa a partir de dados em outras tabelas em seu banco de dados, que entra por um FLAT FILE  usando o driver de acesso ORACLE_DATAPUMP. Este FLAT FILE  está em um formato proprietário da Oracle que pode ser lido por DataPump. A sintaxe é semelhante a sintaxe CREATE TABLE … ORGANIZATION EXTERNAL acima, porém mais simples, uma vez que não é possível especificar o formato de dados, você pode especificar alguns parametros de acesso. A principal diferença é que você deve especificar o driver de acesso, ORACLE_DATAPUMP, desde que o driver de acesso predefinido para ORACLE_LOADER.

Vamos aos testes:

SQL> create table export_teste

2      organization external

3      ( type oracle_datapump

4        default directory external

5       location (‘teste.dmp’)

6    ) as select * from employees;

Table created.

SQL>

Depois de criada a tabela vamos verificar os dados:

SQL> select count(*) from export_teste;

COUNT(*)

———-

107

SQL> select * from export_teste where rownum < 5;

EMPLOYEE_ID FIRST_NAME LAST_NAME  EMAIL        PHONE_NUMBER HIRE_DATE JOB_ID        SALARY

———– ———- ———- ———— ———— ——— ———- ———-

COMMISSION_PCT MANAGER_ID DEPARTMENT_ID

————– ———- ————-

198 Donald    OConnell   DOCONNEL  650.507.9833 21-JUN-07 SH_CLERK  2600 124   50

199 Douglas    Grant   DGRANT  650.507.9844 13-JAN-08 SH_CLERK  2600 124   50

200 Jennifer   Whalen     JWHALEN      515.123.4444 17-SEP-03 AD_ASST   4400  101   10

201 Michael    Hartstein  MHARTSTE     515.123.5555 17-FEB-04 MK_MAN  13000  100   20

CONCLUSÃO

Nós vimos acima uma introdução de carga  de dados usando tabelas externas. As tabelas externas  fornecem uma maneira conveniente de mover dados para dentro e fora do banco de dados, com integração do SQLLoader, agregando funcionalidade do Data Pump e a facilidade no uso de instruções SQL.  Definitivamente vale a pena considerar o uso de tabelas externas na tarefa de carregar dados ao banco. Segue abaixo o link da documentação da ORACLE para melhor compreensão do assunto.

LINK LINK2

Utilizando Help no SQLPLUS

 

 

Neste post estarei falando sobre o uso de scripts do Oracle Database, para carregar  o comando HELP para o SQLPLUS que pode ajudá-lo rapidamente a tirar dúvidas sobre comandos do SQLPLUS. Os scripts de instalação e remoção do help esta em $ORACLE_HOME/sqlplus/admin/help

O esquema a ser utilizado é SYSTEM, não SYS.

Abaixo segue uma demonstração de como habilitar o HELP para o SQLPLUS.

1 – Entar no diretório abaixo:

cd $ORACLE_HOME/sqlplus/admin/help

2 – Listar o conteúdo do diretório

ls -l
total 84

-rwxrwxrwx. 1 oracle oracle   265 Feb 17 2003 helpbld.sql

-rwxrwxrwx. 1 oracle oracle   366 Jan 4 2011 helpdrop.sql

-rwxrwxrwx. 1 oracle oracle 71817 Aug 17 2012 helpus.sql

-rwxrwxrwx. 1 oracle oracle 2154 Jan 4 2011 hlpbld.sql

3 – Executar o script de instalação do HELP

sqlplus -S system/oracle @helpbld.sql `pwd` helpus.sql

1 row created. 

Commit complete.
1 row created.

Commit complete.
Table altered.
View created.
58 rows created.
Commit complete.
PL/SQL procedure successfully completed.

O ‘pwd’ é uma forma de especificar o diretório atual no Unix e no Linux e especifica onde o arquivo de dados de ajuda está localizado. o script helpus.sql são os arquivos de dados de ajuda em Inglês (US-Inglês).

Os scripts cria uma tabela chamada “HELP” no esquema SYSTEM. Ao executar o comando “HELP” do SQLPlus, esta tabela será utilizada.

  • Exemplo de Utilização do comando HELP.

SQL> connect hr/hr 

Connected.

 

SQL> help col

COLUMN
——
Specifies display attributes for a given column, such as:
– text for the column heading
– alignment for the column heading
– format for NUMBER data
– wrapping of column data
Also lists the current display attributes for a single column
or all columns.
COL[UMN] [{column | expr} [option …] ]
where option represents one of the following clauses:
ALI[AS] alias
CLE[AR]
ENTMAP {ON|OFF}
FOLD_A[FTER]
FOLD_B[EFORE]
FOR[MAT] format
HEA[DING] text
JUS[TIFY] {L[EFT] | C[ENTER] | R[IGHT]}
LIKE {expr | alias}
NEWL[INE]
NEW_V[ALUE] variable
NOPRI[NT] | PRI[NT]
NUL[L] text
OLD_V[ALUE] variable
ON|OFF
WRA[PPED] | WOR[D_WRAPPED] | TRU[NCATED]

SQL>

SQL> help set

SET

Sets a system variable to alter the SQL*Plus environment settings  for your current session. For example, to:

–   set the display width for data

–   customize HTML formatting

–   enable or disable printing of column headings

–   set the number of lines per page

SET system_variable value   where system_variable and value represent one of the following clauses:

 APPI[NFO]{OFF|ON|text}                   NEWP[AGE] {1|n|NONE}    ARRAY[SIZE] {15|n}                       NULL text    AUTO[COMMIT] {OFF|ON|IMM[EDIATE]|n}      NUMF[ORMAT] format    AUTOP[RINT] {OFF|ON}                     NUM[WIDTH] {10|n}    AUTORECOVERY {OFF|ON}                    PAGES[IZE] {14|n}    AUTOT[RACE] {OFF|ON|TRACE[ONLY]}         PAU[SE] {OFF|ON|text}      [EXP[LAIN]] [STAT[ISTICS]]             RECSEP {WR[APPED]|EA[CH]|OFF}    BLO[CKTERMINATOR] {.|c|ON|OFF}           RECSEPCHAR {_|c}    CMDS[EP] {;|c|OFF|ON}                    SERVEROUT[PUT] {ON|OFF}    COLSEP {_|text}                            [SIZE {n | UNLIMITED}]    CON[CAT] {.|c|ON|OFF}                      [FOR[MAT]  {WRA[PPED] |    COPYC[OMMIT] {0|n}                          WOR[D_WRAPPED] |    COPYTYPECHECK {ON|OFF}                      TRU[NCATED]}]    DEF[INE] {&|c|ON|OFF}                    SHIFT[INOUT] {VIS[IBLE] |    DESCRIBE [DEPTH {1|n|ALL}]                 INV[ISIBLE]}      [LINENUM {OFF|ON}] [INDENT {OFF|ON}]   SHOW[MODE] {OFF|ON}    ECHO {OFF|ON}                            SQLBL[ANKLINES] {OFF|ON}    EDITF[ILE] file_name[.ext]               SQLC[ASE] {MIX[ED] |    EMB[EDDED] {OFF|ON}                        LO[WER] | UP[PER]}    ERRORL[OGGING] {ON|OFF}                  SQLCO[NTINUE] {> | text}      [TABLE [schema.]tablename]             SQLN[UMBER] {ON|OFF}      [TRUNCATE] [IDENTIFIER identifier]     SQLPLUSCOMPAT[IBILITY] {x.y[.z]}    ESC[APE] {\|c|OFF|ON}                    SQLPRE[FIX] {#|c}    ESCCHAR {@|?|%|$|OFF}                    SQLP[ROMPT] {SQL>|text}    EXITC[OMMIT] {ON|OFF}                    SQLT[ERMINATOR] {;|c|ON|OFF}    FEED[BACK] {6|n|ON|OFF}                  SUF[FIX] {SQL|text}    FLAGGER {OFF|ENTRY|INTERMED[IATE]|FULL}  TAB {ON|OFF}    FLU[SH] {ON|OFF}                         TERM[OUT] {ON|OFF}    HEA[DING] {ON|OFF}                       TI[ME] {OFF|ON}    HEADS[EP] {||c|ON|OFF}                   TIMI[NG] {OFF|ON}    INSTANCE [instance_path|LOCAL]           TRIM[OUT] {ON|OFF}    LIN[ESIZE] {80|n}                        TRIMS[POOL] {OFF|ON}    LOBOF[FSET] {1|n}                        UND[ERLINE] {-|c|ON|OFF}    LOGSOURCE [pathname]                     VER[IFY] {ON|OFF}    LONG {80|n}                              WRA[P] {ON|OFF}    LONGC[HUNKSIZE] {80|n}                   XQUERY {BASEURI text|    MARK[UP] HTML [OFF|ON]                     ORDERING{UNORDERED|      [HEAD text] [BODY text] [TABLE text]              ORDERED|DEFAULT}|      [ENTMAP {ON|OFF}]                        NODE{BYVALUE|BYREFERENCE|      [SPOOL {OFF|ON}]                              DEFAULT}|      [PRE[FORMAT] {OFF|ON}]                   CONTEXT text}

SQL>

Para melhor entendermos, o HELP usa um arquivo de texto simples (script helpus.sql neste caso) para carregar as informações de ajuda.

NOTA: Os comando suportados pelo HELP são comandos SQLPlus, não Comandos de linguagem SQL. Logo,  o comando HELP não fornecerá ajuda sobre comandos CREATE ou ALTER ou SELECT e entre outros comandos.

Para remover o script instalado HELP, o procedimento é semelhante ao de instalação conforme podemos ver abaixo:

sqlplus -S system/oracle @helpdrop.sql `pwd` helpus.sql

  • Verificando a emoção do script HELP

sqlplus hr/hr

SQL*Plus: Release 11.2.0.1.0 Production on Tue Jul 26 22:11:45 2016
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> help
SP2-0171: HELP system not available.
SQL>

Um abraço a Todos!!

 

 

Utilizando Expressões Regulares

A partir da versão 10g do banco de dados a Oracle implementou o uso de expressões regulares. Uma expressão regular é uma expressão que define um padrão de caracteres. Você pode usar uma expressão regular para encontrar strings que correspondem a um padrão específico em uma string de dados. As funções de expressões regulares disponíveis no Oracle pode nos ajudar a realizar as tarefas de busca de caracteres de uma forma mais simples e rápida.

Você pode usar essas funções em uma literal de texto, variável bind ou qualquer coluna de dados de tipo de caracteres como: CHAR, NCHAR, CLOB, NCLOB, NVARCHAR2 e VARCHAR2 (exceto tipo de dados LONG).

As expressões regulares disponíveis no Oracle, são implementadas com as seguintes funções:

  • REGEXP_INSTR – Semelhante a função INSTR,  usa uma expressão regular em vez de uma literal como cadeia de procura.
  • REGEXP_LIKE – Semelhante a função LIKE, só que esta função usa uma expressão regular como cadeia de procura.
  • REGEXP_REPLACEO uso dessa função tem como objetivo procurar um padrão e substituí-lo por uma string.
  • REGEXP_SUBSTR – Retorna parte de uma string com recursos avançados, estende as funcionalidades da função SUBSTR, permitindo pesquisar uma string para uma expressão regular padrão. 
  • REGEXP_COUNT (Novidade na versão 11g) – Usado para obter a quantidade de vezes que uma expressão regular ocorre em uma string.

Logo abaixo montamos um cenário com dois exemplo, passo a passo de consultas utilizando expressões regulares:

1 – Utilizando REGEXP_LIKE(x, padrão[,opção_correspondente])  

Esta expressão realiza a busca em da expressão regular definida no parâmetro padrão. A opção_correspondente  pode ser definida com os valores abaixo:

  • ‘c’  – Especifica correspondência com diferenciação de maiúsculas e minúsculas (Padrão – case-sensitive)
  • ‘i’   – Especifica a busca sem diferenciação de caracteres maiúsculos e minúsculos (case-insensitive)
  • ‘n’  – Que permite usar o operador de correspondência com qualquer caractere.
  • ‘m’ – Que trata x como uma linha múltipla.
  • ‘x’  – ignora espaços em branco.

A semelhança com o comando LIKE não é mera coincidência, mas o leitor já poderá notar a maior flexibilidade no uso de REGEXP_LIKE  em relação ao operador  LIKE.

No primeiro exemplo abaixo, suponhamos a necessidade de achar na tabela de clientes, todos os clientes que tenham credito entre 10 e 19. Podemos realizar a busca usando expressões regulares da seguinte forma:

SELECT CUST_FIRST_NAME,CUST_LAST_NAME, CREDIT_LIMIT FROM SOE.CUSTOMERS  WHERE REGEXP_LIKE(CREDIT_LIMIT,’^1[0-9]$’);

Captura de Tela 2016-04-04 às 15.28.24

No segundo exemplo abaixo, foi feito um select para recuperar os clientes cujo sobrenome se iniciem com ‘Co’ ou ‘co’, o que é realmente um exemplo simples. Nesse caso  por exemplo,  podemos lançar mão do seguinte código, onde podemos observar que o metacaracter  “^” garante a busca no inicio do campo e a opção correspondente “i”  garante uma busca case-insensitive:

SELECT CUST_FIRST_NAME,CUST_LAST_NAME, CREDIT_LIMIT FROM SOE.CUSTOMERS  WHERE REGEXP_LIKE(CUST_LAST_NAME,’^Co’,’i’);

Captura de Tela 2016-04-04 às 15.18.05

OBS: A expressão regexp_like é uma ferramenta poderosa para consultas, mas no entanto não se deve usar essa expressão regular quando uma cláusula LIKE simples vai funcionar, pois haverá uma sobrecarga (full table scan) ao usar expressão regular em oposição a caracteres coringas.

2 –  REGEXP_REPLACE

SQL> SELECT PRODUCT_STATUS FROM PRODUCT_INFORMATION WHERE ROWNUM < 10;

Captura de Tela 2016-04-06 às 11.59.43

SQL> SELECT  REGEXP_REPLACE(PRODUCT_STATUS,’obsolete’,’obsoleto’) FROM PRODUCT_INFORMATION WHERE ROWNUM < 10;
Captura de Tela 2016-04-06 às 12.00.10

 

 

 

 

Conclusão:

As Expressões regulares são muito poderosas e permitem efetuar qualquer padrão de pesquisa, porém a sua utilização deve ser muito bem avaliada. Pois se forem mal utilizadas, poderão tornar as consultas muito lentas  e consequentemente, poderão degradar a performance da instrução SQL.

Para maiores informações e aprofundamento segue os links abaixo: