quarta-feira, 18 de janeiro de 2012

Como eliminar registros em um Browse de multipla seleção

DEFINE VARIABLE i AS INTEGER    NO-UNDO.
  DEFINE VARIABLE l AS LOGICAL    NO-UNDO.
  DO i = 1 TO {&browse-name}:NUM-SELECTED-ROWS:
     ASSIGN l = {&browse-name}:FETCH-SELECTED-ROW(i).
     IF l THEN DO:
         FIND CURRENT customer EXCLUSIVE-LOCK.
         DELETE customer.
     END.
  END.
  {&OPEN-QUERY-{&BROWSE-NAME}}

Stored-procedure em um programa Progress


Hoje precisei desenvolver e utilizar uma stored-procedure Oracle em um programa Progress. E então resolvi compartilhar isto com vocês...

Primeiramente deve-se criar a stored-procedure no Oracle, através do utilitário SQL*Plus, por exemplo. A seguir apresento o código de uma stored-procedure bem simples:

CREATE PROCEDURE createBanco (bancoId IN NUMBER, bancoNome IN VARCHAR2) AS
BEGIN
INSERT INTO banco (cod_banco, nome_abrev, u##nome_abrev, nome_banco, ag_padrao, convenio, cod_resp, usa_cob_esc, cod_febraban) VALUES(bancoId, bancoNome, UPPER(bancoNome), bancoNome, ' ', 0, ' ', 0, 0);
END;

Após a criação deve-se atualizar o Schema Holder Progress para conter a stored-procedure recém criada, pois para programas Progress ela é vista como uma tabela (sua assinatura é verificada em tempo de compilação). Para fazer esta atualização, deve-se utilizar o utilitário Data Administration.

Os passos para atualização* são os seguintes:

Executar o Data Administration;
Selecionar o banco Oracle (não o Schema Holder) que contém a stored-procedure;
Selecionar o menu DataServer + ORACLE Utilities + Update/Add Table Definitions;
Informar os dados de login do usuário proprietário da stored-procedure no banco Oracle;
Informar o nome da stored-procedure no campo object name;
Schema Holder atualizado.

Depois disso, basta utilizar a stored-procedure nos programas Progress, através do comando RUN STORED-PROCEDURE. A seguir apresento um exemplo:

DEFINE VARIABLE iStoredProc AS INTEGER.

RUN STORED-PROCEDURE mgadm.create-banco
    iStoredProc = PROC-HANDLE NO-ERROR
    (INPUT 1009, INPUT "1009").

FOR EACH mgadm.proc-text-buffer
    WHERE PROC-HANDLE = iStoredProc:
    DISPLAY mgadm.proc-text-buffer.proc-text.
END.

CLOSE STORED-PROCEDURE mgadm.create-banco
    WHERE PROC-HANDLE = iStoredProc.

quinta-feira, 27 de janeiro de 2011

Can-find - use-o sempre que possível

Sempre que você precisar validar a existencia de um determinado dado no banco, mas não vai precisar utilizar o mesmo posteriormente, use o can-find. Isto vai ajudar bastante na performance do seu sistema, visto que não estará trafegando um registro inteiro pela rede, mas apenas tendo um retorno de sim ou não para a existencia da informação. O uso é simples, como abaixo:

If can-find(FIRST customer where customer.name = "João Pereira da Silva" and customer.city = "Joinville") then

           message "cliente encontrado! ".

If not can-find(customer where customer.cust-num = 99) then
          message "Chave informada ainda não existe".

segunda-feira, 24 de janeiro de 2011

A função Substring

Bastante útil quando precisamos "pegar" parte de um arquivo, a função substring possui dois parâmetros, o primeiro passa a posição em que começaremos a leitura da string em questão, o segundo, a quantidade de bits que estaremos lendo da string.
Vamos por exemplo gravar na variavel a, a palava "viu " da frase "Ivo viu a uva.". As variáveis i e j serão inteiras e conterão os valores ponto inicial e número de caracteres a serem lidos. Ok?

define variable a as char no-undo.
define variable b as char no-undo.
define variable i as integer no-undo.
define variable j as integer no-undo.

a = "Ivo viu a uva.".
i = 5.  /* i é 5 porque temos antes 4 caracteres, "ivo ". */
j = 3. /* j é 3 porque queremos ler 3 caracteres "viu"  */

b = substring(a, i, j).

display b. /* vai mostrar "viu" */

quinta-feira, 20 de janeiro de 2011

Dicas Progress - compartilhando dados(temp-table)

Temos 3 formas de compartilhar informações entre programas. Passagem de parâmetros, compartilhamento(shared) e variáveis\objetos globais. Todas elas nos servem em determinadas situações, eu aprendi e vi testes que o ideal em termos de memória e performance é o uso de shared, que como diz o nome, compartilha uma área de memória e assim não duplica o uso da mesma. No caso de parametros, é utilizada uma nova área que recebe as informações, o que dobra o uso de memória e quando definimos global, o problema é que apenas quando fecharmos a sessão é que deixará a memória livre. Abaixo, programa exemplo das 3 situações. Qualquer dúvida, comente que tentarei responder.

/* temp table como parametro */

DEFINE TEMP-TABLE ttTeste
  FIELD nome AS CHAR
  FIeld endereco AS CHAR FORMAT "x(50)"
  FIELD cidade AS CHAR.
                                         
repeat:
    INSERT ttTeste WITH SIDE-LABELS.
END.



RUN c:\aprenderProgress\utilizaTT.p (INPUT TABLE ttTeste).

/* utilizaTT parametro */

DEFINE TEMP-TABLE ttTeste
  FIELD nome AS CHAR
  FIeld endereco AS CHAR FORMAT "x(50)"
  FIELD cidade AS CHAR.

DEFINE INPUT PARAMETER TABLE FOR ttTeste.


FOR EACH ttTeste:
    DISP ttTeste.
END.


/* temp table como shared */

DEFINE NEW SHARED TEMP-TABLE shttTeste
  FIELD nome AS CHAR
  FIeld endereco AS CHAR FORMAT "x(50)"
  FIELD cidade AS CHAR.


repeat:
    INSERT ttTeste WITH SIDE-LABELS.
END.

/* utilizaTT shared */

DEFINE SHARED TEMP-TABLE ttTeste
  FIELD nome AS CHAR
  FIeld endereco AS CHAR FORMAT "x(50)"
  FIELD cidade AS CHAR.


FOR EACH ttTeste:
    DISP ttTeste.
END.

RUN c:\aprenderProgress\utilizaTT.p (INPUT TABLE ttTeste).

/* temp table global  */

DEFINE NEW GLOBAL SHARED TEMP-TABLE glttTeste
  FIELD nome AS CHAR
  FIeld endereco AS CHAR FORMAT "x(50)"
  FIELD cidade AS CHAR.

repeat:
    INSERT ttTeste WITH SIDE-LABELS.
END.

RUN c:\aprenderProgress\utilizaTT.p (INPUT TABLE ttTeste).

/* utilizaTT global */

DEFINE NEW GLOBAL SHARED TEMP-TABLE ttTeste
  FIELD nome AS CHAR
  FIeld endereco AS CHAR FORMAT "x(50)"
  FIELD cidade AS CHAR.


FOR EACH ttTeste:
    DISP ttTeste.
END.