segunda-feira, 27 de julho de 2009

Oracle anuncia nova estratégia para aplicação de patches - Patch Set Updates (PSU)

Olá,
Recentemente, a Oracle anunciou (14/07) um novo método para aplicação de correções em seus produtos. Esta nova categoria de pacote de correção se chama Patch Set Update (PSU) e, assim como o Critical Patch Update (CPU), será lançado trimestralmente (Janeiro, Abril, Julho, Outubro).

Este novo pacote de correção além de incluir o último CPU, também será cumulativo. De acordo com o Oracle My Support (Metalink), o primeiro PSU foi lançado para o Oracle 10g (10.2.0.4) e, para o Oracle 11g, a previsão de lançamento do primeiro PSU será em Outubro/2009.

Como dito anteriormente, o PSU será cumulativo, ou seja, cada PSU conterá todas as correções do seu antecessor. Vale a pena salientar que estes pacotes de atualização só estão disponíveis para download através do site Oracle Metalink (My Oracle Support). Portanto, para quem quiser realizar o download das atualizações, terá que ter um contrato de suporte com a Oracle e ter em mãos um código de identificador de suporte válido (Customer Support Identifier – CSI).

Aplicações do PSU:

10.2.0.4.[0] --> 10.2.0.4.[1] --> 10.2.0.4.[2] --> 10.2.0.4.[3] ...






Para maiores informações, acesse as notas referentes ao PSU no site do My Oracle Support (Metalink):

854428.1 - Introduction to Oracle Patch Set Updates (PSU)

850471.1 - Oracle Announces First Patch Set Update For Oracle Database Release 10.2
854473.1 - Known Issues with this Patch Set Update 10.2.0.4.1
8576156.8 - Bug 8576156 10.2.0.4.1 Patch Set Update (PSU)

quarta-feira, 15 de julho de 2009

Testando algumas das compatibilidades do Postgres Plus Advanced Server com o Oracle

Olá,

Para quem teve a oportunidade de ler o artigo de Abril de 2009 intitulado de "Mercado de banco de dados mais acirrado ...", pôde perceber que o Postgres Plus Advanced Server (PAS) trouxe de forma embutida (através de um catálogo adicional), algumas funcionalidades compatíveis com o Oracle, como suporte ao Oracle PL/SQL, algumas views de dicionários de banco de dados USER/ALL/DBA_*, Public Synonyms, Sequences (CURRVAL, NEXTVAL), functions, packages, triggers, tipos de dados (CHAR, VARCHAR, VARCHAR2, NUMBER, BLOB, CLOB, DATE), pseudo-coluna ROWNUM, a tabela DUAL, entre algumas outras funcionalidades.

Apesar de não ser um artigo "diretamente" direcionado ao banco de dados Oracle, mas, já que envolve algumas funcionalidades do próprio Oracle, então irei demonstrar alguns testes que timidamente estou começando a realizar, afim de testar tais compatibilidades. Irei utilizar a versão 8.3 R2 (8.3.0.106) do Postgres PAS para realizar algumas operações básicas.

Vale a pena salientar que no caso do PostgreSQL, o mesmo utiliza um catálogo de dicionários de dados próprio (pg_catalog) e um outro catálogo conforme definido pelo padrão ANSI-92 (information_schema), na qual o Oracle não segue. Fazendo uma pequena comparação, um mesmo catálogo de dicionário de dados no Oracle, está sobre propriedade do usuário SYS através de inúmeras views de dicionário de dados. Uma outra forma de se obter informações de metadados no Oracle é utilizando o comando [DESC]RIBE no SQL*Plus ou através da package DBMS_METADATA disponível desde a versão Oracle 9i.

Portanto, no caso do Postgres PAS, foi criado um catálogo chamado de Redwood(sys) para fornecer algumas das views de dicionário de dados do Oracle. Em se tratando de algumas incompatibilidades conhecidas entre o PostgreSQL e o Oracle, posso citar que o pacote de compatibilidade com o Oracle visa estender algumas funcionalidades do Postgres como:
  • Permitir o uso de views de dicionário de dados USER/ALL/DBA_* mais comuns;
  • Permitir a execução de códigos escritos em PL/SQL estendendo o uso de stored procedures, entre outros;
  • Permitir o uso do operador (+) em junções externas (outer joins);
  • Permitir o uso de comandos como CREATE USER, DROP USER, ALTER USER, entre outros;
  • Permitir o uso do tipo de dado VARCHAR2 pois no PostgreSQL apenas existe o tipo VARCHAR;
  • Permitir o uso do tipo de dado NUMBER pois no PostgreSQL apenas existe o tipo NUMERIC;
  • Permitir o uso do tipo de dado CLOB pois no PostgreSQL apenas existe o tipo TEXT;
  • Permitir o uso do tipo de dado BLOB pois no PostgreSQL o mesmo é implementado através dos tipos BYTEA e OID;
  • Permitir suporte à função DECODE, já que PostgreSQL isso é realizado através de expressões CASE;
  • Permitir o uso da função NVL já que PostgreSQL temos apenas o suporte da função COALESCE;
  • Permitir o uso das funções SYSDATE e SYSTIMESTAMP no PostgreSQL;
  • Permitir o uso do operador MINUS já que PostgreSQL implementa o operador EXCEPT;
  • Permitir o uso da pseudo-coluna ROWNUM já que o PostgreSQL implementa o uso da cláusula LIMIT e OFSET;
  • Permitir o uso das funções (CURRVAL, NEXTVAL) no uso de seqüências utilizando a mesma sintaxe do Oracle;
  • Permitir o uso da tabela DUAL já que no PostgreSQL a mesma não é necessária;
  • entre outras funcionalidades ...
Agora indo para a prática, após instalado e configurado o Postgres PAS, foi criado o banco de dados chamado de BD01 como demonstrado na figura abaixo. A partir de agora, irei utilizar o utilitário EDB*Plus fornecido junto com o Postgres PAS, na qual poderemos perceber mais abaixo, ser nada mais do que um "clone magro" do SQL*Plus ...



-- Conectando com o super-usuário
C:\>edbplus enterprisedb/manager@localhost:5444/bd01
Connected to EnterpriseDB 8.3.0.106 (localhost:5444/bd01) AS enterprisedb

EDB*Plus: Release 8.3 (Build 18)
Copyright (c) 2008-2009, EnterpriseDB Corporation. All rights reserved.

-- Mostrando o usuário corrente que está logado
SQL> show user
USER is "enterprisedb"


-- Verificando a versão do banco de dados
SQL> select * from v$version;

BANNER
--------------------------------------------------
Oracle Database 10g Edition Release 10.2.0.1.0 - P
PL/SQL Release 10.2.0.1.0 - Production is similar
CORE 10.2.0.1.0 Production is similar

-- Mostrando a data atual
SQL> select to_char(sysdate,'dd/mm/yyyy') from dual;

TO_CHAR
----------
15/07/2009

-- Criando um usuário/schema de teste
SQL> create user scott identified by tiger;

Role created.

-- Concedendo algumas atribuições
SQL> grant connect,resource,dba to scott;

Role granted.

-- Concetando com o usuário SCOTT
SQL> connect scott/tiger@localhost:5444/bd01;
Disconnected from EnterpriseDB Database.
Connected to EnterpriseDB 8.3.0.106 (localhost:5444/bd01) AS scott

-- Mostrando o usuário corrente que está logado
SQL> show user
USER is "scott"

-- Mostrando as opções disponíveis no EDB*Plus
SQL> show all
autocommit OFF
colsep " "
define "&"
echo OFF
FEEDBACK ON for 6 row(s).
flush ON
heading ON
headsep "|"
linesize 80
newpage 1
null " "
pagesize 14
pause OFF
serveroutput OFF
spool OFF
sqlcase MIXED
sqlprompt "SQL> "
sqlterminator ";"
suffix ".sql"
termout ON
timing OFF
verify ON
USER is "scott"
HOST is "localhost"
PORT is "5444"
DATABASE is "bd01"
VERSION is "8.3.0.106"

-- Obtendo informações da estrutura da view DBA_USERS
SQL> desc dba_users

Name Null? Data Type
---------------------------------------- -------- ---------------------------
USERNAME CLOB
USER_ID OID
PASSWORD VARCHAR2(30)
ACCOUNT_STATUS VARCHAR2(32)
LOCK_DATE DATE
EXPIRY_DATE DATE
DEFAULT_TABLESPACE VARCHAR2(30)
TEMPORARY_TABLESPACE VARCHAR2(30)
CREATED DATE
PROFILE VARCHAR2(30)
INITIAL_RSRC_CONSUMER_GROUP VARCHAR2(30)
EXTERNAL_NAME VARCHAR2(4000)

-- Verificando usuários/schemas disponíveis no banco de dados
SQL> set linesize 80
SQL> select username,password,default_tablespace,account_status from dba_users;

USERNAME PASSWORD DEFAULT_TABLESPACE ACCOUNT_STATUS
-------------------- ------------------------------ --------------------- --------------
ENTERPRISEDB md59709ec8c91b5809603a24f09975 pg_default OPEN
ADAM md546d5f32a35e4a038de7d0a7ae3c pg_default OPEN
SCOTT md5f5b3b8231a686f681fdee8f66bf pg_default OPEN

-- Dropando o usuário/schema ADAM
SQL> drop user adam;

Role dropped.

-- Criando uma tabela de teste (T1)
SQL> create table t1 (a number, b varchar2(10), c date, d clob);

Table created.

-- Adicionando uma chave primária à tabela T1
SQL> alter table t1 add constraint pk_t1 primary key (a);

Table altered.

-- Verificando a estrutura da tabela T1
SQL> set linesize 80
SQL> desc t1

Name Null? Data Type
----------------------------- -------- ----------------------
A NOT NULL NUMBER(38)
B VARCHAR2(10)
C DATE
D CLOB

-- Selecionando dados da view USER_CONSTRAINTS
SQL> select schema_name,constraint_name,table_name
2 from user_constraints
3 where table_name='T1';

SCHEMA_NAME CONSTRAINT_NAME TABLE_NAME
------------- ------------------ -------------------
SCOTT PK_T1 T1

-- Realizando um procedimento PL/SQL simples
SQL> set serveroutput on
SQL> begin
2 for i in 1..10
3 loop
4 insert into t1 values (i,to_char(sysdate,'mm/yyyy'),sysdate,'teste CLOB');
5 dbms_output.put_line(i);
6 end loop;
7 end;
8 /
1
2
3
4
5
6
7
8
9
10

EDB-SPL Procedure successfully completed.

SQL> commit;

COMMIT completed.

-- Selecionando registros da tabela T1
SQL> select * from t1 order by a;

A B C D
---------- ---------- ----------------------------- -----------
1 07/2009 2009-07-15 10:13:17 teste CLOB
2 07/2009 2009-07-15 10:13:17 teste CLOB
3 07/2009 2009-07-15 10:13:17 teste CLOB
4 07/2009 2009-07-15 10:13:17 teste CLOB
5 07/2009 2009-07-15 10:13:17 teste CLOB
6 07/2009 2009-07-15 10:13:17 teste CLOB
7 07/2009 2009-07-15 10:13:17 teste CLOB
8 07/2009 2009-07-15 10:13:17 teste CLOB
9 07/2009 2009-07-15 10:13:17 teste CLOB
10 07/2009 2009-07-15 10:13:17 teste CLOB

10 rows retrieved.

-- Testando a funcionalidade da pseudo-coluna ROWNUM
SQL> select * from t1 where rownum <=5;

A B C D
---------- ---------- ----------------------------- ----------
1 07/2009 2009-07-15 10:13:17 teste CLOB
2 07/2009 2009-07-15 10:13:17 teste CLOB
3 07/2009 2009-07-15 10:13:17 teste CLOB
4 07/2009 2009-07-15 10:13:17 teste CLOB
5 07/2009 2009-07-15 10:13:17 teste CLOB


SQL> create table t2 as select * from t1;

Table created.

SQL> insert into t2 values (11,'teste',sysdate,'teste CLOB');

1 row INSERTED.

-- Testando a funcionalidade do operador MINUS
SQL> select * from t2
2 minus
3 select * from t1;

A B C D
---------- ---------- ----------------------------- ----------
11 teste 2009-07-15 10:20:25 teste CLOB

-- Testando a funcionalidade da função DECODE
SQL> select decode(a,1,'um',2,'dois',3,'tres','outro') from t1;

DECODE
--------------------------------------------
um
dois
tres
outro
outro
outro
outro
outro
outro
outro

10 rows retrieved.

-- Testando a funcionalidade da função NVL
SQL> select nvl(null,0) from dual;

NVL
----------
0

-- Testando a funcionalidade da função NVL2
SQL> select nvl2(null,0,1) from dual;

NVL2
-----------
1

-- Testando a funcionalidade da função TRANSLATE, apesar do PostgreSQL já ter suporte
-- para a mesma. O SQL abaixo foi executado no pgAdmin III pelo fato de eu ainda não
-- ter
conseguido habilitar caracteres especiais no EDB*Plus
SQL> select upper (
2 translate( 'Exceção, Única, Rápido',
3 'ÁÇÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕËÜáçéíóúàèìòùâêîôûãõëü',
4 'ACEIOUAEIOUAEIOUAOEUaceiouaeiouaeiouaoeu'))
5 from dual;

UPPER
--------------------------------------------
EXCECAO, UNICA, RAPIDO

SQL> drop table t2;

Table dropped.

-- Testando a compatibilidade em relação à sequências de banco de dados
SQL> create sequence seq_doc increment by 1 start with 1 nomaxvalue minvalue 0 nocache;

Sequence created.

SQL> select seq_doc.nextval from dual;

NEXTVAL
--------------------
1

SQL> select seq_doc.nextval from dual;

NEXTVAL
--------------------
2

SQL> select seq_doc.currval from dual;

CURRVAL
--------------------
2

Agora irei testar a criação de procedimentos armazenados (stored procedures), pois no PostgreSQL esse conceito, e normalmente esses objetos, são criados criados como funções (functions)

SQL> create table t3 (id number);

Table created.

SQL> create or replace procedure sp_insere (p_num number) as
2 begin
3 declare
4 v_num number;
5 begin
6 v_num := p_num;
7 insert into t3 values (v_num);
8 end;
9 end;
10 /

Procedure created.

SQL> desc sp_insere

PROCEDURE SP_INSERE
Argument Name Type In/Out Default?
-------------------------------- ---------------------- ------ --------
P_NUM NUMBER IN


SQL> exec sp_insere(100);

EDB-SPL Procedure successfully completed.

SQL> select * from t3;

ID
----------
100

Em relação ao famoso operador (+) do Oracle para construção de junções externas entre tabelas, e, já que o PostgreSQL suporta apenas o padrão ANSI LEFT/RIGHT JOIN, irei abaixo realiar um teste com o operador (+):

SQL> create table t4 (id number);

Table created.

SQL> create table t5 (id number);

Table created.

SQL> insert into t4 values (1);

1 row INSERTED.

SQL> insert into t4 values (2);

1 row INSERTED.

SQL> insert into t5 values (1);

1 row INSERTED.

-- Testando SQL join padrão ANSI
SQL> select t4.id,t5.id from t4 left outer join t5 on (t4.id = t5.id);

ID ID
---------- ----------
1 1
2

-- Testando SQL join padrão Oracle com o sinal (+)
SQL> select t4.id,t5.id from t4,t5 where t4.id = t5.id(+);

ID ID
---------- ----------
1 1
2

Bom, após a realização de testes de alguns comandos básicos, deparei-me com uma de minhas funções de banco de dados que funciona perfeitamente no Oracle, mas que apresentou problemas ao ser executada no Postgres Plus Advanced Server. Percebi que os procedimentos PL/SQL armazenados no Postgres PAS são validados apenas quando os mesmos são executados. O problema que encontrei está relacionado ao tipo de dado retornado na realização de uma conta matemática como demonstrado abaixo:

-- Realizando o teste no Oracle 10g via SQL*Plus
ORACLE10g> select 2.2*100 VAL from dual;

VAL
----------
220

-- Realizando o teste no Postgres PAS via EDB*Plus
SQL> select 2.2*100 val from dual;

VAL
----------
220.0

Portanto, sem entrar em muitos detalhes, a lógica na minha função não espera o resultado com "0" (zeros à direita) e para que seja retornado o mesmo valor retornado pelo Oracle, precisei realizar um CAST explícito como demonstrado abaixo:

SQL> select cast(2.2*100 as integer) val from dual;

VAL
-----------
220

Apenas para ficar bem claro como isso impactou no resultado de retorno da função de banco de dados, abaixo está um trecho da função na qual o resultado precisaria ser exatamente como este:

-- Realizando no Oracle 10g via SQL*PLUS
ORACLE10g> select lpad(to_char(2.2*100),14,'0') from dual;

LPAD(TO_CHAR(2
--------------
00000000000220

No Postgres Plus Advanced Server o tipo retornado não foi do tipo INTEGER:

-- Realizando no Postgres PAS via EDB*PLUS
SQL> select lpad(to_char(2.2*100),14,'0') from dual;

LPAD
--------------------------------------------
000000000220.0

Como demonstrado abaixo, precisei realizar explicitamente um CAST de forma a alterar o tipo de dado retornado para o tipo INTEGER:

-- Realizando no Postgres PAS via EDB*PLUS
SQL> select lpad((cast(2.2*100 as integer)),14,'0') from dual;

LPAD
--------------------------------------------
00000000000220

SQL> exit
Disconnected from EnterpriseDB Database.

No mais, ainda precisarei realizar muitos testes, mas acredito que a compatiblidade atual do Postgres Plus Advanced Server com algumas funcionalidades do Oracle ainda irão me surpreender muito ...

quarta-feira, 8 de julho de 2009

Lançada a primeira versão de produção do Oracle SQL Developer Data Modeler

Olá,


A equipe de desenvolvimento de ferramentas da Oracle, recentemente anunciou e disponibilizou para download, a primeira versão de produção do Oracle SQL Developer Data Modeler (2.0.0.57.0). Para quem ainda não conhece, o OSDM é uma ferramenta gráfica útil para a construção e modelagem de dados visando facilitar e melhorar a comunicação entre arquitetos e administradores de dados, DBAs, desenvolvedores de aplicações e usuários.

No mais, para quem teve problemas na utilização das releases anteriores, conforme comentários postados no artigo de Novembro de 2008 intitulado de "Lançado o Oracle SQL Developer Data Modeling", vale a pena baixar e conferir esta nova versão.

quinta-feira, 2 de julho de 2009

Abordando o uso de Database Links em conexões heterogêneas. Acessando o PostgreSQL à partir do Oracle ...

Olá,

Para quem utiliza o serviço heterogêneo de conectividade "heterogeneous services" (hsodbc) para a realização de conexão entre um banco de dados Oracle e um banco de dados não-oracle, perceberá que no Oracle 11g o programa hsodbc foi substituído pelo dg4odbc (Database Gateway for ODBC). Percebi isso quando tentei, para fins de teste, "interligar" um banco de dados Oracle 11g à um banco de dados PostgreSQL. Lembro-me de que alguns anos atrás, não tive maiores problemas ao realizar este tipo de conexão entre um Oracle 10g (instalado em um Suse Linux 32 bits) e um banco de dados PostgreSQL 7x. Naquela época fiz uso das bibliotecas genéricas UNIXODBC. Hoje, utilizando o Oracle 11g em uma plataforma 64 bits, e após ter realizado algumas tentativas mal sucedidas utilizando o UNIXODBC, acabei apelando por fazer o uso de uma versão para avaliação de bibliotecas de terceiros. No mais, neste artigo, irei demonstrar os passos que realizei para acessar um banco de dados PostgreSQL 8.2.4 através de um objeto (database link) criado à partir do Oracle 11g (11.1.0.7) 64 bits instalado em um Linux CentOS release 5.2.

Como eu mencionei o termo (database link), primeiramente irei fazer uma breve apresentação sobre esse objeto:

Um database link (link de banco de dados) é um tipo especial de objeto criado em um esquema de banco de dados Oracle que permite o acesso direto a objetos de outro banco de dados, seja ele Oracle (homogêneo) ou não (heterogêneo).



Um database link geralmente é utilizado para suportar conexões utilizadas freqüentemente em bancos de dados remotos. Este objeto, na verdade, especifica o descritor de conexão a ser utilizado em uma conexão e também pode especificar o nome de usuário a ser conectado ao banco de dados remoto. Vale a pena salientar que, no geral, se utiliza links de banco de dados de forma a criar objetos locais (como views ou sinônimos) que acessam bancos de dados remotos.

Os sinônimos locais para objetos remotos, fornecem transparência de localização para os usuários locais do banco de dados, ou seja, quando um link de banco de dados é referenciado diretamente ou através de um sinônimo ou uma view, a instrução SQL é enviada e executada em uma nova sessão no banco de dados remoto. Ao ser executada, os dados são retornados para a sessão no banco de dados de origem.

Os links de banco de dados podem ser criados como links públicos (por DBA's) tornando os mesmos disponíveis para todos os usuários de banco de dados local ou como links privados. Para a criação deste objeto, se utiliza a sintaxe abaixo:

CREATE [ SHARED ] [ PUBLIC ] DATABASE LINK dblink
[ CONNECT TO
{ CURRENT_USER
| user IDENTIFIED BY password [ dblink_authentication ]
}
| dblink_authentication
]
[ CONNECT TO
{ CURRENT_USER
| user IDENTIFIED BY password [ dblink_authentication ]
}
| dblink_authentication
]...
[ USING connect_string ] ;

Por exemplo, o comando abaixo iria criar um link de banco de dados público chamado DBLINK:

SQL> create public database link DBLINK
2 connect to SCOTT identified by TIGER
3 using 'DB02';

onde, 'DB02' é o nome de serviço de banco dados existente no arquivo TNSNAMES.ORA local do meu servidor Oracle, na qual estão configuradas as informações da localização do servidor de banco de dados remoto.

Para utilizar esse database link, bastaria apenas adicioná-lo como sufixo aos nomes das tabelas como demonstrado na criação da view abaixo:

SQL> create view emp_remoto
2 as
3 select * FROM emp@DBLINK
4 where cod_dept > 10;

Podemos ver no exemplo acima que a cláusula "FROM" refere-se à EMP@DBLINK, onde, EMP é a tabela de destino, e DBLINK o objeto (database link) que contém as informações "encapsuladas" das informações do banco de dados de destino.

A propósito, no exemplo anterior foi criada uma view de banco de dados (emp_remoto), com o objetivo de simular uma regra de negócio na qual seria limitado os registros que os usuários poderiam recuperar, mas, se nenhuma restrição desse tipo for necessária, então poderíamos criar um sinônimo público como mostrado pelo comando abaixo:

SQL> create public synonym emp_remoto for emp@DBLINK;

Os usuários locais que consultarem o sinônimo público local EMP_REMOTO terão suas consultas automaticamente redirecionadas à tabela EMP do banco de dados remoto e, portanto, de forma transparente.

Irei demonstrar abaixo um exemplo prático na qual criarei um database link em um banco de dados Oracle 10g Express Edition para permitir acesso a um banco de dados Oracle 11g instalado em outro servidor. Observe que passarei a string de conexão diretamente no comando de criação do database link, sem a necessidade de ter definido previamente um serviço TNS de banco de dados, referente à instância Oracle remota no arquivo local TNSNAMES.ORA:

oracle@xe-developer:~> sqlplus / as sysdba

SQL*Plus: Release 10.2.0.1.0 - Production on Qui Jul 02 08:03:52 2009

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

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

SQL> create database link dblink11g
2 connect to system identified by minhasenha
3 using '(description = (address = (protocol = tcp)
4 (host = 11g_production)(port = 1521))
5 (connect_data = (sid = bdprod)))';

Vínculo de banco de dados criado.

-- Selecionando informações do banco de dados local
SQL> select instance_name,host_name from v$instance;

INSTANCE_NAME HOST_NAME
---------------- --------------------------------------
XE xe-developer


-- Selecionando informações do banco de dados remoto
SQL> select instance_name,host_name from v$instance@dblink11g;

INSTANCE_NAME HOST_NAME
---------------- --------------------------------------
BDPROD 11g_production

Bom, depois dessa breve introdução ao conceito de Database Links, vamos voltar ao assunto que originou este artigo ...

Para início, é bom ficar claro que na versão 11g do banco de dados Oracle, não será mais possível executar o utilitário abaixo como nas versões anteriores:

[oracle@Linux ~]$ hsodbc

Oracle Corporation --- QUINTA-FEIRA JUL 02 2009 08:17:25.104

Heterogeneous Agent Release 10.2.0.1.0 - Production Built with
Driver for ODBC

Caso alguma tentativa de acesso ao programa hsodbc seja realizada utilizando o Oracle 11g, o erro abaixo será retornado:

[oracle@Linux ~]$ hsodbc
-bash: hsodbc: command not found

Portanto, deverá ser utilizado o programa dg4odbc que, inclusive, poderá ser instalado e utilizado em versões anteriores ao Oracle 11g conforme a nota 466228.1 do Oracle Metalink:

"Starting with 11g Oracle now provides a Database Gateway for ODBC for 32bit Linux operating systems. The difference between the older product (Generic Connectivity or sometimes also called HSODBC) is DG4ODBC is now a stand alone product. It is no longer required to have DG4ODBC running on the same machine as the Oracle database. The gateway is certified also for older Oracle releases 9.2.0.8, 10.1.0.5, or 10.2.0.3. But please be aware those pre-11g Oracle databases require a patch to work properly with V11 Gateways."

[oracle@Linux ~]$ dg4odbc

Oracle Corporation --- QUINTA-FEIRA JUL 02 2009 08:20:35.379

Heterogeneous Agent Release 11.1.0.7.0 - 64bit Production Built with
Oracle Database Gateway for ODBC

[oracle@Linux ~]$

Após ter realizado o download das bibliotecas (64 bits) de avaliação do site em questão, irei iniciar a instalação das mesmas:

[root@Linux tmp]# tar xzvf evlinuxx64.tar.Z
autorun.dat
install.mi
unixmi.ksh
etc/lang/
etc/lang/msg.dat
etc/lang/license.txt
etc/lang/useng.msg
etc/lic/
etc/lic/makelica
etc/lic/makeliclx
etc/lic/makelicl
etc/lic/makelich
etc/lic/makelicsx
etc/lic/makelics
linuxx/ICULicense.txt
linuxx/mysqllicense.txt
linuxx/ODBC64FIXES.TXT
linuxx/ODBC64README.TXT
linuxx/scr1
linuxx/tarfiles/
linuxx/tarfiles/teradata.tar
linuxx/tarfiles/mssql.tar
linuxx/tarfiles/oracle.tar
linuxx/tarfiles/sybase.tar
linuxx/tarfiles/mysql.tar
linuxx/tarfiles/oraclewp.tar
linuxx/tarfiles/linuxx.tar
linuxx/tarfiles/greenplum.tar
linuxx/tarfiles/drda.tar
linuxx/tarfiles/postgresql.tar
linuxx/tarfiles/infcl.tar

[root@Linux tmp]# ksh unixmi.ksh
DataDirect Technologies Product Setup is preparing....

English has been set as the installation language.

Log file : /tmp/logfile.9216.1
----------------------------------------------------------------------
DataDirect Technologies Product Setup (DPS)
for UNIX operating systems
----------------------------------------------------------------------

The following operating system has been detected:

LinuxX64
Is this the current operating system on your machine (Y/N) ? [Y]
END USER PRODUCT LICENSE AGREEMENT ("AGREEMENT")

DataDirect EULA Revised 02/12/2009

Enter YES to accept the above agreement : yes
Please enter the following information for proper registration.

In the Key field, enter either EVAL or the Key provided.

Name :EVAL
Company :legatti - evaluation
Serial Number :EVAL
Key :EVAL

You can install drivers for all supported databases or
install a single driver.

Drivers for All Supported Databases includes one driver for each supported database.
In the case of Oracle, DataDirect Connect64 for ODBC 6.0 SP1 has two available drivers
that support the database--a wire protocol driver that does not require any database
client software to connect to the database, and a client-based driver that does require
client software. By default, the Oracle Wire Protocol driver is installed.

Single Driver allows you to choose one from any of the DataDirect Connect64 for
ODBC 6.0 SP1 drivers, including the client-based Oracle driver.

If you want to evaluate more than one single driver, you will have the opportunity to do
so after completion of the initial installation.

1. Drivers for All Supported Databases
2. Single Driver
Please enter an option [1]:2


1. DB2 Wire Protocol
2. Greenplum Wire Protocol
3. Informix Wire Protocol
4. MySQL Wire Protocol
5. Microsoft SQL Server Wire Protocol
6. Oracle Wire Protocol
7. PostgreSQL Wire Protocol
8. Sybase Wire Protocol
9. Teradata (XE)
10. Oracle (client)
Please enter driver option:7

You have chosen to eval the PostgreSQL Wire Protocol driver.

To change this information, enter C. Otherwise, press Enter to continue. :

You have chosen to eval the PostgreSQL Wire Protocol driver.

To change this information, enter C. Otherwise, press Enter to continue. :
DataDirect Technologies Product Setup is preparing the installation.
Choose a temporary directory.

Enter the full path to the temporary install directory.[/tmp]:
Checking for available space...

There is enough space.
Extracting files...

Choose a destination directory.
Enter the full path to the install directory.[/opt/Connect64forODBC60]:
Checking for available space...

There is enough space.
Extracting files...

Creating license file......


DataDirect Technologies Product Setup successfully removed all of the temporary files.


Thank you for using DataDirect Technologies products.

Installation ended successfully.

Would you like to install another product (Y/N) ? [Y]N
Thank you for using DataDirect Technologies products.

Installation ended successfully.

Após realizada a instalação das bibliotecas, iniciarei a configuração dos arquivos odbc.ini e odbinst.ini como demonstrado abaixo:

[root@Linux /]# cd /opt/Connect64forODBC60/

-- Arquivo odbc.ini
[root@Linux Connect64forODBC60]# cat odbc.ini
[ODBC Data Sources]
PostgreSQL Wire Protocol=DataDirect 6.0 PostgreSQL Wire Protocol

[ODBC]
IANAAppCodePage=4
InstallDir=/opt/Connect64forODBC60
Trace=0
TraceFile=odbctrace.out
TraceDll=/opt/Connect64forODBC60/lib/odbctrac.so

[PostgreSQL Wire Protocol]
Driver=/opt/Connect64forODBC60/lib/ddpsql24.so
Description=DataDirect 6.0 PostgreSQL Wire Protocol
ApplicationUsingThreads=1
ConnectionReset=0
ConnectionRetryCount=0
ConnectionRetryDelay=3
Database=bdlegatti
EnableDescribeParam=1
EncryptionMethod=0
ExtendedColumnMetadata=0
FailoverGranularity=0
FailoverMode=0
FailoverPreconnect=0
FetchRefCursor=1
FetchTSWTZasTimestamp=0
FetchTWFSasTime=0
HostName=10.10.10.2
LoadBalanceTimeout=0
LoadBalancing=0
LoginTimeout=15
LogonID=postgres
MaxPoolSize=100
MinPoolSize=0
Password=postgres
Pooling=0
PortNumber=5432
QueryTimeout=0
ReportCodepageConversionErrors=0
TransactionErrorBehavior=1
ValidateServerCertificate=1
XMLDescribeType=-10


-- Arquivo odbcinst.ini
[root@Linux Connect64forODBC60]# cat odbcinst.ini
[ODBC Drivers]
DataDirect 6.0 PostgreSQL Wire Protocol=Installed

[ODBC Translators]
OEM to ANSI=Installed

[Administrator]
HelpRootDirectory=/opt/Connect64forODBC60/adminhelp

[ODBC]
#This section must contain values for DSN-less connections
#if no odbc.ini file exists. If an odbc.ini file exists,
#the values from that [ODBC] section are used.

[DataDirect 6.0 PostgreSQL Wire Protocol]
Driver=/opt/Connect64forODBC60/lib/ddpsql24.so
Setup=/opt/Connect64forODBC60/lib/ddpsql24.so
APILevel=1
ConnectFunctions=YYY
DriverODBCVer=3.52
FileUsage=0
HelpRootDirectory=/opt/Connect64forODBC60/help
SQLLevel=0

O próximo passo é configurar os arquivos listener.ora e tnsnames.ora de forma a fazer referência ao serviço de banco de dados que chamarei de POSTGRESQL conforme demonstrado no exemplo abaixo:

[oracle@Linux ~]$ cd $ORACLE_HOME/network/admin

-- Arquivo listener.ora
[oracle@Linux admin]$ cat listener.ora
# listener.ora Network Configuration File: $ORACLE_HOME/network/admin/listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = BD01)
(ORACLE_HOME = /u01/app/oracle/product/11.1.0/db_1)
(SID_NAME = BD01)
)
(SID_DESC =
(SID_NAME= POSTGRESQL)
(ORACLE_HOME = /u01/app/oracle/product/11.1.0/db_1)
(PROGRAM=dg4odbc)
(ENVS=LD_LIBRARY_PATH = /opt/Connect64forODBC60/lib:
/u01/app/oracle/product/11.1.0/db_1/lib:
/lib:/usr/lib:/etc)
)
)

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = Linux)(PORT = 1521))
)
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)

Apenas como observação, caso uma versão anterior do Oracle (10g, 9i ...) esteja sendo utilizada, no trecho do código acima deverá ser substituído a linha onde está (PROGRAM=dg4odbc) para (PROGRAM=hsodbc).

-- Arquivo tnsnames.ora
[oracle@Linux admin]$ cat tnsnames.ora
# tnsnames.ora Network Configuration File: $ORACLE_HOME/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

BD01 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = Linux)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = BD01)
)
)

PG_SERVICE =
(DESCRIPTION=
(ADDRESS=(PROTOCOL=tcp)(HOST = Linux)(PORT=1521))
(CONNECT_DATA=(SID=POSTGRESQL))
(HS=OK)
)

Após definida a configuração dos arquivos listener.ora e tnsnames.ora, irei inicializar o processo listener conforme demonstrado no exemplo abaixo:

-- Inicialização do processo listener
[oracle@Linux ~]$ lsnrctl start

LSNRCTL for Linux: Version 11.1.0.7.0 - Production on 02-JUL-2009 09:10:53

Copyright (c) 1991, 2008, Oracle. All rights reserved.

Iniciando /u01/app/oracle/product/11.1.0/bd01/bin/tnslsnr: aguarde...

TNSLSNR for Linux: Version 11.1.0.7.0 - Production
O arquivo de parâmetros do sistema é $ORACLE_HOME/network/admin/listener.ora
Atendendo em: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=Linux)(PORT=1521)))
Atendendo em: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))

Estabelecendo conexão com (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=Linux)(PORT=1521)))
STATUS do LISTENER
------------------------
Apelido LISTENER
Versão TNSLSNR for Linux: Version 11.1.0.7.0 - Production
Data Inicial 02-JUL-2009 09:10:53
Funcionamento 0 dias 0 hr. 0 min. 0 seg
Nível de Análise off
Segurança ON: Local OS Authentication
SNMP OFF
Arq. Parâm. Listn. /u01/app/oracle/product/11.1.0/db_1/network/admin/listener.ora
Resumo de Atendimento...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=Linux)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
Resumo de Serviços...
O serviço "BD01" tem 1 instância(s).
Instância "BD01", status UNKNOWN, tem 1 handler(s) para este serviço...
O serviço "POSTGRESQL" tem 1 instância(s).
Instância "POSTGRESQL", status UNKNOWN, tem 1 handler(s) para este serviço...
O comando foi executado com êxito

Afim de evitar quaisquer erros de acesso às bibliotecas ODBC instaladas, ou qualquer outra surpresa, irei atualizar também arquivo de profile do usuário "oracle" com o caminho das bibliotecas ODBC instaladas anteriormente:

[oracle@Linux ~]$ cat .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH

export TEMP=/tmp
export TMPDIR=/tmp
export ORACLE_BASE=/u01/app/oracle
export ORACLE_SID=BD01
export ORACLE_HOME=$ORACLE_BASE/product/11.1.0/db_1
export PATH=$PATH:$ORACLE_HOME/bin:$ORACLE_HOME/ctx/bin:/opt/Connect64forODBC60/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/ctx/lib:$ORACLE_HOME/lib:
/opt/Connect64forODBC60/lib
export NLS_LANG="BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1"
export NLS_DATE_FORMAT=DD/MM/YYYY

Agora vem a parte em que criamos o arquivo de configuração para que seja possível a realização da conexão entre o Oracle e o banco de dados remoto (no meu caso, o PostgreSQL). Os programas dg4odbc/hsodbc geralmente procuram por um arquivo init[SID].ora localizado em $ORACLE_HOME/hs/admin. No meu caso, o SID que utilizei no arquivo listener.ora foi POSTGRESQL, portanto o arquivo a ser criado será initPOSTGRESQL.ora conforme demonstrado no trecho de código abaixo:

[oracle@Linux ~]$ cd $ORACLE_HOME/hs/admin

[oracle@Linux admin]$ cat initPOSTGRESQL.ora
# This is a sample agent init file that contains the HS parameters that are
# needed for the Database Gateway for ODBC

# HS init parameters
#
HS_FDS_CONNECT_INFO = "PostgreSQL Wire Protocol"
HS_FDS_TRACE_LEVEL = OFF
HS_LANGUAGE = "BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1"
HS_NLS_DATE_FORMAT = "DD/MM/YYYY HH24:MI:SS"
HS_OPEN_CURSORS = 200
HS_FDS_SHAREABLE_NAME = /opt/Connect64forODBC60/lib/libodbc.so
#
# ODBC specific environment variables
#
set ODBCINI=/opt/Connect64forODBC60/odbc.ini
set ODBCINSTINI=/opt/Connect64forODBC60/odbcinst.ini
set LD_LIBRARY_PATH=/opt/Connect64forODBC60/lib:
/u01/app/oracle/product/11.1.0/bd01/lib:
/lib:/usr/lib
set PATH=/opt/Connect64forODBC60/lib:/u01/app/oracle/product/11.1.0/bd01/lib:
/lib:/usr/lib
#
# Environment variables required for the non-Oracle system
#
#set [envvar]=[value]

Basicamente, os valores e parâmetros acima mais importantes são:

* set ODBCINI define o local onde está localizado o arquivo odbc.ini
* HS_FDS_CONNECT_INFO aponta para o nome da fonte de dados ODBC (DSN).
* HS_FDS_SHAREABLE_NAME aponta para a biblioteca de driver ODBC compartilhada.

Caso algum problema ocorra na tentativa de realizar a conexão com o banco de dados remoto, setando o parâmetro HS_FDS_TRACE_LEVEL com um valor maior que zero ou (ON ou DEBUG) é que nos permitirá verificar com mais detalhes o que aconteceu de errado. Para maiores informações sobre estes e outros parâmetros, acesse a página Oracle Database Gateway for ODBC User's Guide.

Por fim, após realizado todo este trabalho acima, bastará agora, para fins de teste, criar um link de banco de dados privado no meu banco de dados Oracle local que chamarei de "pgsql" para, então, realizar o teste de conexão com o banco de dados remoto. Vale a observação de que eu já criei e populei no banco de dados remoto (PostgreSQL), uma tabela de teste chamada "emp" (empregados) com a estrutura a seguir:

create table emp
(
cod smallint NOT NULL,
data_cadastro date NOT NULL,
nome varchar(80) NOT NULL,
constraint pk_emp primary key (cod)
);

-- Criando o link de banco de dados (database link)
C:\>sqlplus system/*********

SQL*Plus: Release 11.1.0.6.0 - Production on Qui Jul 02 09:25:44 2009

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

Conectado a:
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> create database link pgsql connect to "postgres" identified by "postgres"
2 using 'PG_SERVICE';

Vínculo de banco de dados criado.

-- Realizando o teste de conexão com o PostgreSQL
SQL> select * from "emp"@pgsql;

cod data_cadas nome
---------- ---------- ---------------------------------
1 25/06/2009 EDUARDO
2 28/06/2009 MARIA
3 21/06/2009 ANGELA
4 29/06/2009 LAURA


SQL> delete from "emp"@pg where "cod"=2;


1 linha deletada.

SQL> commit;

Commit concluído.

SQL> select * from "emp"@pgsql;

cod data_cadas nome
---------- ---------- ---------------------------------
1 25/06/2009 EDUARDO
3 21/06/2009 ANGELA
4 29/06/2009 LAURA

Em relação ao PostgreSQL, será necessário colocar os nomes das tabelas e colunas entre "aspas duplas", de forma a acessar os objetos do banco de dados, caso contrário, o erro abaixo será emitido:

SQL> select * from emp@pgsql;
select * from emp@pgsql
*
ERRO na linha 1:
ORA-00942: a tabela ou view não existe
[DataDirect][ODBC PostgreSQL Wire Protocol driver][PostgreSQL]ERROR: relation "EMP" does
not exist(File namespace.c;Line 221;Routine RangeVarGetRelid;)[DataDirect][ODBC
PostgreSQL Wire Protocol driver][PostgreSQL]Failed transaction.
The current transaction rolled back.
ORA-02063: precedendo 2 lines a partir de PGSQL


SQL> select owner,table_name from all_tables@pgsql where table_name='emp';

OWNER TABLE_NAME
--------------- ------------------------------
public emp


SQL> desc "emp"@pgsql
Nome Nulo? Tipo
-------------------------- --------- ----------------------------
cod NOT NULL NUMBER(5)
data_cadastro NOT NULL DATE
nome NOT NULL VARCHAR2(80)


SQL> select nome from "emp"@pgsql;
select nome from "emp"@pgsql
*
ERRO na linha 1:
ORA-00904: "NOME": identificador inválido

SQL> select "nome" from "emp"@pgsql;

nome
-------------------------------------------------
EDUARDO
ANGELA
LAURA


SQL> create view emp_remoto
2 as
3 select * from "emp"@pgsql;

View criada.

SQL> select * from emp_remoto;

cod data_cadas nome
---------- ---------- ---------------------------
1 25/06/2009 EDUARDO
3 21/06/2009 ANGELA
4 29/06/2009 LAURA


SQL> create synonym emp for "emp"@pgsql;

Sinônimo criado.

SQL> select * from emp;

cod data_cadas nome
---------- ---------- ---------------------------
1 25/06/2009 EDUARDO
3 21/06/2009 ANGELA
4 29/06/2009 LAURA


SQL> create table "emp2"@pgsql (id integer);
create table "emp2"@pgsql (id integer)
*
ERRO na linha 1:
ORA-02021: as operações DDL não são permitidas em um banco de dados remoto

Para concluir, podemos ver acima que o último comando falhou, pelo fato de não ser possível qualquer operação DDL (Data Definition Language) no banco de dados remoto.