Pesquisar este blog

sábado, 11 de setembro de 2010

Função para validar CPF em PHP

/*
     Delphi-like function para converter string para inteiro
*/
function StrToInt($value){
  return (int)$value; } /*   Função para validar CPF.   Baseado na função validaCPF (Delphi) do PoliGestor da empresa Polidados Informática Ltda. */ function validaCPF($cpf){   $CPFInvalido = array ('00000000000', '11111111111', '22222222222', '33333333333', '44444444444',                         '55555555555', '66666666666', '77777777777', '88888888888', '99999999999');   $digitado = "";   $calculado = "";   $Result = false;   try {      // verifica CPF inválido      for ($i = 0; $i < 9; $i++)        if ($cpf == $CPFInvalido[$i])          return false;      if ($cpf != ''){        $n1 = StrToInt($cpf[0]);        $n2 = StrToInt($cpf[1]);        $n3 = StrToInt($cpf[2]);        $n4 = StrToInt($cpf[3]);        $n5 = StrToInt($cpf[4]);        $n6 = StrToInt($cpf[5]);        $n7 = StrToInt($cpf[6]);        $n8 = StrToInt($cpf[7]);        $n9 = StrToInt($cpf[8]);        $d1 = $n9*2+$n8*3+$n7*4+$n6*5+$n5*6+$n4*7+$n3*8+$n2*9+$n1*10;        $d1 = 11-($d1 % 11);        if ($d1>=10)           $d1 = 0;        $d2 = $d1*2+$n9*3+$n8*4+$n7*5+$n6*6+$n5*7+$n4*8+$n3*9+$n2*10+$n1*11;        $d2 = 11-($d2 % 11);        if ($d2>=10)          $d2 = 0;        $calculado = $d1 . $d2;        $digitado = $cpf[9] . $cpf[10];        return ($calculado == $digitado) ? true : false;      }   }   catch (Exception $e) {     $Result = false;   } } ?>

sábado, 4 de setembro de 2010

Principais Visões para ORACLE

Lista das principais visões do ORACLE utilizadas no desenvolvimento PL/SQL e na administração do banco de dados. 


Fonte: http://www.techonthenet.com/oracle/sys_tables/index.php


ALL_ARGUMENTS Arguments in object accessible to the user
ALL_CATALOG All tables, views, synonyms, sequences accessible to the user
ALL_COL_COMMENTS Comments on columns of accessible tables and views
ALL_CONSTRAINTS Constraint definitions on accessible tables
ALL_CONS_COLUMNS Information about accessible columns in constraint definitions
ALL_DB_LINKS Database links accessible to the user
ALL_ERRORS Current errors on stored objects that user is allowed to create
ALL_INDEXES Descriptions of indexes on tables accessible to the user
ALL_IND_COLUMNS COLUMNs comprising INDEXes on accessible TABLES
ALL_LOBS Description of LOBs contained in tables accessible to the user
ALL_OBJECTS Objects accessible to the user
ALL_OBJECT_TABLES Description of all object tables accessible to the user
ALL_SEQUENCES Description of SEQUENCEs accessible to the user
ALL_SNAPSHOTS Snapshots the user can access
ALL_SOURCE Current source on stored objects that user is allowed to create
ALL_SYNONYMS All synonyms accessible to the user
ALL_TABLES Description of relational tables accessible to the user
ALL_TAB_COLUMNS Columns of user's tables, views and clusters
ALL_TAB_COL_STATISTICS Columns of user's tables, views and clusters
ALL_TAB_COMMENTS Comments on tables and views accessible to the user
ALL_TRIGGERS Triggers accessible to the current user
ALL_TRIGGER_COLS Column usage in user's triggers or in triggers on user's tables
ALL_TYPES Description of types accessible to the user
ALL_UPDATABLE_COLUMNS Description of all updatable columns
ALL_USERS Information about all users of the database
ALL_VIEWS Description of views accessible to the user
DATABASE_COMPATIBLE_LEVEL Database compatible parameter set via init.ora
DBA_DB_LINKS All database links in the database
DBA_ERRORS Current errors on all stored objects in the database
DBA_OBJECTS All objects in the database
DBA_ROLES All Roles which exist in the database
DBA_ROLE_PRIVS Roles granted to users and roles
DBA_SOURCE Source of all stored objects in the database
DBA_TABLESPACES Description of all tablespaces
DBA_TAB_PRIVS All grants on objects in the database
DBA_TRIGGERS All triggers in the database
DBA_TS_QUOTAS Tablespace quotas for all users
DBA_USERS Information about all users of the database
DBA_VIEWS Description of all views in the database
DICTIONARY Description of data dictionary tables and views
DICT_COLUMNS Description of columns in data dictionary tables and views
GLOBAL_NAME global database name
NLS_DATABASE_PARAMETERS Permanent NLS parameters of the database
NLS_INSTANCE_PARAMETERS NLS parameters of the instance
NLS_SESSION_PARAMETERS NLS parameters of the user session
PRODUCT_COMPONENT_VERSION version and status information for component products
ROLE_TAB_PRIVS Table privileges granted to roles
SESSION_PRIVS Privileges which the user currently has set
SESSION_ROLES Roles which the user currently has enabled.
SYSTEM_PRIVILEGE_MAP Description table for privilege type codes. Maps privilege type numbers to type names
TABLE_PRIVILEGES Grants on objects for which the user is the grantor, grantee, owner, or an enabled role or PUBLIC is the grantee
TABLE_PRIVILEGE_MAP Description table for privilege (auditing option) type codes. Maps privilege (auditing option) type numbers to type names

terça-feira, 31 de agosto de 2010

Exemplo de Midlet

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.util.Date;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;


/**
 * @author agilar
 */
public class CadastroCliente extends MIDlet {
    private Display display;
    private Form frmCadastro;
    private TextField txtNome, txtEndereco, txtFone, txtEmail;
    private DateField txtDtCadastro;
    private ChoiceGroup sexo, casado;

    private void createGUI(){
        txtNome = new TextField("Nome", "", 70, TextField.ANY);
        frmCadastro.append(txtNome);

        txtEndereco = new TextField("Endereço", "", 70, TextField.ANY);
        frmCadastro.append(txtEndereco);

        txtFone = new TextField("Fone", "", 20, TextField.PHONENUMBER);
        frmCadastro.append(txtFone);

        txtEmail = new TextField("E-mail", "", 30, TextField.EMAILADDR);
        frmCadastro.append(txtEmail);

        txtDtCadastro = new DateField("Data Cadastro", DateField.DATE);
        txtDtCadastro.setDate(new Date());
        frmCadastro.append(txtDtCadastro);
        
        sexo = new ChoiceGroup("Sexo", ChoiceGroup.EXCLUSIVE);
        sexo.append("Masculino", null);
        sexo.append("Feminino", null);
        frmCadastro.append(sexo);
        
        casado = new ChoiceGroup("Casado", ChoiceGroup.EXCLUSIVE, new String[] {"Sim", "Não"}, null);
        frmCadastro.append(casado);

    }

    public void startApp() {
        display = Display.getDisplay(this);
        frmCadastro = new Form("Cadastro de Clientes");
        createGUI();
        display.setCurrent(frmCadastro);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }
}

quinta-feira, 12 de agosto de 2010

Arvore binária simples com os três métodos de caminhamento

/*
 * Árvore binária simples com os três métodos de caminhamento: 
 *   Pré-Fixado 
 *      Central 
 *   Pós-Fixado
 * 
 * Autor: Everton Agilar 
 * Data: 12/08/2010
 * 
 */


package aula.arvore;

public class Arvore {
 int valor;
 Arvore esq;
 Arvore dir;

 public Arvore(int valor){
  this.valor = valor;
  this.esq = null;
  this.dir = null;
 }
 
 public void add(Arvore no){
  if (no.valor < this.valor){
   if (esq == null){
    esq = no;
   }else {
    esq.add(no);
   }
  }
  else {
   if (no.valor > this.valor){
    if (dir == null){
     dir = no;
    }
    else {
     dir.add(no);
    }
   }
  }
 }
 
 public void caminhamentoPreFixado(){
  System.out.printf("%d%n", valor);  // a raiz é acessada por primeiro
  if (esq != null) 
   esq.caminhamentoPreFixado();
  if (dir != null) 
   dir.caminhamentoPreFixado();
 }
 
 public void caminhamentoCentral(){
  if (esq != null) 
   esq.caminhamentoCentral();
  System.out.printf("%d%n", valor);  // a raiz é acessada no meio   
  if (dir != null) 
   dir.caminhamentoCentral();
 }

 public void caminhamentoPosFixado(){
  if (esq != null) 
   esq.caminhamentoPosFixado();
  if (dir != null) 
   dir.caminhamentoPosFixado();
  System.out.printf("%d%n", valor);  // a raiz é a última acessada
 }

 public static void main(String[] args) {
  System.out.println("Demonstração de formas de caminhamento em árvore binária\n");
  
  Arvore arv = new Arvore(10);
  arv.add(new Arvore(8));
  arv.add(new Arvore(12));
  arv.add(new Arvore(4));
  arv.add(new Arvore(14));
  arv.add(new Arvore(2));
  arv.add(new Arvore(1));
  
  System.out.println("Caminhamento Pré-Fixado:");
  arv.caminhamentoPreFixado();
  
  System.out.println("\nCaminhamento In-Fixado ou Central:");
  arv.caminhamentoCentral();

  System.out.println("\nCaminhamento Pós-Fixado:");
  arv.caminhamentoPosFixado();
 }
}

quarta-feira, 11 de agosto de 2010

Regras Firewall Pessoal - iptables

#/bin/bash
# Regras de Firewall
# Autor: Everton Agilar
# Última alteração: 11/08/2010

# Limpa todas as tabelas
iptables -t filter -F INPUT
iptables -t filter -F OUTPUT
iptables -t filter -F FORWARD

# Define política padrão (DROP)
iptables -t filter -P INPUT DROP
iptables -t filter -P OUTPUT DROP
iptables -t filter -P FORWARD DROP

# Permite pacotes de loopback
iptables -t filter -A INPUT -i lo -j ACCEPT

# Permite pacotes de entrada gerados dentro da rede
iptables -t filter -A INPUT -i wlan0 -p tcp -m state --state related,established -j ACCEPT
iptables -t filter -A INPUT -i wlan0 -p udp -m state --state related,established -j ACCEPT
iptables -t filter -A INPUT -i wlan0 -p icmp -m state --state related,established -j ACCEPT
iptables -t filter -A INPUT -i wlan0 -p tcp --sport 20:21 -j ACCEPT
iptables -t filter -A INPUT -i wlan0 -p tcp --sport 1863 -j ACCEPT
iptables -t filter -A INPUT -i wlan0 -p tcp --sport 443 -j ACCEPT


# Permite pacotes de saída para icmp,www,domain,ftp,msn,https
iptables -t filter -A OUTPUT -o wlan0 -p icmp -j ACCEPT
iptables -t filter -A OUTPUT -o wlan0 -p tcp --dport 80 -j ACCEPT
iptables -t filter -A OUTPUT -o wlan0 -p udp --dport 53 -j ACCEPT
iptables -t filter -A OUTPUT -o wlan0 -p tcp --dport 20:21 -j ACCEPT
iptables -t filter -A OUTPUT -o wlan0 -p tcp --dport 1863 -j ACCEPT
iptables -t filter -A OUTPUT -o wlan0 -p tcp --dport 443 -j ACCEPT

segunda-feira, 26 de julho de 2010

Exemplo de Applet e os eventos de ativação

package aula.applet;

import java.applet.*;
import java.awt.Graphics;

public class HelloWorldApplet extends Applet implements Runnable {
    Thread anime = null;
    
    public void init(){
        System.out.println("Inicializando...");
        
    }

    public void start(){
        System.out.println("Startando...");
        if (anime == null){
            System.out.println("Cria animador...");
            anime = new Thread(this);
            anime.start();
        };    
    }
    
    public void stop(){
        System.out.println("Parando...");
        anime.interrupt();
        anime = null;
    }
    
    
    public void destroy(){
        System.out.println("Morrendo...");
    }
    
    public void paint(Graphics g){
        int x = new java.util.Random().nextInt(100);
        int y = new java.util.Random().nextInt(100);
        g.drawString("Ola Mundo", x, y);
        System.out.println("pintando...");
    }

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){ 

            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
            }

            if (isActive())
                repaint();
            else {
                break;
            }    
        }
        
        System.out.println("Finalizando animador...");
        return;
    }

}

sexta-feira, 23 de julho de 2010

Comandos diversos

1 - Para listar somente diretórios
 
  ls -l | grep "^d"

   Sinopse: ^ significa primeira letra, que nesse caso é d

2 - Para listar somente arquivos executáveis

  ls -l | grep "^-..x"

  Sinopse: ^ significa lista primeira letra, nesse caso - significa arquivo comum, pula
     dois caracteres de permissão (rw) e encontra o x se o arquivo estiver com permissão de
     executável

3 - Como listar arquivos somente em uma linha
 
  ls -1

  Sinopse: -1 significa 1 linha

4 - Como listar arquivos pelo mais recente (o que foi modificado por último)

  ls -1t

  Sinopse: Use -1 para listar apenas uma coluna e -t para listar pela data de modificação


5 - Como alterar a data/hora

  date 092713202006
  clock -w

  Sinopse: O comando date serve para alterar a data/hora.
           Foi passado no formato mêsdiahoraminutoano.
           Logo em seguinda foi usado o comando clock -w para gravar a data/hora na bios.

6 - Copiando usando tar
    Use o comando tar.

    $ (cd /origem && tar cf - . ) | (cd /destino && tar xvfp -)

    Preste atenção nos parêntesis, eles fazem com que a operação seja executada em uma subshell,
    não afetando a shell que vc está usando.

7 - Como saber o tamanho de um diretório em MB?
     du -sm nome_do_diretório

8 - Como se tornar o root sem efetuas logou

   su root ou su -

   Sinopse: Digite o comando e após informe a senha


RPM
-------------------------------------------------

8 - Saber se um arquivo pertence a um pacote

   rpm -qf nomearquivo

9 - Saber os arquivos de um pacote

  rpm -ql koules-1.2-2.i386.rpm

10 - Obter informações sobre um pacote

  rpm -qi coreutils


11 - Ver uma lista de todos os pacotes instalados

  rpm -qa

12 - Como instalar, atualizar e remover pacotes
 
  rpm -ivh nompacote.rpm
  rpm -U nomepacote.rpm
  rpm -e nomepacote

13 - Como testar se um pacote pode ser instalado corretamente

  rpm -i --test nomepacote.rpm

14 - Reinstalar um pacote

  rpm -U --replacedpkgs nomepacote.rpm


Redes
---------------------------------------------------

1 - Como saber as portas TCP abertas

  netstat -an | grep LISTEN

 


diff e patch
-------------------------------------------------------------------

1 - Como comparar dois arquivos e gerar um arquivo das diferenças

   diff -a arq1 arq2 > dif.txt

   Sinopse: A opção -a foi usada para ser modo texto


G++
-------------------------------------------------------------------

1 - Compilar um programa usando uma bibliteca externa

  g++ -o app1.exe -Wl,--add-stdcall-alias,L.,-msgdll app1.c


2 - Compilar sem usar a rtl cygwin1.dll

  Incluir a opção -mno-cygwin no g++


--------------------------------------------------------------------

1 - Como redirecionar dispositivos no Windows

   Ver comando MODE

  Ex.: MODE LPT1:=COM1:    
       Este comando redireciona tudo que vai para LPT1 para COM1




    

terça-feira, 6 de julho de 2010

Criando objetos com javascript


Exemplo de código em javascript para criar e instânciar objetos

        // Classe Pessoa

    function pessoa(nome, idade, endereco){


      this.nome = nome;
      this.idade = idade;
      this.endereco = endereco;
      function gritar(){
        if (this.idade >= 30)
     document.write("aaaaaaaaaaaaaaaa! ");
        else
  document.write("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa! ");
      } 
   
      this.gritar = gritar;
    }

    // Classe Calc 
    function Calc(){
   
      function add(x, y){
        return x + y;
      } 
      function subtract(x, y){
        return x - y;
      } 
      this.add = add;
      this.subtract = subtract; 
    }

    // instância a calculadora e faz cálculos matemáticos
    var c = new Calc();
    document.write("2+2=" + c.add(2, 2) + " ");
    document.write("2-2=" + c.subtract(2, 2) + " ");

    // instância pessoas e imprime seus nomes
    var joao = new pessoa("Joao", 30, "rua X");
    document.write(" My name is " + joao.nome + " e tenho " + joao.idade + " anos ");
    joao.gritar();
    // instância Maria e imprime seu nome
    var maria = new pessoa("Maria", 25, "rua Y");
    document.write(" My name is " + maria.nome + " e tenho " + maria.idade + " anos ");
    maria.gritar();

 

sábado, 26 de junho de 2010

Base de fatos e regras família em Prolog

homem(everton).
homem(joao).
homem(marcos).
homem(jader).
homem(henrique).
homem(jonas).
homem(leo).
homem(rodrigo).

mulher(thaise).
mulher(mara).
mulher(carol).
mulher(melina).

marido(everton, thaise).
marido(joao, carol).

esposa(mara, jader).

filho(henrique, everton).
filho(jonas, marcos).
filho(leo, melina).
filho(rodrigo, mara).

casado_com(X, Y):- homem(X),
               mulher(Y),
               marido(X, Y), !.
casado_com(X, Y):- homem(X),
               mulher(Y),
               esposa(Y, X), !.           
casado_com(X, Y):- mulher(X),
               homem(Y),
               esposa(X, Y), !.
casado_com(X, Y):- mulher(X),
               homem(Y),
               marido(Y, X), !.           

tem_filho(X):- homem(X),
           filho(Y, X), !.    

tem_filho(X):- mulher(X),
           filho(Y, X), !.    

tem_filho(X):- casado_com(X, Y),   
           filho(K, Y), !.   

sábado, 19 de junho de 2010

Questões sobre Gerenciamento de Projetos

1 - O QUE É UM PROJETO
   
    É um esforço progressivo e temporário para criar um produto ou serviço único.

2 - O QUE É GERENCIAMENTO DE PROJETOS

    É a aplicação de ferramentas, técnicas, conhecimentos e habilidades de gerência de projetos
    a fim de atender a seus requisitos.

3 - QUAIS OS PROCESSOS DO GERENCIAMENTO DE PROJETOS

    São cinco: iniciação, planejamento, execução, controle e encerramento

4 - QUAIS AS ÁREAS DE CONHECIMENTO DO GERENCIAMENTO DO PROJETO

    São nove áreas:

    * Gerenciamento de Integração - processos necessários para gerenciar e coordenar
      os diversos grupos do gerenciamento de projetos;
        Palavra chaves: Termo de abertura, plano de gerenciamento de projeto, 
                    controle e monitoramento.

    * Gerenciamento do Escopo - processos envolvidos na verificação de que o projeto
      inclui todo o trabalho e somente o necessário para concluir com sucesso.
        Palavras chaves: coletar requisitos, definir escopo, criar EAP, verificar e controlar escopo.

    * Gerenciamento do Tempo - processos necessários para assegurar o termino
      do projeto no tempo definido.
        Palavras chaves: Definir e sequenciar atividades, estimar recursos e duração das atividades,
                 desenvolver e controlar cronograma.

    * Gerenciamento de Custos - processos envolvidos no planejamento, estimativa, orçamentação
      e controle de custos de modo que o projeto termine dentro do orçamento aprovado.
        Palavras chaves: estimar custo, determinar orçamento, controlar custo.

    * Gerenciamento da Qualidade - processos envolvidos na garantia de que o projeto 
      irá satisfazer os objetivos para os quais foi realizado.
        Palavras chaves: Planejar qualidade, realizar garantia e controle da qualidade.

    * Gerenciamento de Recursos Humanos - processos que organiza e gerencia a equipe do projeto.
        Palavras chaves: desenvolver plano de RH, mobilizar equipe, desenvolver e gerenciar equipe.

    * Gerenciamento das comunicações - processos relativos a geração e disseminação da informação
      do projeto as pessoas interessadas.
        Palavras chaves: Identificar interessados, planejar comunicação, reportar desempenho, 
                 gerenciar expectativas.

    * Gerenciamento de Riscos - processos para realizar o gerenciamento dos riscos do projeto.
        Palavras chaves: planejar e identificar riscos, fazer análise 
                 qualitativa e quantitativa dos riscos, monitorar e controlar riscos.

    * Gerenciamento de Aquisições - processos para compra e aquisição de produtos, serviços, 
          resultados e contratos.
        Palavras chaves: planejar e realizar aquisições, administrar e encerrar aquisições.


5 - QUAIS AS HABILIDADES DE UM GERENTE DE PROJETO

    São cinco:
        Habilidades organizacionais - organização e planejamento
        Habilidades para finanças e contabilidade - estimar custos e desenvolver orçamentos
        Habilidades de liderar - direcionamento e envolvimento da equipe
        Habilidades de negociar e influênciar - dialogar e obter consenso
        Habilidades de comunicação - comunicação clara e objetiva


6 - DEFINA O CONTEXTO DO GERENCIAMENTO
   
    São cinco:
        Portfólio - carteira de negócios (conj. de programas e/ou projetos)
        Programas - são conj. de projetos administrados juntos. Ex.: Programa Educacional
        Projeto - é um esforço progressivo e temporário para criar um produto ou serviço único.
        Tarefa - elemento de trabalho com duração, custo e recurso definido.
        Pacote de trabalho - menor unidade de trabalho possível de ser planejada, controlada e executada.

7 - O QUE É UM PMO

    Escritório de projetos. Orienta e fornece suporte aos gerentes de projeto.


8 - PORQUE ESTUDAR GERENCIAMENTO DE PROJETOS

    Porque falhas em projetos em suas definições de tempo, prazo e custo são elevadas 
    quando não se aplicam técnicas consistentes de gerenciamento de projetos. Estudos
    mostram que o uso de gerenciamento de projetos aumenta as chances do projeto concluir no    prazo e no orçamento estipulado.


9 - PARA GESTÃO DE UM PROJETO, QUAIS OS CICLOS DE VIDA QUE PRECISAMOS CONSIDERAR

    São três:   
    Ciclo de vida do produto - permanência do produto no mercado
        Palavras chaves: idealização, concepção, construção, uso e descarte.

    Ciclo de vida do projeto - descreve o que deve ser feito para completar o projeto (definem inicio, meio e fim)
        Palavras chaves: Termo de abertura, plano do projeto, declaração do escopo, progresso, aceitação, aprovação, entrega

    Cicle de vida da GP - descreve o que deve ser feito para gerenciar o projeto (grupos de processos)
        Palavras chaves: iniciação, planejamento, execução, controle, encerramento.


10 - CARACTERÍSTICAS DO CICLO DE VIDA DE UM PROJETO DE SOFTWARE

    - fases geralmente sequenciadas
    - custos e uso do pessoal baixos no início, aumentam durante a execução e cai rapidamente no final
    - no início do projeto, nível de incerteza e riscos maiores e caem no final
    - capacidade dos stakeholders em influênciar no projeto são maiores no início
    - mudanças tem maior impacto a medida que a execução do projeto avança


11 - QUEM SÃO OS STAKEHOLDERS

    São os interessados no projeto, ou seja, pessoas ou organizações que influênciam
    ou são influênciados, positivamente ou negativamente, pelos resultados de um projeto.


12 - QUEM SÃO OS PRINCIPAIS STAKEHOLDERS

    Gerente do projeto, cliente, usuário, membros da equipe, patrocinador, fornecedores, PMOs.
   

13 - QUAIS OS FATORES DE SUCESSO DE UM PROJETO

    - seleção dos processos adequados
    - uso de abordagem definida
    - atendimento aos requisitos do cliente
    - balançeamento de interesses entre os vários interessados


14 - FATORES QUE DETERMINAM A NECESSIDADE OU NÃO DE GERENCIAMENTO DE PROJETO

    - Tamanho do empreendimento
    - Importãncia do empreendimento
    - Reputação da organização
    - Compartilhamento de recursos
    - Não familiaridade - empreendimento completamente novo


15 - TIPOS DE PROCESSOS

    - Orientado ao Projeto - Iniciação, planejamento, execução, controle, monitoramento, encerramento.
    - Orientado ao Produto - Especificação e criação do produto do projeto.

quarta-feira, 12 de maio de 2010

Formatando datas no ORACLE para importar scripts do IBExpert

Ao executar scripts com inserts ou updates gerados pelo IBExpert do banco de dados Firebird no ORACLE, precisamos configurar corretamente a sessão para tratar o formato de data corretamente, caso contrário, ocorrerá erros na execução dos scripts.

Dois parâmetros no ORACLE devem ser configurados:
  • nls_date_format
  • nls_timestamp_format

A máscara default utilizado pelo IBExpert para formatar as datas é 'YYYY-MM-DD' para o tipo DATE e 'YYYY-MM-DD HH:MI:SS' para o tipo TIMESTAMP. No ORACLE pode-se executar os seguintes comandos para configurar as máscaras:

Para o tipo DATE:

ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD';

Para o tipo TIMESTAMP:

ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD HH24:MI:SS';

Seguindo estes procedimentos, consegue-se importar registros que contém campos de data e timestamp de forma simples.

Uma observação é quanto ao tipo TIME do Firebird, inexistente no ORACLE. Para este tipo de dados pode-se armazenar como VARCHAR2(8).

Até o próximo post!

sexta-feira, 7 de maio de 2010

Oracle Pipelined Table Functions

Material sobre como implementar procedures selecionável, um recurso do Firebird em ORACLE através de funções pipelined table functions:

http://www.akadia.com/services/ora_pipe_functions.html
http://mail.firebase.com.br/pipermail/lista_firebase.com.br/2008-February/049950.html

quinta-feira, 6 de maio de 2010

Ativar teclas de atalho para o sqlplus no Linux

Muitos sabem que ao trabalhar com sqlplus no Linux, não temos a opção de utilizar teclas de atalho para navegar entre os comandos digitados.

Recentemente descobri uma software que pode ser instalado, que permite ativar as teclas de atalho para o sqlplus. Para instalar digite o seguinte comando no prompt de comando.

sudo apt-get install rlwrap

Após instalado, precisamos invocar o sqlplus desta forma:

rlwrap sqlplus user/senha

Com isso, teremos um histórico de comandos da mesma forma que em ambiente Windows.

quarta-feira, 5 de maio de 2010

Usando sudo para executar comandos como root no Linux

No Linux, quando você precisar executar um comando que exige permissões de root, pode-se usar o comando sudo. Ao usar o comando sudo, o Linux vai pedir a senha do root e executar o comando.

Para que qualquer usuário possa utiliza-lo é necessário informar ao Linux que o usuário pertence ao grupo sudo. Podemos fazer isso através do usuário root da seguinte forma:
usermod -G sudo agilar

O comando acima adiciona o usuário agilar no grupo sudo. A partir dai, pode-se utilizar sudo toda vez que precisarmos executar um comando com permissões de root para o usuário agilar.

domingo, 7 de março de 2010

Windows Seven com Delphi 7

1 - Ao instalar o Delphi 7 diversos arquivos BPL são instalados na pasta C:\Windows\SysWOW64.

A pasta SysWOW64 contém as DLLs de 32 bits. Já a pasta C:\Windows\System32 contém arquivos DLLs de 64 bits. Quando um programa necessita de uma DLL de 32 bits, automaticamente é redirecionado para a pasta C:\Windows\SysWOW64. Pode parecer estranho, mas é assim que o Windows funciona. A pasta C:\Windows\System32 ainda continua existindo, mas seu conteúdo é de 64 bits!

2 - Como substituir o QuickReport do Delphi 7 por outra versão.

Antes de instalar a bpl qrpt70.bpl deve-se primeiro excluir o arquivo c:\windows\SysWOW64\qrpt70.dll e reabrir o Delphi.

3 - Mostrar arquivos e pastas ocultas do Windows

No Windows Explorer, clique no botão Organizar, Opções de pasta e pesquisa. Na janela "Opções de Pasta" possui diversos opções para mostrar pastas e arquivos ocultos.

4 - Como acessar a pasta "Arquivos de Programas" no menu Executar.

Digite "program files".

Obs.: Se você digitar "arquivos de programas" como no Windows XP, aparece a mensagem acesso negado.

segunda-feira, 25 de janeiro de 2010

Usando condições ANY ou SOME

Dado o esquema a seguir:
SQL> desc valores
Nome                Nulo?    Tipo
------------------- -------- ---------
V                            NUMBER(38)

SQL> select * from valores;

V
----------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

18 linhas selecionadas.

SQL>


Exemplos de Condições SQL
EXEMPLO 1
SQL> select * from valores
  2  where v = some(1, 3, 10);

         V
----------
         1
         3
        10

3 linhas selecionadas.

EXEMPLO 2

  1  select * from valores
  2* where v > some(3, 10, 11)
SQL> /

         V
----------
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18

15 linhas selecionadas.

EXEMPLO 3

  1  select * from valores
  2* where v > all(3, 10, 11)
SQL> /

         V
----------
        12
        13
        14
        15
        16
        17
        18

7 linhas selecionadas.



sexta-feira, 22 de janeiro de 2010

Desafio SQL: Alias em SQL

Ola, vou iniciar este post com uma questão para resolvermos.
Considere a seguinte questão:
SQL>
1 select id "Produto ID", sum(preco) "Preco"
2 from estoque
3 where Preco > 50
4 group by "Produto ID"
5* order by sum(preco)

Qual linha causa um erro ?


Analisando a questão, pode-se perceber várias partes que podem dar a entender estar errado. Olhando o SQL, vemos que os campos utilizam-se de alíases, e o campo preco tem um alias semelhante ao nome do campo: "Preco". Isso pode passar despercebido ou confundir, fazendo alguém pensar que a linha 3 está errado, pois o alias está sendo referênciado.

Então a primeira regra que temos que saber: na cláusula WHERE, devemos referênciar o campo e não o alias, senão um erro ocorre.

Na consulta acima, agora não resta dúvida, estamos acessando o campo preco, pois SQL é case insensitive, não importa como escrevemos: preco, Preco, PRECO, PReco, etc. Com isso, podemos concluir também que, se fizermos uma prova para certificação em SQL e aparecer um alias na cláusula WHERE, é certo que há um erro ai.

Para não restar dúvida, segue um SQL de exemplo:

SQL> select codigo "Codigo" from estoque
  2  where "Codigo" <> 0;
where "Codigo" <> 0
      *
ERRO na linha 2:
ORA-00904: "Codigo": identificador invßlido

Seguindo o exercício da questão, alguns podem dizer que a linha 4 está errado. E de fato, está. A mesma regra do WHERE vale no GROUP BY, na cláusula WHERE e GROUP BY, devemos referênciar o campo e não o alias, senão um erro ocorre.

Segue dois exemplos, o primeiro SQL referenciou um alias no group by e o segundo o próprio campo:

EXEMPLO 1:
SQL>
  1  select codigo as num
  2  from estoque
  3* group by num
SQL> /
group by num
         *
ERRO na linha 3:
ORA-00904: "NUM": identificador invßlido

EXEMPLO 2:
SQL>
  1  select codigo as num
  2  from estoque
  3* group by codigo
SQL> /

NUM
-------------
1255
124
126
125

Bom, sabemos que o erro na questão está na linha 4, onde é referênciado o alias "Produto ID". Mas quero mostrar outra regra, que nesta questão não se aplica, mas que devemos saber mesmo assim:

Na cláusula ORDER BY, podemos acessar tanto o campo, como o alias ou um número que indica a posição do campo na cláusula SELECT.

Isso pode confundir muitos, pois porque não podemos acessar o alias no WHERE e no GROUP BY mas podemos acessar no ORDER BY. E ainda, podemos acessar o campo pela sua posição na lista de campos do SELECT.

Isso mesmo, segue vários exemplos que mostram isso na prática:

EXEMPLO 1:
SQL>
  1  select codigo as num
  2  from estoque
  3* order by codigo
SQL> /

NUM
-------------
124
124
124
125
125
125
1255
126

8 linhas selecionadas.

EXEMPLO 2:
SQL>
  1  select codigo as num
  2  from estoque
  3* order by num
SQL> /

NUM
-------------
124
124
124
125
125
125
1255
126

8 linhas selecionadas.

EXEMPLO 3:
SQL>
  1  select codigo as num
  2  from estoque
  3* order by 1
SQL> /

NUM
-------------
124
124
124
125
125
125
1255
126

8 linhas selecionadas.

SQL>

Então como vemos, o ORDER BY é a cláusula mais flexivel de todas, podemos acessar os campos da consulta de qualquer maneira e vai funcionar. A cláusula ORDER BY tem como finalidade ordenar as tuplas de uma relação, portanto, ela é a última etapa executada e consegue ver a relação pronta, ao contrário das demais cláusulas.


Mais uma vez, espero ter ajudado a comunidade de desenvolvedores, sempre tive muita dúvida a respeito disso, até que resolvi escrever este post e testar de diversas maneiras, vários SQL e terminar de uma vez por todas, estas dúvidas sobre o uso do alias em consultas SQL.


Até o próximo post!

Números randômicos em ORACLE

Neste post, vamos ver uma dica para obter números aleatórios. A ORACLE disponibiliza a package DBMS_RANDOM. Vamos consultar as funções disponíveis usando o seguinte comando no SQL-Plus:

SQL> desc dbms_random
PROCEDURE INITIALIZE
 Nome do Argumento                  Tipo                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 VAL                            BINARY_INTEGER          IN
FUNCTION NORMAL RETURNS NUMBER
FUNCTION RANDOM RETURNS BINARY_INTEGER
PROCEDURE SEED
 Nome do Argumento                  Tipo                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 VAL                            BINARY_INTEGER          IN
PROCEDURE SEED
 Nome do Argumento                  Tipo                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 VAL                            VARCHAR2                IN
FUNCTION STRING RETURNS VARCHAR2
 Nome do Argumento                  Tipo                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OPT                            CHAR                    IN
 LEN                            NUMBER                  IN
PROCEDURE TERMINATE
FUNCTION VALUE RETURNS NUMBER
FUNCTION VALUE RETURNS NUMBER
 Nome do Argumento                  Tipo                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 LOW                            NUMBER                  IN
 HIGH                           NUMBER                  IN

Como se pode ver, existem diversas funções para gerar números aleatórios. No exemplo a seguir, vou demonstrar como gerar números aleatórios inteiros entre 1 e 100:

SQL> select trunc(dbms_random.value(1, 100)) num  from dual;

       NUM
----------
        89

SQL> select trunc(dbms_random.value(1, 100)) num  from dual;

       NUM
----------
         9

SQL> select trunc(dbms_random.value(1, 100)) num  from dual;

       NUM
----------
        39

No exemplo, três instruções SQL consecutivas exibem como a função DBMS_RANDOM.VALUE funciona. Ela retorna um valor NUMBER. Como sabemos o tipo NUMBER pode armazenar tanto números inteiros como números ponto flutuante. Para retornar um inteiro, foi utilizado a função TRUNC. A função utilizada permite passar o range da randomização, o que pode ser muito útil.


É isso ai, espero ter ajudado a quem procura uma maneira de gerar números randômicos em ORACLE.
Até mais!

SQL - Verificar duplicidade de código de barra

Ola, seguindo o espírito de "Ask Tom", vou postar alguns truques usando SQL que podem ser muito úteis para os desenvolvedores. Sem perdemos tempo, vamos-la!

Últimamente alguns clientes estão reclamando que há mais de 1 produto com o mesmo código. O Analista, ao verificar o banco de dados, descobre que não existe uma chave única no campo do código de barra. Como podemos saber quais são os produtos que possuem o código duplicado ?

Resposta: Existem várias maneiras de construir um SQL para verificar duplicidade de valor em uma coluna. Uma das maneiras que vou ensinar é usar subquery e a cláusula group by como segue:

select id, codigo, nome
from estoque
where codigo in (select codigo
            from estoque
            group by codigo
            having count(codigo) > 1)


Analisando a consulta, verifique que estamos buscando todos os produtos da tabela estoque que tem o código na sub-consulta. A sub-consulta, por sua vez, lista os códigos da tabela estoque que possuem duplicidade.

Para entender a sub-consulta, é simples, baste dizer que "select codigo from estoque group by codigo" lista todos os códigos sem duplicidade e "having count(codigo) > 1" filtra somente os códigos que existe em mais de 1 tupla na tabela estoque.

Ainda me lembro há 5 anos atraz de um programa em Clipper para fazer isso. Apenas um comando SQL fez todo trabalho!

É isso ai, até o próximo post, com mais dicas!

quarta-feira, 20 de janeiro de 2010

Vou ter que ensinar o Firebird a fazer aritmética

Bem, vou iniciar este post depois de muita depuração. Em nosso ERP PoliGestor, realizamos um cálculo para encontrar o lucro bruto para os produtos cadastrados. Acontece que no Delphi a expressão resulta em um valor diferente que a mesma expressão computada via SQL.

Eis a expressão no código fonte:
Lucro:= TruncFloat((ADO_EstoquePRC_VENDA.AsCurrency -                                                           ADO_EstoquePRC_CUSTO.AsCurrency) / ADO_EstoquePRC_CUSTO.AsCurrency * 100, 9);

A mesma expressão em um formato mais legível é:
vLucro:= trunc(((prc_venda - prc_custo) / prc_custo) * 100, 9);

  Resultado no Delphi usando o tipo REAL para vLucro: 80,375180375

Esta expressão é truncada para 9 casas para ter uma precisão boa em nosso sistema. Então qual é o problema ? Se executarmos esta mesma expressão no servidor RDBMS Firebird, o resultado é 80.370000000 em uma stored procedure (codificando vLucro com tipo NUMERIC(12, 9)) ou 80.37 quando executado via SQL.

A instrução SQL é a seguinte:
select ((200 - 110.88)/110.88)*100 from rdb$database

Resultado: 80.37
Versão do Firebird: 2.5

SOLUÇÂO

A solução encontrada foi ensinar o Firebird a fazer a aritmética, promovendo um número da expressão, como segue:

select ((cast(200 as numeric(12, 9)) -  110.88)/110.88)*100 from rdb$database

Resultado: 80,375180375


Esta solução funcionou mas me deixou preocupado com os demais cálculos realizados pelo sistema. Sabemos que o Firebird realiza cálculos com precisão diferente de outros bancos e de outras linguagens de programação e isso pode acarretar problemas em arredondamentos e cálculos de porcentagens.

CONCLUSÂO

Sabe-se que cada RDBMS usa um esquema diferente para promover seus tipos. A conversão implícita (automática), nem sempre é o que queremos. No ORACLE, por exemplo, é recomendado usar to_number para fazer as conversões. Depois de fazer a promoção de uma parte da expressão para NUMERIC(12, 9) o cálculo ficou correto porque foi informado ao Firebird que os cálculos devem ser entre números com tipos NUMERIC(12, 9).

É isso ai, até mais!

terça-feira, 19 de janeiro de 2010

Dicas e Truques PL/SQL - Parte 3

Function ASCII - retorna o código ASCII do caracter.

SQL> select ascii('A') from dual;

ASCII('A')
----------
        65


Function CHR - Retorna um caracter quando recebe seu valor ASCII.

SQL> select chr(65) from dual;

C
-
A


Function CONCAT - Concatena duas strings.

SQL> select concat('ORACLE ', 'PL/SQL') texto from dual;

TEXTO
-------------
ORACLE PL/SQL


Function INITCAP - Primeiro caracter de cada palavra de uma string em maiúsculo.

SQL> select initcap('everton de vargas agilar') my_name from dual;

MY_NAME
------------------------
Everton De Vargas Agilar


Function INSTR - Retorna a localização de uma string dentro de outra string.

EXEMPLO 1

SQL> select instr('ABCDEFGHIJLMNOPQRSTUVXZabcdefghijlmnopqrstuvxzABCDEFGHIJKLMNOPQRSTUVXZ', 'DEF') pos from dual;

       POS
----------
         4


EXEMPLO 2

SQL> select instr('ABCDEFGHIJLMNOPQRSTUVXZabcdefghijlmnopqrstuvxzABCDEFGHIJKLMNOPQRSTUVXZ', 'DEF', 5) pos from dual;

       POS
----------
        50

EXEMPLO 3


SQL> 
  1  create or replace procedure print_values(
  2    pValues in varchar2,
  3    pDesconsiderar in varchar2)
  4  is
  5    v char;
  6  begin
  7    for i in 1..length(pValues) loop
  8      v:= substr(pValues, i, 1);
  9      if instr(pDesconsiderar, v) = 0 then
 10        dbms_output.put_line(v);
 11      end if;
 12    end loop;
 13* end;
SQL> /

Procedimento criado.

SQL> execute print_values('12345', '4');
1
2
3
5

Procedimento PL/SQL concluÝdo com sucesso.


Function LPAD - Preenche uma string no lado esquerdo de caracteres com qualquer string especificada.

SQL> select lpad('789123', 13) codigo from dual;

CODIGO
-------------
       789123

SQL> select lpad('789123', 13, '0') codigo from dual;

CODIGO
-------------
0000000789123

SQL> select lpad('789123', 13, '01') codigo from dual;

CODIGO
-------------
0101010789123

SQL> select lpad('789123', 13, '*') codigo from dual;

CODIGO
-------------
*******789123



Function RPAD - Preenche uma string no lado direito de caracteres com qualquer string especificada.

SQL> select rpad('789123', 13) codigo from dual;

CODIGO
-------------
789123

SQL> select rpad('789123', 13, '0') codigo from dual;

CODIGO
-------------
7891230000000

SQL> select rpad('789123', 13, '01') codigo from dual;

CODIGO
-------------
7891230101010

SQL> select rpad('789123', 13, '-') codigo from dual;

CODIGO
-------------
789123-------

SQL> select rpad('789123', 13, '*') codigo from dual;

CODIGO
-------------
789123*******


Function LENGTH - Retorna o comprimento de uma string.

SQL> select length('ORACLE 10g') text from dual;

      TEXT
----------
        10


Function REPLACE - Substitui toda ocorrência de uma string por outra string.

SQL> select replace('ORACLE 10g', '10g', '11g') text from dual;

TEXT
----------
ORACLE 11g


Function TRANSLATE - Igual a REPLACE mas opera a nível de caracter. Veja um exemplo com REPLACE e TRANSLATE.

-- Converte ad para x. Somente uma ocorrência a ser encontrada.
SQL> select replace('abcdabada', 'ad', 'x') from dual;

REPLACE(
--------
abcdabxa

-- Converte o caracter "a" ou o caracter "d" para x. Várias ocorrências são encontradas.
SQL> select translate('abcdabada', 'ad', 'x') from dual;

TRANSLA
-------
xbcxbxx


Function SOUNDEX - Retorna a representação fonética de uma string. Útil nas palavras que têm ortografia diferente mas com som parecido.

SQL> 
  1  select * from (
  2      select 'Agilar' as nome from dual
  3      union
  4      select 'Aguilar' as nome from dual
  5      union
  6      select 'Stefanello' as nome from dual
  7      union
  8      select 'Agilare' as nome from dual
  9  )
 10* where soundex(nome) = soundex('Agilar')
SQL> /

NOME
----------
Agilar
Agilare
Aguilar


Function SUBSTR - Retorna uma parte de uma string de dentro de uma string.

SQL> select substr('ORACLE 11g', 8, 3) from dual;

SUB
---
11g


Function TRIM, LTRIM, RTRIM - Remove espaços de uma string em ambos lados, a esquerda ou a direita.

SQL> select trim('      8976       ') texto from dual;

TEXT
----
8976

SQL> select ltrim('      8976       ') text from dual;

TEXT
-----------
8976

SQL> select rtrim('      8976       ') text from dual;

TEXT
----------
      8976


Function UPPER, LOWER - Converte a string para maiúsculo ou minúsculo.


SQL> select upper('oracle') texto from dual;

TEXTO
------
ORACLE

SQL> select lower('Oracle') texto from dual;

TEXTO
------
oracle



Function ABS - Retorna o valor absoluto de um número.

SQL> select abs(-11) from dual;

  ABS(-11)
----------
        11

SQL> select abs(11) from dual;

   ABS(11)
----------
        11


Function FLOOR - Retorna o maior integer menor ou igual a um valor decimal.
Function CEIL - Retorna o menor integer maior ou igual a um valor decimal.

SQL> select floor(12345.56) from  dual;

FLOOR(12345.56)
---------------
          12345

SQL> select ceil(12345.56) from  dual;

CEIL(12345.56)
--------------
         12346


Function ROUND - Retorna um número arredondado para n casas.

SQL> select round(10.126, 2) from dual;

ROUND(10.126,2)
---------------
          10,13

SQL> select round(10.126, 2) value from dual;

     VALUE
----------
     10,13

SQL> select round(10.126, 3) value from dual;

     VALUE
----------
    10,126


Function Trunc - Retorna um número truncado em n casas.

SQL> select trunc(10.126, 3) from dual;

TRUNC(10.126,3)
---------------
         10,126

SQL> select trunc(10.126, 2) from dual;

TRUNC(10.126,2)
---------------
          10,12

SQL> select trunc(10.126, 1) from dual;

TRUNC(10.126,1)
---------------
           10,1

SQL> select trunc(123456, -1) from dual;

TRUNC(123456,-1)
----------------
          123450

SQL> select trunc(123456, -2) from dual;

TRUNC(123456,-2)
----------------
          123400

SQL> select trunc(123456, -3) from dual;

TRUNC(123456,-3)
----------------
          123000


Function SIGN - Determina se um número é positivo, negativo ou zero.

SQL> select sign(10) from dual;

  SIGN(10)
----------
         1

SQL> select sign(-10) from dual;

 SIGN(-10)
----------
        -1

SQL> select sign(0) from dual;

   SIGN(0)
----------
         0


Function ADD_MONTHS - Adiciona mês a uma data.

SQL> select add_months(to_date('31/01/2010', 'dd/mm/yyyy'), 1) from dual;

ADD_MONT
--------
28/02/10

SQL> select add_months(to_date('31/01/2010', 'dd/mm/yyyy'), -1) from dual;

ADD_MONT
--------
31/12/09


Function LAST_DAY - Retorna a data do último dia do mês.

SQL> select last_day(to_date('19/01/2010', 'dd/mm/yyyy')) from dual;

LAST_DAY
--------
31/01/10

SQL> select last_day(to_date('01/02/2010', 'dd/mm/yyyy')) from dual;

LAST_DAY
--------
28/02/10


Function MONTHS_BETWEEN - Calcula os meses entre duas datas.

SQL> select months_between(to_date('01/03/2010', 'dd/mm/yyyy'), to_date('01/04/2010', 'dd/mm/yyyy')) meses from dual;

     MESES
----------
        -1

SQL> select months_between(to_date('01/04/2010', 'dd/mm/yyyy'), to_date('01/03/2010', 'dd/mm/yyyy')) meses from dual;

     MESES
----------
         1


Function NEXT_DAY - Retorna a data do primeiro dia da semana especificado em uma string após a data inicial.

SQL> select next_day(sysdate, 'SEXTA') from dual;

NEXT_DAY
--------
22/01/10

SQL> select next_day(sysdate, 'DOMINGO') from dual;

NEXT_DAY
--------
24/01/10


Function TO_CHAR - Converte um número ou data para string.

EXEMPLOS COM DATA

SQL> select to_char(sysdate, 'Month') dt from dual;

DT
------------------------------------
Janeiro

SQL> select to_char(sysdate, 'MON') dt from dual;

DT
------------
JAN

SQL> select to_char(sysdate, 'MONTH') dt from dual;

DT
------------------------------------
JANEIRO

SQL> select to_char(sysdate, 'MM') dt from dual;

DT
--
01

SQL> select to_char(sysdate, 'YYYY') dt from dual;

DT
----
2010

SQL> select to_char(sysdate, 'YYY') dt from dual;

DT
---
010

SQL> select to_char(sysdate, 'YY') dt from dual;

DT
--
10

SQL> select to_char(sysdate, 'RR') dt from dual;

DT
--
10


SQL> select to_char(sysdate, '"Data: "DD/MM/YYYY') dt from dual;

DT
----------------
Data: 19/1/2010

SQL> select to_char(sysdate, 'FMDay, Month, YYYY') dt from dual;

DT
-------------------------------------------------------------------
Terþa-Feira, Janeiro, 2010

SQL> select to_char(sysdate, 'Day, Month, YYYY') dt from dual;

DT
-------------------------------------------------------------------
Terça-Feira  , Janeiro  , 2010


EXEMPLOS COM NÚMEROS

SQL> select to_char(12345.23, '99999999') from dual;

TO_CHAR(1
---------
    12345

SQL> select to_char(12345.23, '99999D99') from dual;

TO_CHAR(1
---------
 12345,23

SQL> select to_char(12345.23, '99999D999') from dual;

TO_CHAR(12
----------
 12345,230

SQL> select to_char(12345.23, '99999D000') from dual;

TO_CHAR(12
----------
 12345,230

SQL> select to_char(12345, '99999D000') from dual;

TO_CHAR(12
----------
 12345,000

SQL> select to_char(12345, '$99999D000') from dual;

TO_CHAR(123
-----------
 $12345,000


SQL> select to_char(12345, 'L99999D000') from dual;

TO_CHAR(12345,'L9999
--------------------
         R$12345,000

-- OBS: Se a máscara for menor que o número, o caracter # será impresso!
SQL> select to_char(12345, '999') from dual;

TO_C
----
####



segunda-feira, 18 de janeiro de 2010

Dicas e Truques PL/SQL - Parte 2

1 - Uso do WHILE com EXIT WHEN

SQL> 
  1  create or replace
  2  function conta_ate_espaco(texto in varchar2) return number is
  3    i number := 1;
  4    vResult number := 0;
  5  begin
  6    while i <= length(texto) loop
  7       if substr(texto, i, 1) != ' ' then
  8          vResult:= vResult + 1;
  9          i:= i+1;
 10       end if;
 11      exit when substr(texto, i, 1) = ' ';   -- vai sair do loop quando encontrar um espaço
 12    end loop;
 13    -- return é executado após o fim do loop ou quando exit when da linha 11 é executado.
 14    return vResult;
 14* end;
SQL>


2 - Usando rótulos para identificar loops.

EXEMPLO 1:

SQL> 
  1  create or replace
  2  function conta_ate_espaco(texto in varchar2) return number is
  3    i number := 1;
  4    vResult number := 0;
  5  begin
  6    <<conta_char>>  -- define um rótulo
  7    while i <= length(texto) loop
  8       if substr(texto, i, 1) != ' ' then
  9     vResult:= vResult + 1;
 10          i:= i+1;
 11       end if;
 12      exit when substr(texto, i, 1) = ' ';
 13    end loop conta_char;  -- finalize o loop e opcionalmente informe o nome do rótulo
 14    return vResult;
 15* end;
SQL> / 

EXEMPLO 2:

SQL> 
  1  create or replace procedure imprime_tabuada is
  2    vNumero number := 1;
  3    i number := 1;
  4  begin
  5    <<inicio_rotina>>
  6    for vNumero in 1..10 loop
  7      i := 1;
  8      <<tabuada>>
  9      loop
 10        dbms_output.put_line(to_char(vNumero) || 'x' ||
 11                             to_char(i) || ' = ' || to_char(vNumero*i));
 12        exit tabuada when i = 10;
 13        i := i + 1;
 14      end loop tabuada;
 15    end loop inicio_rotina;
 16* end;
SQL>

EXEMPLO 3


SQL> 
  1  create or replace procedure conta_ate_10 is
  2    i number := 1;
  3  begin
  4    <<conta>>
  5    loop
  6      dbms_output.put_line(i);
  7      exit when i = 10;
  8      i := i + 1;
  9    end loop;
 10* end;
SQL>


3 - Usando a instrução GOTO.

SQL> 
  1  create or replace procedure conta_ate_10_com_goto is
  2    i number := 1;
  3  begin
  4    loop
  5      dbms_output.put_line(i);
  6      if i = 10 then
  7        goto fim;
  8      end if;
  9      i := i + 1;
 10    end loop;
 11    <<fim>>
 12    null;  -- necessário uma instrução após o rótulo ou um erro é gerado
 13* end;
SQL>




domingo, 10 de janeiro de 2010

Dicas e Truques PL/SQL - Parte 1

1 - Nunca esqueça de usar o ; para finalizar uma bloco PL/SQL.


SQL> begin
2     dbms_output('não esqueça de usar ;');
3  end
4  /
end
*
ERRO na linha 3:
ORA-06550: linha 3, coluna 3:
PLS-00103: Encontrado o símbolo "end-of-file" quando um dos seguintes símbolos
era esperado:
; 

O símbolo ";" foi substituído por "end-of-file" para continuar.


SQL> begin
2     dbms_output.put_line('o ; finaliza um bloco PL/SQL');
3* end;
SQL> /

Procedimento PL/SQL concluído com sucesso.

SQL>


2 - Uma tipo VARCHAR2 tem 4000 bytes de comprimento no banco mas em PL/SQL o limite 
sobe para 32767 bytes.


3 - Existem dois subtipos para o tipo VARCHAR2: VARCHAR e STRING. A ORACLE recomenda
que não se usem estes dois subtipos, pois existe apenas para compatibilidade com
outras marcas de banco de dados e também com o padrão SQL.

SQL> 
1  declare
2    x varchar2(100);
3    y string(100);
4    z varchar(100);
5  begin
6    x:= 'Use sempre o tipo VARCHAR2 ';
7    y:= 'em vez de subtipos STRING ';
8    z:= 'ou VARCHAR.';
9    dbms_output.put_line(x || y || z);
10* end;
SQL> /
Use sempre o tipo VARCHAR2 em vez de subtipos STRING ou VARCHAR.

Procedimento PL/SQL concluído com sucesso.

SQL>


4 - Ao declarar uma variável VARCHAR2 dentro de um procedimento 
armazenado sempre especifique o comprimento ou um erro ocorrerá.


5 - Ao invocar uma função que não retorne valor um erro será levantado. 


6 - A comparação entre variáveis VARCHAR2 e CHAR pode retornar falso, pois 
o tipo CHAR é fixo.

SQL> declare
2  x1 varchar2(10);
3  x2 char(10);
4  begin
5     x1:= 'agilar';
6     x2:= 'agilar';
7     if x1 = x2 then
8             dbms_output.put_line('exatamente iguais');
9     else
10             dbms_output.put_line('diferente!');
11     end if;
12  end;
13  /

Procedimento PL/SQL concluído com sucesso.

SQL> set serveroutput on
SQL> /
diferente!

Procedimento PL/SQL concluído com sucesso.


7 - Use funções e procedimentos aninhados para obter modularidade.

SQL> 
1  declare
2     x1 number;
3     x2 number;
4    procedure troca(x in out number, y in out number)
5    as
6      temp number;
7    begin
8      temp:= x;
9      x:= y;
10      y:= temp;
11    end;
12  begin
13     x1:= 100;
14     x2:= 200;
15     dbms_output.put_line(x1);
16     dbms_output.put_line(x2);
17     troca(x1, x2);
18     dbms_output.put_line(x1);
19     dbms_output.put_line(x2);
20* end;
SQL> /
100
200
200
100

Procedimento PL/SQL concluído com sucesso.


8 - Não use os tipos obsoletos: LONG, RAW e LONG RAW.


9 - Use PLS_INTEGER em vez de BINARY_INTEGER em aplicativos novos para obter performance.


10 - Cuidado com o escopo das variáveis. Uma variável pode ser referenciada
apenas dentro do bloco em que foi declarado.

SQL> 
1  declare
2     x varchar2(10):= 'everton';
3  begin
4     declare
5             y varchar2(10):= 'agilar';
6     begin
7             dbms_output.put_line(x);
8             dbms_output.put_line(y);
9     end;
10     dbms_output.put_line(y);   -- erro pois y está declarado dentro do bloco anterior
11* end;
SQL> /
dbms_output.put_line(y);
*
ERRO na linha 10:
ORA-06550: linha 10, coluna 23:
PLS-00357: A referência 'Y' Ó Tabela, View ou Seqência não permitida neste
contexto
ORA-06550: linha 10, coluna 2:
PL/SQL: Statement ignored

SQL> 


11 - Exemplos de uso da função CAST


SQL> select cast(123.1254 as number(12,3)) as num from dual;

NUM
----------
123,125

SQL> select cast(123.1254 as number(12,2)) as num from dual;

NUM
----------
123,13

SQL> select cast(123.1254 as number(12,1)) as num from dual;

NUM
----------
123,1

SQL> select cast(123.1254 as number(12,0)) as num from dual;

NUM
----------
123

SQL> select cast(123.1254 as number(12,-1)) as num from dual;

NUM
----------
120

SQL> select cast(123.1254 as number(12,-2)) as num from dual;

NUM
----------
100

SQL> select cast(123.1254 as number(12,-3)) as num from dual;

NUM
----------
0

SQL>


12 - Você pode usar o operador de exponenciação em PL/SQL mas não em SQL.

SQL> l
1  declare
2     x number:= 10;
3     y number:= 2;
4  begin
5     dbms_output.put_line(x**y);
6* end;
SQL> /
100

Procedimento PL/SQL concluído com sucesso.

SQL> select 10**2 from dual;
select 10**2 from dual
*
ERRO na linha 1:
ORA-00936: expressão não encontrada


13 - É possível atribuir um valor durante a declaração da variável.

SQL> l
1  declare
2     pi number:= 3.14;
3     x number;
4     y number:= 10;
5  begin
6     dbms_output.put_line('O número PI is '|| to_char(pi));
7* end;
SQL>


14 - Operadores de desigualdade da PL/SQL: <>, != e ~=

1  begin
2     if 1 != 2 then
3             dbms_output.put_line('diferente');
4     end if;
5     if 1 <> 2 then
6             dbms_output.put_line('diferente');
7     end if;
8     if 1 ~= 2 then
9             dbms_output.put_line('diferente');
10     end if;
11* end;
SQL>


15 - Expressões envolvendo NULL em PL/SQL

SQL> 
1  declare
2     a number;
3     b number;
4  begin
5    -- Atribui 10 a variável A mas deixa B null.
6    a:= 10;
7    -- A lógica dos três valores diz que o resultado
8    -- de uma expressão pode ser true, false ou null.
9    if a = b then
10      dbms_output.put_line('a = b is true');
11    elsif a <> b then
12     dbms_output.put_line('a = b is not true');
13    else
14      dbms_output.put_line('a = b is null');
15    end if;
16    -- Eis uma expressão que muitos esperam ser true
17    if (a = b) or (a <> b) then
18      dbms_output.put_line('true');
19    else
20     dbms_output.put_line('is not true');
21    end if;
22* end;
SQL> /
a = b is null
is not true

Procedimento PL/SQL concluído com sucesso.

SQL>


16 - Oracle considera uma string vazia como sendo null.

SQL> 
1  declare
2     x varchar2(10);
3     y varchar2(10);
4  begin
5     -- Oracle considera uma string vazia como sendo null
6     x:= '';
7     if x = '' then
8             dbms_output.put_line('x is vazio');
9     elsif x is null then
10             dbms_output.put_line('x is null');
11     else
12             dbms_output.put_line('x contém algo?');
13     end if;
14     -- Comparação entre duas variáveis vazias
15     y:= '';
16     if x = y then
17             dbms_output.put_line('x = y');
18     elsif x is null then
19             dbms_output.put_line('x is null');
20     else
21             dbms_output.put_line('x <> y');
22     end if;
23* end;
SQL> /
x is null
x is null

Procedimento PL/SQL concluído com sucesso.

SQL>

17 - NULL não se propaga na concatenação de strings em ORACLE. Em outros
RDBMS o valor retornado é NULL.

SQL> 
1* select 'everton ' || 'agilar' || null from dual;

'EVERTON'||'AG
--------------
everton agilar

SQL> begin
2     dbms_output.put_line('everton ' || 'agilar' || null);
3  end;
4  /
everton agilar

Procedimento PL/SQL concluído com sucesso.

SQL>


18 - Use a função NVL ou COALESCE para trocar valores nulls por outro valor.


SQL> select nvl(null, 10) from dual;

NVL(NULL,10)
------------
10

SQL> select coalesce(null, 10) from dual;

COALESCE(NULL,10)
-----------------
10



19 - Como comparar duas datas em PL/SQL para saber se o ano é o mesmo ?

SQL> 
1  declare
2    d1 date;
3    d2 date;
4  begin
5    d1:= to_date('30/03/2010', 'dd/mm/yyyy');
6    d2:= sysdate;
7    if trunc(d1, 'yyyy') = trunc(d2, 'yyyy') then
8      dbms_output.put_line('ano igual...');
9    else
10      dbms_output.put_line('ano diferente...');
11    end if;
12* end;
SQL> /
ano igual...

Procedimento PL/SQL concluído com sucesso.

SQL>



20 - Obtendo as partes de uma data através da função TO_CHAR.

SQL> select to_char(to_date('10/01/2010', 'dd/mm/yyyy'), 'dd') from dual;

TO
--
10

SQL> select to_char(to_date('10/01/2010', 'dd/mm/yyyy'), 'mm') from dual;

TO
--
01

SQL> select to_char(to_date('10/01/2010', 'dd/mm/yyyy'), 'yyyy') from dual;

TO_C
----
2010

SQL>

quinta-feira, 7 de janeiro de 2010

Criando e usando um repositório Subversion

Subversion é um sistema de controle de versão muito utilizado em empresas de desenvolvimento de software para controle de versão de projetos em geral. Permite gerenciar um repositório com os fontes de um ou mais projetos e permitir acesso e alteração por diversos integrantes da equipe de desenvolvimento.

A equipe de desenvolvimento pode trabalhar em diversos arquivos e após sincronizar estes arquivos com o repositório que mantém a cópia oficial do projeto. Cada usuário trabalha em uma cópia local (Work Copy), realizando as alterações necessárias e depois comitando com o repositório.

Abaixo, segue algumas dicas sobre a implantação de um repositório SVN em minha empresa divididos em etapas que devem ser seguidas passo a passo.

Onde posso baixar o Subversion

O Subversion pode ser encontrado no link http://subversion.tigris.org/. É um produto open-source disponibilizado gratuitamente. Existem também diversos outros pacotes de software disponível e plugins para várias IDEs.

Pacotes Necessários para Implantação do Subversion


Servidor VisualSVN - http://www.visualsvn.com/visualsvn/download/
Cliente TortoiseSVN - http://tortoisesvn.tigris.org/


O que é o VisualSVN 


Conjunto de ferramentas necessárias para implementar o SVN junto com um servidor Web para administração remota. Este software é necessário no servidor onde será instalado o SVN.


O que é o TortoiseSVN


Plugin Windows para ter acesso ao repositório através do Windows Explorer. É independente de IDE e os desenvolvedores podem ter acesso aos comandos do SVN de forma muito fácil. Somente este plugin é necessário nas estações de trabaho dos desenvolvedores mas pode ser instalado também no servidor para facilitar o uso do SVN.


Sobre o servidor VisualSVN


Existem diversos pacotes e plugins disponíveis ficando as vezes complicado a escolha de qual instalar. Ao implantar o Subversion optei por instalar o VisualSVN. O link direto pode ser encontrado em: http://www.visualsvn.com/visualsvn/download/.

A escolha do VisualSVN foi permitir gerenciar os usuários e criar o repositório em uma ferramenta visual, ter acesso aos comandos standalone svn e svnadmin quando necessário e ainda permitir gerenciar o repositório remotamente. Os comandos svn, svnadmin são muito úteis para administração do repositório via linha de comando. A Fig. 1 exibe a tela do VisualSVN.



Para instalar o servidor é preciso apenas executar seu setup. Um serviço será instalado chamado VisualSVN. Você pode verificar o serviço através do utilitário services.msc. Durante a instalação é necessário selecionar a porta do serviço ou deixar a porta padrão 443 se a opção SSL for selecionada.

Com o servidor instalado, já podemos abrir o aplicativo VisualSVN Server Manager e criar um repositório SVN.

Instalando o cliente TortoiseSVN


Apos instalado o VisualSVN, vamos instalar o plugin TortoseSVN. Através deste plugin podemos fazer praticamente qualquer atividade necessária: criar um repositório, criar um pasta de trabalho, etc. A intenção de utilizar o TortoiseSVN é aumentar a produtividade no dia-dia, pois não será necessário usar o prompt de comando para sincronizar os fontes com a equipe. Este plugin pode ser instalado tanto no servidor, se também for um ambiente de desenvolvimento como nas demais estações de trabalho.

Para instalar o TortoiseSVN basta executar o setup e sequir confirmando as opções do instalador. Com a instalação concluída perceba que se você clicar no botão direito do mouse verá o menu TortoiseSVN. É através deste menu que você tem acesso a todos os recursos do Subversion para gerenciar o seu SVN. A Fig. 2 exibe o menu com a opção TortoiseSVN e SVN Checkout....



Entendendo o Repositório


Pense no repositório como um banco de dados. Dentro do banco de dados você vai inserir (usamos o termo importar no SVN) a pasta raiz do seu projeto e então poderá através do TortoiseSVN criar uma pasta "local" em qualquer computador na sua rede exatamente igual a pasta importada do seu projeto. Esta pasta local será a Work Copying, ou seja, cópia de trabalho. Você, desenvolvedor, poderá trabalhar nela e alterar qualquer arquivo sem interferir no servidor SVN. Quando desejar poderá querer salvar (comitar) as alterações realizadas com o servidor, quando então, o Subversion vai persistir os arquivos alterados no repositório do projeto.

A cada commit, o Subversion gera uma nova versão. Através deste esquema de geração de versão, pode-se rapidamente "navegar" entre as versões do projeto com muita facilidade e sem medo de perda de dados, uma vez que estamos apenas trabalhando em uma cópia local.

O Subversion tem total controle do que a equipe de desenvolvimento está fazendo. Por exemplo, se dois usuários tentarem comitar um mesmo arquivo sendo alterado, o desenvolvedor será avisado que o arquivo foi alterado por mais de 1 usuário e oferecerá várias opções para eliminar o conflito. Em meus vários testes, obtive muito exito. De fato, o TortoiseSVN oferece uma quantidade enorme de ferramentas, incluindo ferramentas que mostram o que mudou de um arquivo para outro (Diffs).


Criando um Repositório


Com o servidor VisualSVN e o cliente TortoiseSVN instalados vamos criar um repositório no servidor para gerenciar um projeto. Para isto é preciso definir onde será o repositório. O repositório pode ser criado de varias maneiras:

  • com o VisualSVN - No VisualSVN você pode criar o repositório facilmente. Será necessário criar pelo menos um usuário antes realizar a criação do repositório. Vários outros usuários podem ser criados para utilizar o SVN.
  • com o TortoiseSVN - Através do menu TortoseSVN selecione a opção "Create repository here". A criação do repositório pelo Tortoise seria útil para um desenvolvedor. Para uma equipe use o VisualSVN.
  • Pode-se usar a opção de linha de comando - svnadmin create d:\repo


Importando o projeto para o repositório


Para importar o projeto para o repositório navegue até a pasta do projeto e com a opção "Import" do TortoseSVN, informe o repositório onde será armazenado o projeto. Informe o caminho no seguinte formato: https://hostname/svn/nome_repositorio. Clique no botão Ok e aquarde o projeto ser importado para dentro do repositório. Após importado já é possível criar uma pasta de trabalho em qualquer estação de trabalho.

Criando a pasta de trabalho (Working Copy)


Novamente, utilizando o plugin TortoiseSVN, selecione a opção SVN Checkout em alguma pasta vazia, onde será definido a pasta de trabalho. Aguarde a criação de pasta de trabalho e após já pode começar a trabalhar nos fontes.

Pode-se utilizar a linha de comando. Segue um exemplo abaixo:
svn checkout https://pc01/svn/poligestor d:\Projetos\PoliGestor

Comitando as alterações no Repositório


Após qualquer alteração nos fontes do projeto, pode-ser, através da opção SVN Commit, comitar as alterações realizadas no repositório.

Atualizando a pasta de trabalho


Em uma equipe de desenvolvimento vários desenvolvedores estão trabalhando em um mesmo projeto. Para sincronizar a pasta de trabalho com o servidor faz-se um update através do TortoseSVN. A opção utiliada é SVN Update no menu.

Conclusão


O gerenciamento de projeto com SVN torna-se uma necessidade cada vez maior em projetos atuais, pois elimina quande parte da complexidade do gerenciamento e facilita o compartilhamento dos fontes. Espero que com este artigo poder ter ajudo a vários que já tiveram a idéia de implantar um SVN para uma equipe de desenvolvedores e não encontraram material que torna-se fácil esta tarefa.

quarta-feira, 6 de janeiro de 2010

Exemplo de Programa em JAVA usando JDBC para conectar ao ORACLE

O programa abaixo, demonstra os passos necessários para fazer conexão usando JDBC ao ORACLE.

import java.sql.*;
/*
 * Programa ConexaoOracle.java 
 * 
 * Demonstrar a utilização do driver JDBC para conexão ao ORACLE
 * 
 * Data: 06/01/2010
 * Autor: Everton de Vargas Agilar
 * 
 * Para executar este programa execute o seguinte no prompt de comando:
 *   java -classpath "c:\Arquivos de programas\java\jdk1.7.0\jdbc\ojdbc6.jar"; ConexaoOracle
 *
 *   Obs.: a opção -classpath informa o caminho do driver JDBC para o ORACLE.
 * 
 *  Biblioteca Necessária: Driver JDBC para Oracle
 *  http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/
 *  
 */

public class ConexaoOracle {

 public static void main(String[] args) {
  System.out.println("Conexão Oracle");
  
  Connection conn = null;
  Statement smnt = null;
  ResultSet rs = null;
  String sql = null;

  try {
   Class.forName("oracle.jdbc.OracleDriver");
  } catch (ClassNotFoundException e) {
   System.out.println("Driver para ORACLE não encontrado!\nErro interno: ");
   e.printStackTrace();
  }
  
  try {
   conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "gestorerp", "gestorerp");
  } catch (SQLException e) {
   System.out.println("Erro ao obter conexão ao banco de dados XE\nErro interno: ");
   e.printStackTrace();
  }
  
  System.out.println("Conexão bem sucedida!");
  
  try {
   smnt = conn.createStatement();
  } catch (SQLException e) {
   System.out.println("Erro ao criar instrução SQL\nErro interno: ");
   e.printStackTrace();
  }
  
  sql = "select * from sequence";
  try {
   rs = smnt.executeQuery(sql);
   while (rs.next()){
    System.out.println("SEQ_NAME "+ rs.getString("SEQ_NAME"));
   }
   
  } catch (SQLException e) {
   System.out.println("Ocorreu erro ao executar sql!\nErro interno: ");
   e.printStackTrace();
  }
  
  try {
   conn.close();
  } catch (SQLException e) {
   System.out.println("Ocorreu erro ao terminar a conexão ao banco de dados!\nErro interno: ");
   e.printStackTrace();
  }
  
  System.out.println("FIM...");
 }
}

Dor de cabeça com -classpath com apenas 1 biblioteca

Hoje me deparei com uma situação interessante que pode ser uma dor de cabeça para quem está informando as bibliotecas na opção de linha de comando -classpath ou -cp da máquina virtual Java.

Acontece que precisei informar apenas uma biblioteca para meu aplicativo e o seguinte erro estava ocorrendo: Error: Could not find main class MeuAplicativo

Percebi que ao informar um ; no final da string dos caminhos o erro não acontecia. Veja abaixo as linhas de comando com erro e sem erro:

  • Este comando não executa:
  • C:\>java -classpath "c:\Arquivos de programas\java\jdk1.7.0\jdbc\ojdbc6.jar" MeuAplicativo
    Error: Could not find main class MeuaAplicativo
    Exception in thread "main" java.lang.NoClassDefFoundError: MeuaAplicativo
            at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:198)
    Caused by: java.lang.ClassNotFoundException: MeuaAplicativo
            at java.net.URLClassLoader$1.run(URLClassLoader.java:299)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:288)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:287)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:422)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:325)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:355)
            at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:195)
    
    
  • Este comando executa corretamente porque informei o ";" no final da string do caminho:
  • C:\>java -classpath "c:\Arquivos de programas\java\jdk1.7.0\jdbc\ojdbc6.jar"; MeuAplicativo
    
  • Este comando também funciona:
  • C:\>java -classpath "c:\Arquivos de programas\java\jdk1.7.0\jdbc\ojdbc6.jar";. MeuAplicativo
    

Ainda bem que logo ao tentar executar o comando pela segunda vez coloquei o ";". Isso poderia ser uma dor de cabeça sem tamanho, você sabe que a sintaxe do comando está certo mas a máquina virtual não consegue executar o aplicativo. Talvez isso seja o fato do parser do programa java.exe não saber tratar bem o -classpath com apenas uma biblioteca.