quarta-feira, 29 de dezembro de 2010

DBMS_SQL.DESCRIBE_COLUMNS

Busca o nome das colunas num SQL dinâmico.

 

DECLARE

   cur PLS_INTEGER := DBMS_SQL.OPEN_CURSOR;

   cols DBMS_SQL.DESC_TAB;

   ncols PLS_INTEGER;

BEGIN

   DBMS_SQL.PARSE

      (cur, 'SELECT * from SQ_TENSAO where id = 120', DBMS_SQL.NATIVE);

   DBMS_SQL.DEFINE_COLUMN (cur, 1, SYSDATE);

   DBMS_SQL.DEFINE_COLUMN (cur, 2, 1);

   DBMS_SQL.DESCRIBE_COLUMNS (cur, ncols, cols);

   FOR colind IN 1 .. ncols

   LOOP

      DBMS_OUTPUT.PUT_LINE (cols(colind).COL_name);     

   END LOOP;

   DBMS_SQL.CLOSE_CURSOR (cur);

END;

SQL Dinâmico

SQL Dinâmico

O SQL dinâmico permite que se crie procedimentos de propósito mais geral. Por exemplo, utilizando o SQL dinâmico você pode escrever um procedimento que opere sobre uma tabela cujo nome só será conhecido em tempo de execução. Ela permite ainda o uso da linguagem de definição de dados (DDL), isto é, permite que se crie (CREATE), altere (ALTER) e remova (DROP) objetos dentro de um procedimento ou bloco PL/SQL, o que não é permitido com declarações do SQL estático.

O SQL dinâmico é implementado pela package DBMS_SQL.

Usando a DBMS_SQL

Para que uma declaração SQL dinâmico possa ser processada é preciso que haja um cursor que guarde o identificador da declaração, este cursor (do tipo INTEGER) é diferente dos cursores convencionais da PL/SQL e é usado apenas pela biblioteca DBMS_SQL. O identificador é atribuído ao cursor pela função OPEN_CURSOR.

O próximo passo é se analisar gramaticalmente a declaração, utilizando o procedimento PARSE, ele analisa a sintaxe da consulta e a associa ao cursor. Caso a declaração analisada seja uma DDL ela será executada pelo procedimento e um commit implícito também será executado, portanto não é necessário executar o procedimento EXECUTE.

Se a declaração possuir referências a variáveis de ambiente, então é necessário que se insira um marcador para estas variáveis dentro da declaração, colocando o sinal (:) antes da variável, como em :nome. Depois que a declaração foi analisada pode-se ligar o valor às variáveis utilizando o procedimento BIND_VARIABLE, e quando a declaração for executada as variáveis serão substituídas pelos respectivos valores.

As colunas selecionadas por uma declaração SELECT são identificadas por suas posições relativas dentro da declaração. Em uma consulta você deve usar o procedimento DEFINE_COLUMN para especificar quais as variáveis que receberão que serão gerados quando a consulta for executada. Para colunas do tipo LONG é utilizado o procedimento DEFINE_COLUMN_LONG.

A declaração é executada pela função EXECUTE. Caso a declaração seja INSERT, UPDATE ou DELETE a função retorna o número de linhas processadas, caso contrário seu valor pode ser desprezado.

Se você definiu uma declaração SELECT então os valores retornados pela consulta podem ser extraídos do cursor utilizando-se a função FETCH_ROWS, esta função retorna 0 (zero) caso não haja mais registros a serem extraídos do cursor.

Se a declaração for uma consulta, os valores obtidos como resultado podem ser atribuídos a variáveis usando o procedimento COLUMN_VALUE ou COLUMN_VALUE_LONG para colunas do tipo LONG, caso a declaração seja uma chamada a um bloco PL/SQL, então o valor retornado por este bloco pode ser obtido com o procedimento VARIABLE_VALUE.

Quando você não for mais utilizar o cursor, ele deve ser fechado com o procedimento CLOSE_CURSOR para evitar que o bloco da memória não permaneça desnecessariamente alocada.

Procedimentos, Funções e Parâmetros

BIND_VARIABLE(cursor, variável, valor, [tamanho]) ; Permite a atribuição de um valor à variáveis de ambiente, tamanho é utilizado para variáveis do tipo VARCHAR2.

CLOSE_CURSOR(cursor) ; Fecha o cursor e libera a de memória associada.

COLUMN_VALUE(cursor, posição, variável[,erro][,tamanho]) ; Recupera um valor do cursor para a variável.

DEFINE_COLUMN(cursor, posição, variável) ; Associa colunas ou expressões da consulta com a variável.

EXECUTE(cursor) ; retorna INTEGER Executa a declaração associada ao cursor e retorna o número de linhas processadas.

FETCH_ROWS(cursor) ; retorna INTEGER Extrai do cursor os valores resultantes da consulta, retorna 0 (zero) caso não haja mais linhas.

IS_OPEN(cursor) ; retorna BOOLEAN Retorna TRUE se o cursor já estiver aberto e FALSE caso contrário.

OPEN_CURSOR ; retorna INTEGER Esta função "abre" o cursor e retorna um identificador para ele.

PARSE(cursor, declaração, flag) ; Analisa a declaração. flag especifica o comportamento que o Oracle terá durante a análise, pode ser: DBMS_SQL.V6 (para Versão 6), DBMS_SQL.V7 (para Versão 7) e

DBMS_SQL.NATIVE (para utilizar o comportamento de acordo com a base à qual ele está conectado)

VARIABLE_VALUE (cursor, variável_da_declaração, variável,[tamanho]) ; Recupera o valor da variável_da_declaração para a variável do bloco PL/SQL.

Usando SQL Dinâmico para Chamar Stored Procedures e Functions

Você pode também utilizar o SQL dinâmico para chamar stored procedures e functions de dentro de seu bloco PL/SQL. Para isto os passos são os seguintes:

- Chamar DBMS_SQL.OPEN_CURSOR para abrir um cursor;

- Se existir variáveis bind, vincule-as utilizando a procedure DBMS_SQL.BIND_VARIABLE;

- Execute a procedure ou function utilizando DBMS_SQL.EXECUTE;

- Se houver variáveis bind, chame DBMS_SQL.VARIABLE_VALUE para obter os valores associados a elas;

- Feche o cursor com a procedure DBMS_SQL.CLOSE_CURSOR.

Quando você utiliza a package DBMS_SQL para executar uma procedure ou function as variáveis passadas como parâmetro são tratadas como sendo bind, o mesmo acontece para variáveis que recebem os valores retornados por functions.

As variáveis associadas a parâmetros do tipo IN ou IN OUT devem ter valores associados antes que eles sejam passados para a procedure ou function. As variáveis do tipo VARCHAR2 ou CHAR que serão vinculadas a parâmetros do tipo OUT, devem ser inicializadas ou seu tamanho máximo deve ser passado para a procedure DBMS_OUTPUT.BIND_VARIABLE através do parâmetro tamanho.

Exemplos de SQL Dinâmico

Exemplo 1

O exemplo seguinte cria um procedimento (stored procedure) que realiza uma consulta em uma coluna de uma tabela, o nome da coluna e da tabela são passados como parâmetro para o procedimento.

CREATE OR REPLACE PROCEDURE SQL_DINAMICO(coluna IN VARCHAR2, tabela IN

VARCHAR2) IS

cur_handle INTEGER;

texto VARCHAR2(80);

temp NUMBER;

BEGIN

cur_handle := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cur_handle, 'SELECT '||coluna||' FROM '||tabela, DBMS_SQL.V7);

DBMS_SQL.DEFINE_COLUMN(cur_handle, 1, texto, 80);

temp := DBMS_SQL.EXECUTE(cur_handle);

LOOP

IF DBMS_SQL.FETCH_ROWS(cur_handle) = 0

THEN EXIT;

ELSE

DBMS_SQL.COLUMN_VALUE(cur_handle, 1, texto);

DBMS_OUTPUT.PUT_LINE(texto);

END IF;

END LOOP;

DBMS_SQL.CLOSE_CURSOR(cur_handle);

END SQL_DINAMICO;

/

Como neste caso a declaração SQL é uma consulta (SELECT) o valor da variável temp pode ser desprezado.

O procedimento pode ser criado através do SQL*Plus com o seguinte comando (supondo que o código esteja no arquivo EXEMPLO1.SQL) :

SQL> @EXEMPLO1.SQL

Este procedimento pode ser utilizado dentro de outros procedimentos ou blocos PL/SQL, ou pode ainda ser executado no SQL*Plus com o comando:

SQL> EXECUTE SQL_DINAMICO('ENAME','EMP')

que irá retornar os dados da coluna ENAME da tabela EMP.

Exemplo 2

Este segundo exemplo mostra a utilização de variáveis de ambiente (bind variables) em declarações SQL. Os marcadores :valor1 e :valor2 são inseridos na declaração SQL para indicar que serão utilizados valores obtidos a partir de variáveis de ambientes (no exemplo são bind1 e bind2) e o procedimento BIND_VARIABLE faz a ligação entre estas variáveis e os marcadores .

DECLARE

cur_handle INTEGER;

BEGIN

cur_handle := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cur_handle,

'INSERT INTO FONE VALUES (:valor1,:valor2)',DBMS_SQL.V7);

DBMS_SQL.BIND_VARIABLE(cur_handle,':valor1',:bind1);

DBMS_SQL.BIND_VARIABLE(cur_handle,':valor2',:bind2);

DBMS_OUTPUT.PUT_LINE('NUM. DE LINHAS INSERIDAS: '||DBMS_SQL.EXECUTE(cur_handle));

DBMS_SQL.CLOSE_CURSOR(cur_handle);

END;

/

Para a declaração utilizada (INSERT), a função EXECUTE retorna o número de

linhas inseridas.

As variáveis de ambiente poderiam ser ítens do Oracle Forms, seus valores poderiam ter sido atribuidos em outros blocos e procedimentos ou ainda podem ser difinidos a partir do SQL*Plus :

SQL> VARIABLE bind1 VARCHAR2(40)

SQL> VARIABLE bind2 VARCHAR2(40)

SQL> BEGIN

1 :bind1 := 'Oracle do Brasil';

2 :bind2 := 'http://www.oracle.com.br';

3 end;

4 /

e o bloco pode ser executado fazendo:

SQL> @EXEMPLO2.SQL

que irá inserir os dados na tabela FONE e emitir a mensagem:

NUM. DE LINHAS INSERIDAS: 1

PL/SQL procedure successfully completed.

Exemplo 3

Uma utilização da package DBMS_SQL para tornar os procedimentos ainda mais genéricos é mostrada neste exemplo. Ele cria um procedimento que recebe como argumento a declaração SQL inteira, não apenas parte dela. As declarações podem ser de inserção, alteração ou remoção. Sua listagem é mostrada a seguir.

CREATE OR REPLACE PROCEDURE QUERY(query_in IN VARCHAR2) IS

cur_handle INTEGER;

temp NUMBER;

BEGIN

cur_handle := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cur_handle, query_in, DBMS_SQL.V7);

temp := DBMS_SQL.EXECUTE(cur_handle);

DBMS_SQL.CLOSE_CURSOR(cur_handle);

DBMS_OUTPUT.PUT_LINE('Num. de linhas tratadas : '||temp);

END QUERY;

/

Novamente o procedimento deve ser criado com o comando :

SQL> @EXEMPLO3.SQL

e um exemplo de sua utilização é :

SQL> EXECUTE QUERY('INSERT INTO FONE VALUES (''DISCOVER TECHNOLOGY'',''(011)853-0692'')')

que irá retornar a mensagem :

Num. de linhas tratadas : 1

PL/SQL procedure successfully completed.

Exemplo 4

Neste exemplo, a package DBMS_SQL é utilizada para chamar uma stored function que retorna um VARCHAR2 e recebe como parâmetro uma variável do tipo IN NUMBER.

CREATE OR REPLACE FUNCTION RETORNA_TEXTO (numero IN NUMBER) RETURN VARCHAR2 AS

temp_var VARCHAR2(30);

BEGIN

temp_var := 'O valor passado foi ' || TO_CHAR(numero);

RETURN temp_var;

END;

/

DECLARE

cursor_handle NUMBER;

temp INTEGER;

valor NUMBER := 1;

-- Variável que receberá o valor retornado pela função é inicializada

-- com 30 espaços em branco

var_text VARCHAR2(30) := ' ';

BEGIN

cursor_handle := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_handle,'BEGIN :x1:=RETORNA_TEXTO(:x2); END;',DBMS_SQL.V7);

DBMS_SQL.BIND_VARIABLE(cursor_handle, ':x1', var_text);

DBMS_SQL.BIND_VARIABLE(cursor_handle, ':x2', valor);

temp := DBMS_SQL.EXECUTE(cursor_handle);

DBMS_SQL.VARIABLE_VALUE(cursor_handle, ':x1', var_text);

DBMS_SQL.CLOSE_CURSOR(cursor_handle);

DBMS_OUTPUT.PUT_LINE('var_text = ' || var_text);

END;

/

Para o caso em que a variável var_text não é inicializada, o bloco fica da seguinte forma:

DECLARE

cursor_handle NUMBER;

temp INTEGER;

valor NUMBER := 1;

var_text VARCHAR2(30);

BEGIN

cursor_handle := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_handle,'BEGIN :x1:=RETORNA_TEXTO(:x2); END;',DBMS_SQL.V7);

DBMS_SQL.BIND_VARIABLE(cursor_handle, ':x1', var_text, 30);

DBMS_SQL.BIND_VARIABLE(cursor_handle, ':x2', valor);

temp := DBMS_SQL.EXECUTE(cursor_handle);

DBMS_SQL.VARIABLE_VALUE(cursor_handle, ':x1', var_text);

DBMS_SQL.CLOSE_CURSOR(cursor_handle);

DBMS_OUTPUT.PUT_LINE('var_text = ' || var_text);

END;

/

Oracle para Excel - Função para gerar arquivo texto

Apresento uma função que recebe um script, grava um arquivo texto e retorna um parâmetro com a quantidade de registros gravados. Para abrir este arquivo no Excel coloque no parâmetro P_SEPARADOR o valor CHR(9), código ASCII para a tecla TAB.
Para executá-la utilize o scritp abaixo:

O código abaixo foi atualizado e melhorado em 03/10/2012


   select dump_csv('select * from tmp_arsesp_14',
                   chr(9), --Separador
                   'N',  --Entre aspas Sim ou Não
                   '/work/dump',
                   'Arquivo.csv',
                   'N') --Cabeçalho Sim ou Não   
    from dual;



create or replace function dump_csv( p_query     in varchar2,
                                      p_separator in varchar2 default ',',
                                      p_aspas     in varchar2 default 'n',
                                      p_dir       in varchar2 ,
                                      p_filename  in varchar2 ,
                                      p_cabecalho in varchar2 default 's' )


return number
is
   TYPE tipoCursor IS REF CURSOR;
   cursorDinamico tipoCursor;
    l_output        utl_file.file_type;
    l_theCursor     integer default dbms_sql.open_cursor;
    l_columnValue   varchar2(20000);
    l_column        varchar2(20000);
    l_status        integer;
    l_colCnt        number default 0;
    l_separator     varchar2(10);
    l_cnt           number default 0;
    l_tabela        varchar2(50);
    l_char          char(1);
    i               integer;
    l_pos_ini       integer;
    l_pos_fin       integer;
    l_cabecalho     varchar2(20000);
    l_linha         varchar2(20000);
begin
    l_output := utl_file.fopen( p_dir, p_filename, 'w' );

     l_separator := p_separator;

   -- Tratando cabeçalho 
   ---------------------
   if upper(p_cabecalho) = 'S' then
     if   instr(p_query,'*') > 0 then
          -- Pego o nome da tabela
          for i in instr(lower(p_query),'from ')+5..50 loop
            l_char := substr(p_query,i,1);
            exit when (l_char is null);
              l_tabela := l_tabela || l_char;
          end loop;

          open cursorDinamico for select column_name
                                    from all_tab_cols
                                   where table_name = upper(l_tabela)
                                   order by column_id;
          -- Gravo todos os campos da tabela no arquivo de saída

          loop
              fetch cursorDinamico into l_column;
              exit when cursorDinamico%NOTFOUND;
              
              if upper(p_aspas) = 'S'  then
                 l_cabecalho := l_cabecalho || '''' || l_column || '''' || l_separator;
              else
                 l_cabecalho := l_cabecalho || l_column || l_separator;
              end if;
            
                          
                 --   l_cabecalho := l_cabecalho || l_column || l_separator;
          end loop;
          close cursorDinamico;
          l_cabecalho := trim(l_cabecalho);
          l_cabecalho := substr(l_cabecalho,1,length(l_cabecalho)-1);
          UTL_FILE.put (l_output,l_cabecalho);          
          utl_file.new_line (l_output);                                   
                                   
                                   
                                   
/*          -- Gravo todos os campos da tabela no arquivo de saída
          loop
              fetch cursorDinamico into l_column;
              exit when cursorDinamico%NOTFOUND;
                   UTL_FILE.put (l_output,l_column || l_separator);
          end loop;
          close cursorDinamico;
          utl_file.new_line (l_output);*/
     else
          --  Gravo todos os campos do select no arquivo de saída
          l_pos_ini := instr(p_query,' ') + 1;
          l_pos_fin := instr(lower(p_query),'from') - 1;
          l_column := substr(p_query,l_pos_ini, l_pos_fin - l_pos_ini);
          l_column := replace(l_column,' ','');
          l_column := replace(l_column,',',  l_separator);

         -- dbms_output.put_line (l_column);
          UTL_FILE.put_line (l_output,l_column);
     end if;
  end if;
    
  -- fim tratando cabecalho
  -------------------------
  
  
    dbms_sql.parse(  l_theCursor,  p_query, dbms_sql.native );


    for i in 1 .. 255 loop
        begin
            dbms_sql.define_column( l_theCursor, i, l_columnValue, 2000 );
            l_colCnt := i;
        exception
            when others then
                if ( sqlcode = -1007 ) then exit;
                else
                    raise;
                end if;
        end;
    end loop;

    dbms_sql.define_column( l_theCursor, 1, l_columnValue, 2000 );


    l_status := dbms_sql.execute(l_theCursor);


    loop
        exit when ( dbms_sql.fetch_rows(l_theCursor) <= 0 );
        l_separator := p_separator;
        for i in 1 .. l_colCnt loop
            dbms_sql.column_value( l_theCursor, i, l_columnValue );
            if upper(p_aspas) = 'S'  then
              -- utl_file.put( l_output, '''' || l_columnValue || '''' || l_separator);
               l_linha := l_linha || '''' || l_columnValue || '''' || l_separator;
            else
              -- utl_file.put( l_output,   l_columnValue || l_separator);
               l_linha := l_linha || l_columnValue || l_separator;
            end if;
        end loop; 
            
        utl_file.put (l_output, substr(l_linha,1,length(l_linha)-1));
        l_linha := '';
        utl_file.new_line( l_output );
        l_cnt := l_cnt+1;
    end loop;


    dbms_sql.close_cursor(l_theCursor);


    utl_file.fclose( l_output );
    return l_cnt;
end dump_csv;



UTL_FILE ORA-29280: invalid directory path

Deve-se inserir no arquivo INIT.ORA a linha de comando abaixo, indicando que diretório que será utilizado no UTL_FILE.

UTL_FILE_DIR = 'C:\'

Após execute a linha de comando abaixo:

SHOW PARAMETER UTL_FILE_DIR;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
utl_file_dir                         string 

Se no campo VALUE não conter o valor “C:\” execute o comando abaixo:

ALTER SYSTEM SET UTL_FILE_DIR='C:\'

Caso ocorra o erro abaixo…

ORA-02095: specified initialization parameter cannot be modified

… complemente o comando da forma abaixo:

ALTER SYSTEM SET UTL_FILE_DIR='C:\' scope=spfile;

Após isso pare o serviço do Oracle e o reinicie.

Para verificar como utilizar o UTL_FILE acesse Utl_File Links.

terça-feira, 28 de dezembro de 2010

Bitwise operations

Most SQL implementations (like MySQL, PostgreSQL, MS SQL, SQLite, etc) provide bitwise operators (like ~, &, |, etc). The Oracle database doesn't support bitwise operators, but supports a bitAND function that can be used to provide similar functionality.

Oracle's bitAND (most SQL implementations use the & operator):

SQL> SELECT bitand(2, 4) FROM dual;
BITAND(2,4)
-----------
          0

To simulate bitOR (most SQL implementations use the | operator):

CREATE FUNCTION bitor(x IN NUMBER, y IN NUMBER) RETURN NUMBER AS
BEGIN
    RETURN x + y - bitand(x,y);
END;
/
SQL> SELECT bitor(2, 4) FROM dual;
BITOR(2,4)
----------
         6

To simulate bitXOR (most SQL implementations use the ^ operator):

CREATE FUNCTION bitxor(x IN NUMBER, y IN NUMBER) RETURN NUMBER AS
BEGIN
    RETURN bitor(x,y) - bitand(x,y);
END;
/ 
SQL> SELECT bitxor(2, 4) FROM dual;
BITXOR(2,4)
-----------
          6

To simulate bitNOT (most SQL implementations use the ~ operator):

CREATE FUNCTION bitnot(x IN NUMBER) RETURN NUMBER AS 
BEGIN
    RETURN (0 - x) - 1;
END;
/

Decimal para Binário

CREATE OR REPLACE FUNCTION dec2bin (N in number) RETURN varchar2 IS
  binval varchar2(64);
  N2     number := N;
BEGIN
  while ( N2 > 0 ) loop
     binval := mod(N2, 2) || binval;
     N2 := trunc( N2 / 2 );
  end loop;
  return binval;
END dec2bin;
/

SQL> SELECT dec2bin(22) FROM dual;

DEC2BIN(22)
----------------
10110

Simple decimal to binary conversion table:

Decimal Binary
0 0000 0000
1 0000 0001
2 0000 0010
3 0000 0011
4 0000 0100
5 0000 0101
6 0000 0110
7 0000 0111
8 0000 1000
9 0000 1001
10 0000 1010

Binário para Decimal

CREATE OR REPLACE FUNCTION bin2dec (binval in char) RETURN number IS
  i                 number;
  digits            number;
  result            number := 0;
  current_digit     char(1);
  current_digit_dec number;
BEGIN
  digits := length(binval);
  for i in 1..digits loop
     current_digit := SUBSTR(binval, i, 1);
     current_digit_dec := to_number(current_digit);
     result := (result * 2) + current_digit_dec;
  end loop;
  return result;
END bin2dec;
/
 
SQL> SELECT bin2dec('10110') FROM dual;
BIN2DEC('10110')
----------------
              22

Simple decimal to binary conversion table:

Decimal Binary
0 0000 0000
1 0000 0001
2 0000 0010
3 0000 0011
4 0000 0100
5 0000 0101
6 0000 0110
7 0000 0111
8 0000 1000
9 0000 1001
10 0000 1010

Decimal para Octal

CREATE OR REPLACE FUNCTION dec2oct (N in number) RETURN varchar2 IS
  octval varchar2(64);
  N2     number := N;
BEGIN
  while ( N2 > 0 ) loop
     octval := mod(N2, 8) || octval;
     N2 := trunc( N2 / 8 );
  end loop;
  return octval;
END dec2oct;
/

SQL> SELECT dec2oct(44978) FROM dual;
DEC2OCT(44978)
--------------
127662

Octal para Decimal

CREATE OR REPLACE FUNCTION oct2dec (octval in char) RETURN number IS
  i                 number;
  digits            number;
  result            number := 0;
  current_digit     char(1);
  current_digit_dec number;
BEGIN
  digits := length(octval);
  for i in 1..digits loop
     current_digit := SUBSTR(octval, i, 1);
     current_digit_dec := to_number(current_digit);
     result := (result * 8) + current_digit_dec;
  end loop;
  return result;
END oct2dec;
/
 
SQL> SELECT oct2dec(127662) FROM dual;
OCT2DEC(127662)
---------------
          44978

Decimal para Hexadecimal

CREATE OR REPLACE FUNCTION dec2hex (N in number) RETURN varchar2 IS
  hexval varchar2(64);
  N2     number := N;
  digit  number;
  hexdigit  char;
BEGIN
  while ( N2 > 0 ) loop
     digit := mod(N2, 16);
     if digit > 9 then 
       hexdigit := chr(ascii('A') + digit - 10);
     else
       hexdigit := to_char(digit);
     end if;
     hexval := hexdigit || hexval;
     N2 := trunc( N2 / 16 );
  end loop;
  return hexval;
END dec2hex;
/

SQL> SELECT dec2hex(44978)  FROM dual;
DEC2HEX(44978)
--------------
AFB2

Hexadecimal para Decimal

CREATE OR REPLACE FUNCTION hex2dec (hexval in char) RETURN number IS
  i                 number;
  digits            number;
  result            number := 0;
  current_digit     char(1);
  current_digit_dec number;
BEGIN
  digits := length(hexval);
  for i in 1..digits loop
     current_digit := SUBSTR(hexval, i, 1);
     if current_digit in ('A','B','C','D','E','F') then
        current_digit_dec := ascii(current_digit) - ascii('A') + 10;
     else
        current_digit_dec := to_number(current_digit);
     end if;
     result := (result * 16) + current_digit_dec;
  end loop;
  return result;
END hex2dec;
/

SQL> SELECT hex2dec('AFB2') FROM dual;
HEX2DEC('AFB2')
---------------
          44978

segunda-feira, 27 de dezembro de 2010

Diversos Links

Icones em alta definição
http://www.iconshock.com/


Photoshop
http://www.photoshopcreative.com.br
http://www.tutoriaisphotoshop.net/2006/10/arquivo-de-tutoriais.html
http://designclube.blogspot.com

Imagens Free
http://br.freepik.com
http://www.photoxpress.com
http://www.imotion.com.br/imagens

Caricaturas
http://socaricaturas.com.br
http://caricasdopadron.blogspot.com/

Ganhar Dinheiro com Blog
http://www.professionalblogger.com.br/voce-quer-ganhar-dinheiro-com-blogs/

Criação de DB-Links

Um database link é um objeto criado em um esquema de um banco de dados que possibilita o acesso a objetos de outro banco de dados, seja ele Oracle ou não. Esse tipo de sistema é conhecido como Sistema de Banco de Bados Distribuídos e pode ser Homogêneo – quando acessa outros bancos de dados Oracle - e Heterogêneo – quando acessam outros tipos de bancos de dados.

Para acessar bancos de dados que não sejam Oracle é necessário utilizar o Oracle Heterogeneous Services em conjunto com um agente.

O Heterogeneous Services é um componente integrante do Oracle server a partir de sua versão 8i que habilita a tecnologia dos produtos Oracle Transparent Gateway, sendo que Heterogeneous Services provê uma arquitetura comum e mecanismos de administração para os produtos Oracle gateway, além de outras facilidades de acesso a bancos heterogêneos.

Para acessar um banco de dados não Oracle utilizando um Oracle Transparent Gateway (agente) deve-se selecionar uma aplicação específica do sistema, ou seja, cada banco de dados específico requer um agente diferente.

Por exemplo, para criar um database link com um banco de dados Sybase é necessário obter um gateway transparente específico para Sybase para que então o banco de dados Oracle possa comunicar-se com ele. O agente executa comandos SQL e requisições de transações a bancos de dados não Oracle em nome do usuário da base de dados Oracle.

Pode-se, também, utilizar uma conectividade genérica para acessar bancos de dados não Oracle, como os protocolos ODBC ou OLE DB, através do uso dos Heterogeneous Services ODBC e OLE-DB, sem a necessidade de adquirir e configurar um agente específico para o banco de dados que se deseja acessar.

Neste artigo irei ensinar, em detalhes, a criar um database link homogêneo entre bancos de dados (inclusive de diferentes versões) Oracle. Ao criar um database link é possível utilizar e referenciar tabelas e visões do outro banco de dados, acrescentando ao final do nome destes objetos @nome_do_dblink.

Com o dblink e os privilégios necessários é possível utilizar comandos SELECT, INSERT, UPDATE, DELETE ou LOCK TABLE sobre os objetos desejados do banco de dados remoto, sabendo que uma transação do banco de dados irá incluir os comandos DML (linguagem de manipulação de dados) direcionados a dblinks, tornando as operações de COMMIT e ROLLBACK sobre tais bases, transparente.
clip_image001

Para a criação de um database link alguns pré-requisitos devem ser observados:
·  O usuário que irá criar o database link precisa ter o privilégio de sistema CREATE DATABASE LINK (para database links privados) ou CREATE PUBLIC DATABASE LINK (para database links públicos), além do privilégio de sistema CREATE SESSION no banco de dados Oracle remoto.
·  A ferramenta Oracle Net precisa estar instalada tanto para o banco de dados local quanto para o remoto.
·  O valor da variável GLOBAL_NAMES na instância onde o database link será criado, se configurada no arquivo de inicialização ou na sessão corrente (ALTER SESSION SET) do banco de dados como TRUE o nome global do banco de dados remoto deve ser utilizado (composto pelo nome_do_banco.domínio, ou seja, os parâmetros db_name.db_domain do arquivo de inicialização: initSID.ora). O nome global do banco de dados também pode ser descoberto através da execução do seguinte comando SELECT no banco remoto:
select GLOBAL_NAME from GLOBAL_NAME;

A criação, propriamente dita de um database link é realizada conectando-se no banco de dados local com um usuário que possua os privilégios necessários e executando o seguinte comando:
CREATE DATABASE LINK nome_do_dblink
CONNECT TO usuário_banco_remoto IDENTIFIED BY senha
USING 'connect_string';


Exemplo:
CREATE DATABASE LINK PRODUC
CONNECT TO scott IDENTIFIED BY tiger
USING 'PRODUC';

Com o comando especificado acima, o usuário atualmente conectado pode conectar-se ao banco de dados remoto PRODUC com se fosse o usuário Scott/tiger deste banco de dados remoto. Vale lembrar que o usuário especificado na criação do dblink deve existir no banco de dados remoto e caso a senha do usuário de conexão neste banco seja alterada é necessário destruir (DROP DATABASE LINK) e recriar o dblink com a identificação da nova senha do usuário de conexão, caso contrário o dblink deixará de funcionar.

Quando o usuário é especificado, juntamente com sua senha, na cláusula CONNECT TO, tem-se um database link especificado, caso contrário, tem-se um database link anônimo (ou conectado). No caso de database links anônimos o usuário da sessão corrente será utilizado como padrão. Por exemplo:
CREATE DATABASE LINK PRODUC USING 'PRODUC';

O valor especificado na cláusula USING é conhecido como connect_string (ou net_connect_string a partir do Oracle8i). A connect string precisa estar definida no Net8, no arquivo de configurações de nome TNSNAMES.ORA.

Por exemplo:
PRODUC = (DESCRIPTION = (ADDRESS = (COMMUNITY = tcp.world) (PROTOCOL = TCP) (Host = meteoro) (Port = 1521)) (CONNECT_DATA = (SID = PRODUC) (GLOBAL_NAME = PRODUC.com.br) (SERVER = DEDICATED)))
Para testar se o dblink foi criado com sucesso pode-se utilizar o seguinte comando SELECT:
SELECT * FROM emp@PRODUC;

Para manter-se a transparência no acesso a objetos de outros bancos de dados pode-se criar sinônimos públicos para os objetos acessados através do dblink.

Por exemplo:
CREATE PUBLIC SYNONYM emp FOR scott.emp@PRODUC

Pode-se também criar um dbkink como PUBLIC, que permite a todos os usuários do banco de dados local acessar os objetos do banco de dados remoto. Em geral, a opção de databases links públicos são criados apenas quando se utiliza a cláusula de autenticação, garantindo o aspecto de segurança no acesso a dados. Esta opção de database link está disponível apenas em configuração de servidores multi-thread.

Exemplo:
CREATE SHARED PUBLIC DATABASE LINK PUBLIC
CONNECT TO scott IDENTIFIED BY tiger
AUTHENTICATED BY admin IDENTIFIED BY adm123
USING 'PRODUC';


A cláusula AUTHENTICATED especifica o usuário e senha, neste exemplo ADMIN/ADM123 na instância remota, permitindo autenticar o usuário para o servidor remoto, potencializando o aspecto de segurança.

Para identificar quais os database links disponíveis ao usuário atual e para onde os mesmos apontam o seguinte comando SELECT pode ser utilizado para acessar a view de DBA, dba_db_links:
select OWNER, DB_LINK, USERNAME, HOST,
to_char(CREATED,'MM/DD/YYYY HH24:MI:SS') Criação
from dba_db_links
order by OWNER, DB_LINK;
Onde:
Owner – Nome do usuário criou o dblink; DBLink – Nome do dblink; Username – Nome do usuário para log no banco remoto; Host – SQL*Net de conexão (encontrada no arquivo TNSNAMES.ORA); Created – Data e hora de criação do dblink.
Restrições:
·  As seguintes operações não podem ser desenvolvidas utilizando-se database links:
·  Conceder privilégios em objetos remotos;
·  Executar operações de DESCRIBE em alguns objetos remotos, com exceção de tabelas, views, procedures e functions;
·  Realizar operações de ANALYZE objetos remotos;
·  Definir integridade referencial;
·  Conceder roles à usuários em a banco de dados remoto;
·  Obter roles além dos padrões do usuário de conexão no banco de dados remoto e Executar consultas com hash joins.
Fonte: http://www.criarweb.com/artigos/618.php
Related Posts Plugin for WordPress, Blogger...