quinta-feira, 26 de abril de 2012

Tabelas Temporárias no Banco de Dados Oracle


DEFINIÇÃO
Uma tabela temporária é uma tabela com vida útil de uma sessão ou transação. Ela está vazia quando a sessão ou transação começa e descarta os dados ao fim da sessão ou transação. Uma tabela temporária é associada à transação. Isto significa que ao término da transação os dados da tabela são perdidos, porém sua descrição permanece gravada no banco de dados mesmo após a mudança de sessão.

Nesta solução, o que é temporário é o armazenamento dos dados. Com este tipo de tabela não temos necessidade de remover os dados ao término da transação. Podem ser muito úteis na geração de dados de trabalho temporários. A seguir serão mostrados dois exemplos: 
O primeiro(Listagem 1) de uma tabela temporária que é associada à transação e o segundo (Listagem 2), de uma tabela temporária que é associada à sessão.


SQL> create global temporary table TEMP_PROD
2 (cod_prod number(5),
3 desc_prod varchar2(30),
4 dat_cadas date);
Table created.
SQL> insert into TEMP_PROD
2 values (1,'Mesa',sysdate);
1 row created.
SQL> select * from TEMP_PROD;
COD_PROD DESC_PROD DAT_CADAS
---------- ------------------------------ ---------
1 Mesa 18-MAR-05

SQL> commit;
Commit complete.

SQL> select * from TEMP_PROD;
no rows selected

SQL> desc TEMP_PROD;
Name Null? Type
------------------------------- -------- ----
COD_PROD NUMBER(5)
DESC_PROD VARCHAR2(30)
DAT_CADAS DATE
SQL>
Listagem 1. Tabela temporária por transação

Neste primeiro exemplo foi criada uma tabela temporária associada à transação. Isto significa que ao término da transação (commit ou rollback) os dados da tabela são perdidos. No exemplo, utilizamos o comando commit para finalizar a transação. Note que após executar o comando commit, o select seguinte não retorna nenhum registro, porém a estrutura da tabela permanece gravada no banco de dados mesmo após a mudança de sessão.

SQL> create global temporary table TEMP_PROD
2 (cod_prod number(5),
3 desc_prod varchar2(30),
4 dat_cadas date) on commit preserve rows;
Table created.
SQL> insert into TEMP_PROD
2 values (100,'Computador',sysdate);
1 row created.

SQL> select * from TEMP_PROD;
COD_PROD DESC_PROD DAT_CADAS
---------- ------------------------------ ---------
100 Computador 18-MAR-05
SQL> commit;
Commit complete.

SQL> select * from TEMP_PROD;
COD_PROD DESC_PROD DAT_CADAS
---------- ------------------------------ ---------
100 Computador 18-MAR-05
SQL> connect dados@data1w
Enter password: *****
Connected.

SQL> select * from TEMP_PROD;
no rows selected
SQL> desc TEMP_PROD;
Name Null? Type
------------------------------- -------- ----
COD_PROD NUMBER(5)
DESC_PROD VARCHAR2(30)
DAT_CADAS DATE


Listagem 2. 
Tabela temporária por sessão

Neste segundo exemplo, a tabela foi criada com a indicação de que após o término da transação os dados deverão ser mantidos, ou seja, a tabela é temporária, porém seus dados ficam disponíveis por toda a sessão independente de transação. Quando ocorre o fim da sessão (disconnect e connect), os dados são removidos (ou liberados). Note que no exemplo acima, após executar o comando connect, os dados da tabela foram removidos, porém a estrutura da tabela permanece gravada no banco de dados mesmo após a mudança de sessão.

CARACTERÍSTICAS
As tabelas temporárias possuem as seguintes características:
• Sua definição é visível para todas as sessões, mas seus dados são visíveis e acessíveis somente pela sessão que os inclui.

• O comando LOCK não tem efeito em tabelas temporárias uma vez que cada sessão tem acesso exclusivo a seus dados.

• Um comando TRUNCATE trunca somente os dados referentes à sessão do usuário.
• Os dados são criados na tablespace temporária do usuário.

• Operações de Rollback to Savepoint são suportadas, mas os dados não são recuperáveis caso ocorra um “crash” porque as modificações não são logadas (gravadas no REDO LOG).

• Podemos criar índices para uma tabela temporária usando o comando CREATE INDEX. Estes índices também são temporários.

• Podemos criar triggers para tabelas temporárias assim como views que utilizem simultaneamente tabelas temporárias e permanentes.

• Os utilitários IMPORT e EXPORT podem exportar e importar a definição de uma tabela temporária, porém nenhum dado é exportado.

• Da mesma forma, podemos replicar a definição de uma tabela temporária, mas não podemos replicar seus dados.

• Só podemos executar operações de DDL (ALTER TABLE, DROP TABLE, CREATE INDEX, etc.) para a tabela temporária se não houver nenhuma tabela fazendo acesso a ela.

• Uma tabela temporária associada à transação é acessível por uma determinada transação e suas transações filha. Porém, uma tabela temporária associada à transação não é acessível por duas transações simultâneas na mesma sessão, apesar de poder ser usada por transações em diferentes sessões.

• Se uma transação do usuário faz um INSERT em uma tabela temporária, então nenhuma de suas transações filhas pode usar a tabela temporária após isto.

• Se uma transação filha faz um INSERT em uma tabela temporária, ao fim da transação filha, o dado associado com a tabela temporária é removido. Após isto, tanto a transação do usuário quanto qualquer outra transação podem fazer acesso à tabela temporária.

Conclusões
Vimos neste artigo que o uso da tabelas temporárias é muito interessante, o uso deste mecanismo por transação ou sessão deverá ser analisado em cada caso. Isto pode evitar o problema de se manter tabelas temporárias com volumes grandes armazenados no banco de dados sem real necessidade.

Referências 
http://www.oracle.com.br– site da Oraclehttp://metalink.oracle.com– Site da Oracle de pesquisa técnica.

Enviar e-mail externo a partir do programa ABAP e incluir anexo


REPORT  zpptest28_mymail                               .
TABLES: kna1.
DATA : w_name(135).

SELECTION-SCREEN :
SKIPBEGIN OF LINE,COMMENT 5(35) var1 FOR FIELD s_name.
SELECT-OPTIONS :
   s_name FOR w_name DEFAULT sy-uname NO INTERVALS.
SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN :
SKIPBEGIN OF LINE,COMMENT 5(35) var2 FOR FIELD s_culist.
SELECT-OPTIONS :
* How many Customer's List you wish to mail?
  s_culist FOR kna1-kunnr.
SELECTION-SCREEN END OF LINE.


INITIALIZATION.
  var1 = 'Recipient Address'.
  var2 = 'Customer No'.
  s_culist-low = '10'.
  s_culist-high = '50'.
  APPEND s_culist.

*---------------------------------------------------------------------*
START-OF-SELECTION.

  PERFORM f_send_mail.

*---------------------------------------------------------------------*
* Form f_send_mail
*---------------------------------------------------------------------*
FORM f_send_mail.
*Routine to send mail
* Data Declaration
  DATA:
    l_datum(10),
    ls_docdata    TYPE sodocchgi1,
    lt_objpack    TYPE TABLE OF sopcklsti1 WITH HEADER LINE,
    lt_objhead    TYPE TABLE OF solisti1   WITH HEADER LINE,
    lt_objtxt     TYPE TABLE OF solisti1   WITH HEADER LINE,
    lt_objbin     TYPE TABLE OF solisti1   WITH HEADER LINE,
    lt_reclist    TYPE TABLE OF somlreci1  WITH HEADER LINE,
    lt_listobject TYPE TABLE OF abaplist   WITH HEADER LINE,

    l_tab_lines TYPE i,
    l_att_type  LIKE soodk-objtp.

* Inicio Enviar E-mail como Excel
constants:
    c_nova_coluna  type c value cl_abap_char_utilities=>HORIZONTAL_TAB,
    c_nova_linha type c value cl_abap_char_utilities=>CR_LF.

*faça um select / loop na tabela  kna1

  clear lt_objbin.
  concatenate 'Coluna1' 'Coluna2' 'Coluna3'  'Coluna4' c_nova_linha INTO lt_objbin-line SEPARATED BY c_nova_coluna.
  CONDENSE lt_objbin-line NO-GAPS.
  APPEND lt_objbin.
  clear lt_objbin.
  concatenate 'Coluna1' 'Coluna2' 'Coluna3'  'Coluna4' c_nova_linha INTO lt_objbin-line SEPARATED BY c_nova_coluna.
  CONDENSE lt_objbin-line NO-GAPS.
  APPEND lt_objbin.
  clear lt_objbin.
  concatenate 'Coluna1' 'Coluna2' 'Coluna3'  'Coluna4' c_nova_linha INTO lt_objbin-line SEPARATED BY c_nova_coluna.
  CONDENSE lt_objbin-line NO-GAPS.
  APPEND lt_objbin.
  clear lt_objbin.
  concatenate 'Coluna1' 'Coluna2' 'Coluna3'  'Coluna4' c_nova_linha INTO lt_objbin-line SEPARATED BY c_nova_coluna.
  CONDENSE lt_objbin-line NO-GAPS.
  APPEND lt_objbin.
  concatenate '1111111' '2222222' '3333333'  '''4444444''' 'F' c_nova_linha INTO lt_objbin-line SEPARATED BY c_nova_coluna.
  CONDENSE lt_objbin-line NO-GAPS.
  APPEND lt_objbin.
*
* Final Enviar E-mail como Excel


* NOTE: Creation of attachment is finished yet.
* For your report, the attachment should be placed into table
* objtxt for plain text or
* objbin for binary content.
* Now create the message and send the document.
* Create Message Body
* Title and Description
  ls_docdata-obj_name = 'Nome do anexo'.
  CONCATENATE 'Lista de clientes' s_culist-high
        INTO ls_docdata-obj_descr SEPARATED BY space.

* Main Text
  lt_objtxt = 'Texto do corpo da mensagem'.

  APPEND lt_objtxt.
* Write Packing List (Main)
  DESCRIBE TABLE lt_objtxt LINES l_tab_lines.
  READ TABLE lt_objtxt INDEX l_tab_lines.
  ls_docdata-doc_size = ( l_tab_lines - 1 ) * 255 + STRLEN( lt_objtxt ).
  CLEAR lt_objpack-transf_bin.
  lt_objpack-head_start = 1.
  lt_objpack-head_num = 0.
  lt_objpack-body_start = 1.
  lt_objpack-body_num = l_tab_lines.
  lt_objpack-doc_type = 'RAW'.
  APPEND lt_objpack.

* Create Message Attachment
* Write Packing List (Attachment)
  l_att_type = 'XLS'.
  DESCRIBE TABLE lt_objbin LINES l_tab_lines.
  READ TABLE lt_objbin INDEX l_tab_lines.
  lt_objpack-doc_size = ( l_tab_lines - 1 ) * 255 + STRLEN( lt_objbin ).
  lt_objpack-transf_bin = 'X'.
  lt_objpack-head_start = 1.
  lt_objpack-head_num = 0.
  lt_objpack-body_start = 1.
  lt_objpack-body_num = l_tab_lines.
  lt_objpack-doc_type = l_att_type.
  lt_objpack-obj_name = 'ATTACHMENT'.
  lt_objpack-obj_descr = 'Nome do anexo'.                   "#EC *
  APPEND lt_objpack.

* Create receiver list
  LOOP AT s_name.
    lt_reclist-receiver = 'adilson.afl@gmail.com.br'.
    lt_reclist-rec_type = 'U'.
*    lt_reclist-receiver = s_name-low.
*    lt_reclist-rec_type = 'B'.
    APPEND lt_reclist.
  ENDLOOP.

* Send Message
  CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
    EXPORTING
      document_data              = ls_docdata
      put_in_outbox              = 'X'
      commit_work                = 'X'
    TABLES
      packing_list               = lt_objpack
      object_header              = lt_objhead
      contents_bin               = lt_objbin
      contents_txt               = lt_objtxt
      receivers                  = lt_reclist
    EXCEPTIONS
      too_many_receivers         = 1
      document_not_sent          = 2
      document_type_not_exist    = 3
      operation_no_authorization = 4
      parameter_error            = 5
      x_error                    = 6
      enqueue_error              = 7
      OTHERS                     = 8.

  IF sy-subrc = 0.
*   Document sent
    MESSAGE ID 'SO' TYPE 'S' NUMBER '022'.
  ELSE.
*   Document <&> could not be sent
    MESSAGE ID 'SO' TYPE 'S' NUMBER '023'
       WITH ls_docdata-obj_name.
  ENDIF.

  WAIT UP TO 2 SECONDS.
  SUBMIT rsconn01 WITH mode = 'INT'
  WITH output = 'X'
  AND RETURN.

ENDFORM.                               " F_SEND_MAIL