Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Corte ou Sem Corte?


Essa é a questão.



Um post recente nos fóruns da OTN perguntou sobre o uso de ponto e vírgula e barras como terminadores de declaração. Tirei a poeira de um artigo que escrevi para nossa equipe de desenvolvimento há mais de 4 anos sobre esse tópico. Este artigo recebeu boas críticas e está disponível nos fóruns da OTN, se desejado. Pensei em postar também no meu blog. Aqui está o artigo:


Barra ou sem barra


por Brian Peasland

Em nossa empresa, os scripts SQL implantados são executados no utilitário de linha de comando SQL*Plus da Oracle, enquanto muitos desenvolvedores usam uma ferramenta GUI como PL/SQL Developer ou SQL Developer. A barra significa algo para o SQL*Plus que não é necessário no PL/SQL Developer ou no SQL Developer. Como tal, pode ser confuso saber se você precisa incluir uma barra em seus scripts SQL ou não. Esperançosamente, esta seção irá esclarecer o que a barra faz, quando usá-la e quando não usá-la. Terminador de ponto e vírgula Para a maioria das instruções SQL, o ponto e vírgula é o terminador de instrução. Por exemplo, considere esta simples instrução SQL executada no SQL*Plus:

SQL> selecione sysdate de dual;

SYSDATE

———

18-JUN-12

Quando o SQL*Plus vê o ponto e vírgula, ele sabe que o final da instrução SQL foi atingido e agora pode executar o comando.

Buffer SQL*Plus


Você pode não estar ciente de que o SQL*Plus possui um buffer para seus comandos. Se eu pressionar a tecla 'l' para 'lista', posso ver o comando atualmente no buffer da minha sessão.

SQL>l

1 * selecione sysdate de dual

Não surpreendentemente, há o comando que acabei de executar. Em seguida, executei outra instrução SQL e aqui está a aparência do meu buffer:

SQL>l

1 selecione sysdate, usuário

2* de duplo

Como você pode ver, agora tenho duas linhas no buffer SQL*Plus da minha sessão.

Barra =Executar buffer


A primeira regra a entender sobre a barra é que para o SQL*Plus, a barra significa executar o conteúdo do buffer. Para ilustrar esse conceito, executarei uma instrução SQL, aguardarei alguns segundos e, em seguida, executarei a mesma instrução SQL novamente, mas apenas executando o buffer.

SQL> selecione to_char(sysdate,'MM/DD/AAAA HH24:MI:SS') de dual;

TO_CHAR(SYSDATE,'MM

——————-

18/06/2012 15:20:40

SQL> /
TO_CHAR(SYSDATE,'MM

——————-

18/06/2012 15:21:17

SQL> /

TO_CHAR(SYSDATE,'MM

——————-

18/06/2012 15:21:50

Você pode ver que tudo o que fiz na segunda e na terceira vez foi apenas digitar '/' e pressionar enter e o SQL*Plus executou o conteúdo de seu buffer de comando a cada vez.

Blocos PL/SQL


O terminador de instrução de ponto e vírgula funcionou bem sozinho até que a Oracle introduziu o PL/SQL no Oracle versão 7. O problema é que os blocos PL/SQL podem ter vários pontos e vírgulas para encerrar as instruções individuais que compõem esse bloco. Considere este bloco PL/SQL muito simples que não faz nada:

SQL> iniciar

2 nulo;

3 nulo;

4 fim;

5

As linhas 2 e 3 contêm instruções perfeitamente válidas, cada uma terminada com ponto e vírgula. E na linha 4, temos a palavra-chave END significando o fim do bloco PL/SQL. Se não for permitido pares BEGIN/END aninhados, toda vez que o SQL*Plus vir “END;” ele saberia que o fim do bloco PL/SQL foi atingido, mas nos são permitidos pares BEGIN/END aninhados, então o seguinte é perfeitamente legal e válido:

SQL> iniciar

2 começar

3 nulo;

4 fim;

5 nulo;

6 fim;

7

Você pode dizer acima que apenas procurando por “END;” não é suficiente porque o SQL*Plus teria tentado executar o bloco após a linha 4. Então, como a Oracle decidiu indicar que o bloco PL/SQL estava pronto para ser executado? A resposta é usando a barra, como você já deve estar ciente. A segunda regra a entender é que tudo que a barra está fazendo quando você a usa para finalizar um bloco PL/SQL é dizer ao SQL*Plus para executar o que está no buffer! Isso não mudou desde antes da criação do PL/SQL para o Oracle 7. Considere o seguinte exemplo:

SQL> iniciar

2 nulo;

3 fim;

4 /

Procedimento PL/SQL concluído com sucesso.

SQL>l

1 início
2 nulo;

3* fim;

Na linha 4, digitei a barra para executar o bloco PL/SQL. Você pode ver que meu bloco foi concluído com sucesso. Se voltarmos e olharmos para o conteúdo do meu buffer de comando, você verá que ele contém tudo, menos a barra. A barra não faz parte do buffer de comando. Então agora, vou executar um bloco PL/SQL diferente:

SQL> iniciar

2 dbms_output.put_line('Hoje é '||to_char(sysdate,'MM/DD/AAAA HH24:MI:SS'));

3 fim;

4 /

Hoje é 18/06/2012 15:39:32

Procedimento PL/SQL concluído com sucesso.

A barra disse ao SQL*Plus para executar o que está em seu buffer e os resultados são exibidos. Agora vamos digitar apenas a barra novamente e devemos ver nosso bloco PL/SQL sendo executado novamente.

SQL> /

Hoje é 18/06/2012 15:40:42

Procedimento PL/SQL concluído com sucesso.

Não precisei digitar meu bloco PL/SQL novamente, pois ele está atualmente no buffer de comando.

Desenvolvedor PL/SQL e SQL e Blocos PL/SQL


O maior problema para a maioria dos desenvolvedores é que o PL/SQL Developer e o SQL Developer não exigem que você use a barra. Por quê? Porque você pode clicar em Executar (F8) ou Executar Script (F5) para executar seu bloco PL/SQL. O PL/SQL Developer sabe que no momento em que você pressionar F8, você pretende enviar o bloco PL/SQL para ser executado. Nesse caso, F8 no PL/SQL Developer está fazendo o mesmo trabalho que a barra no SQL*Plus. Da mesma forma, para F5 no SQL Developer.

O problema na minha empresa é que nossa equipe de implantação de código para produção não implanta código com PL/SQL Developer ou SQL Developer. Eles usam o SQL*Plus porque criar scripts de várias execuções é mais fácil com uma ferramenta de linha de comando. Muitos desenvolvedores cometem o erro de não incluir a barra para blocos PL/SQL em scripts porque eles não precisam dela, mas se você deseja implantar essa seção de código em um script SQL, a barra é necessária no final de cada PL bloco /SQL.

Quando não usar barra


Então, vimos quando e por que usamos a barra, mas quando é ruim usá-la? A terceira regra a saber é que é ruim usar a barra após uma única instrução SQL (não em um bloco PL/SQL), especialmente quando essa barra segue imediatamente uma instrução DML (INSERT, UPDATE ou DELETE). Se meu script contiver o seguinte:

selecione sysdate de dual;

/

Então, obterei “saída dupla”, que não é o que normalmente pretendo fazer em um script. Eu realmente quero apenas uma linha retornada, não duas, como o script acima faria:

SQL> selecione sysdate de dual;

SYSDATE

———

18-JUN-12
SQL> /

SYSDATE

———

18-JUN-12

É ainda pior quando eu uso a barra após uma instrução DML porque essa instrução será executada duas vezes. Considere o seguinte roteiro:

insira em valores test_tab (10);

/

Agora sabemos que quando executo as duas linhas acima em um script, o SQL*Plus o executará uma vez devido ao terminador de instrução de ponto e vírgula e, em seguida, executará uma segunda vez porque a barra indica ao SQL*Plus para executar o que está no buffer de comando. Quando executo o script de duas linhas acima, recebo a seguinte saída:

SQL> insira nos valores test_tab (10);

1 linha criada.

SQL>

/

insira em valores test_tab (10) *

ERRO na linha 1:ORA-00001:restrição exclusiva (PEASLAND.SYS_C00767176) violada

Ops! A primeira inserção funcionou (criada 1 linha), mas quando a barra foi inserida, o SQL*Plus tentou inserir os mesmos dados e fui pego em uma violação de restrição exclusiva.

Conclusão


Felizmente, esta página mostra por que a barra é necessária, o que ela faz e quando não usá-la. Para recapitular:
  • Inclua a barra no final de cada bloco PL/SQL
  • Não inclua a barra após nenhuma instrução SQL que não esteja em um bloco PL/SQL.
  • A barra após uma única instrução SQL fará com que o comando SQL seja executado duas vezes.