Introdução a plsql

Propaganda
PL/SQL
PL/SQL (acrônimo para a expressão inglesa Procedural Language/Structured Query Language) é uma
extensão da linguagem padrão SQL primeiramente criada para o SGBD Oracle da Oracle Corporation.
É uma Linguagem Procedural da Oracle, estendida da SQL.
Permite que a manipulação de dados seja incluída em unidades de programas. Blocos de PL/SQL são
passados e processados por uma PL/SQL Engine que pode estar dentro de uma ferramenta de
desenvolvimento de aplicações ou no SGBD. A PL/SQL Engine filtra os comandos SQL e manda
individualmente o comando SQL para o SQL Statement Executor no SGBD, que processa o PL/SQL
com os dados retornados do SGBD.
É a linguagem básica para criar programas complexos e poderosos, não só no banco de dados, mas
também em diversas ferramentas Ligadas ao SGBD.
Antes de 1991 a única forma de usar construções procedurais com o SQL era usar PRO*C. Foi onde as
instruções SQL do Oracle foram embutidas em código na linguagem “C”. O código “C” era précompilado para converter as instruções SQL em chamadas de bibliotecas.
Em 1991 o PL/SQL 1.0 foi lançado com o Oracle Versão 6.0. Ele era muito limitado nas suas
capacidades.
A unidade básica em PL/SQL é um bloco. Todos os programas em PL/SQL são compostos por blocos,
que podem estar localizados uns dentro dos outros. Geralmente, cada bloco efetua uma ação lógica no
programa. Um bloco tem basicamente a seguinte estrutura para SGBDs Oracle:
DECLARE
Seção para declaração de variáveis,tipos e subprogramas locais.
BEGIN
Seção Executável, nesta seção ficam as instruções procedurais e SQL. Esta é a única seção do bloco que é indispensável e
obrigatória.
EXCEPTION
Seção/Setor onde ficam as instruções de tratamento de erro.
END
Procedures
Uma procedure nada mais é que um bloco PL/SQL nomeado. A grande vantagem sobre um bloco
PL/SQL anônimo é que pode ser compilado e armazenado no banco de dados como um objeto de
schema. Graças a essa característica as procedures são de fácil manutenção, o código é reutilizável e
permitem que trabalhemos com módulos de programa.
Uma procedure é, então, um bloco PL/SQL nomeado que pode aceitar argumentos (também chamado
de parâmetros) e pode ser chamada por um programa, uma sessão SQL ou uma trigger.
Durante a instalação do banco de dados Oracle um script é executado automaticamente e cria toda a
estrutura necessária para que as procedures sejam executadas. Eventualmente esse procedimento automático pode
falhar devido a alguma falha física no disco rígido, nesse caso o usuário SYS pode recriar a estrutura através do
script SQL DBMSSTDX.SQL.
Para criar uma procedure o usuário precisa ter o privilégio de sistema CREATE PROCEDURE, para
criar a procedure em outros schemas (Banco de dados) o usuário deve ter o privilégio de CREATE ANY
PROCEDURE. Este é um ponto muito interessante sobre as procedures, os privilégios para criação de
procedures têm que concedidos explicitamente, ou seja, não pode ser adquirido através de roles
(usuários comuns).
Para executar uma procedure externa é necessário ter o privilégio de EXECUTE. Caso queira alterar a
procedure de outro schema deve ter o privilégio de sistema ALTER ANY PROCEDURE.
A sintaxe básica de uma procedure no MYSQL é:
CREATE PROCEDURE proc_name([parameters, ...])
[characteristics]
[BEGIN]
corpo_da_rotina;
[END]
Explicando...
proc_name: seu procedimento armazenado deve ter um nome, para quando for chamado, podermos
então usá-lo;
tipo_param: existem 3 tipos de parâmetros em uma Stored Procedure no MySQL:



IN => este é um parâmetro de entrada, ou seja, um parâmetro cujo seu valor será utilizado no
interior do procedimento para produzir algum resultado;
OUT => esté parâmetro retorna algo de dentro do procedimento para o lado externo, colocando
os valores manipulados disponíveis na memória ou no conjunto de resultados;
INOUT => faz os dois trabalhos ao mesmo tempo!
parameters: nessa parte do procedimento, informaremos os parâmetros da seguinte forma: [IN | OUT |
INOUT] nome_parametro tipo_dado.
characteristics: as características do procedimento pode apresentar. Como não utilizaremos
inicialmente tais características, vamos nos ater a sintaxe principal. Questões de segurança, se é
determinística ou não, qual a linguagem que estamos utilizando e se nosso procedimento modificará
dados na banco de dados, são algumas das características que poderemos definir neste item que
abordaremos com mais detalhe na parte dois do artigo.
corpo_da_rotina: onde são definidos os comandos SQL que farão alguma manipulação e/ou defenderão
alguma lógica, podendo retornar ou não algum resultado.
Vamos ver um exemplo de procedure para ajudar nosso entendimento :
O Query Browser já nos deu quase tudo pronto para escrevermos somente os parâmetros que teremos
no nosso procedimento e o corpo da rotina. Notem que é utilizado o operador DELIMITER para mudar o
delimitador de comandos, que por padrão é o ";". Mudamos o DELIMITADOR para podermos usar o ";"
no meio do procedimento. Caso não efetuemos essa troca, o procedimento será enviado pela metade e
um erro será enviado ao terminal, por erro na sintaxe.
DELIMITADOR no MySQL, em outras situações, por padrão também é chamado de terminador. Para
verificar qual é o delimitador da sessão corrente emita o comando \s, que é a forma curta do comando
STATUS.
DELIMITER $$
DROP PROCEDURE IF EXISTES `banco`.`nomeproc`$$
CREATE PROCEDURE `banco`.`nomepreoc`( )
BEGIN
SELECT 'Olá!';
END$$
DELIMITER ;
Bem, procedimento compilado basta executarmos o procedimento com o seguinte comando:
CALL OLA();
OBS.: Após a versão 5.1.18, não é mais necessário os parênteses caso o procedimento não receba
parâmetros.
A resposta do procedimento será "OLÁ!" como definimos.
Bom, agora que já temos uma noção básica de como é implementado um procedimento armazenado
no MySQL, já podemos partir para aplicações do mundo real, tais como, manipular inserções de dados,
exclusões de registros e atualizações de linhas de uma ou mais tabelas. Tudo isso nos levará a aportar
lá na frente no conceito de transações, onde desenvolveremos um procedimento para simulação de
transferência de valor entre contas bancárias de mesma agência.
Como seria então, um procedimento para inserir dados em uma tabela do banco de dados?
Bom, antes de prosseguirmos, criaremos uma tabela, de nome correntista, que terá os campos
correntista_id do tipo INT, correntista_nome do tipo VARCHAR(60) e correntista_cpf do tipo
VARCHAR(20).
CREATE TABLE tbl_correntista (
correntista_id int auto_increment primary key,
correntista_nome varchar(60) not null unique,
correntista_cpf varchar(20) not null,
dt_cadastro timestamp default current_timestamp,
) Engine =InnoDB;
Pronto! Após executarmos o script acima nossa tabela estará criada e já poderemos dar carga através
de um procedimento armazenado, onde também utilizaremos em meio a este, estruturas condicionais,
IF-THEN-ELSE!
Com a nossa tabela criada, criaremos nosso procedimento para efetuar o INSERT dos dados, ou seja,
um procedimento para dar carga na tabela.
DELIMITER //
CREATE PROCEDURE correntistaInsert(v_nome VARCHAR(60), v_cpf VARCHAR(20))
BEGIN
IF ((v_nome != '') && (v_cpf != '')) THEN
INSERT INTO tbl_correntista (correntista_nome, correntista_cpf)
VALUES (v_nome, v_cpf);
ELSE
SELECT 'NOME e CPF devem ser fornecidos para o cadastro!' AS Msg;
END IF;
END;
//
Após compilarmos o procedimento, já poderemos chamá-lo através da declaração CALL, como se
segue:
CALL correntistaInsert('Wagner Bianchi', '023.456.789-10');
...notem que utilizamos em meio ao nosso procedimento de inserção, a estrutura condicional para
consistir o valor das variáveis. Caso os valores de ambas sejam vazios, a mensagem será disparada.
Faremos a seguir, um procedimento, com o mesmo formato para atualizarmos o registro da nossa
tabela "tbl_correntista", que até o momento encontra-se com um registro. Serão três agora, o
identificador do registro - v_id - , o novo nome do correntista “v_nome” e o novo cpf “v_cpf”.
DELIMITER //
CREATE PROCEDURE correntistaUpdate(v_id INT, v_nome VARCHAR(60), v_cpf VARCHAR(20))
BEGIN
IF (((v_id > 0) && (v_id != '') ) && (v_nome != '') && (v_cpf != '')) THEN
UPDATE tbl_correntista SET correntista_nome =v_nome, correntista_cpf = v_cpf
WHERE correntista_id =v_id;
ELSE
SELECT 'O novos NOME e CPF devem ser informados!' AS Msg;
END IF;
END;
//
Já podemos, após compilarmos o procedimento de UPDATE, atualizarmos nosso registro na tabela de
correntistas. Depois de compilado com sucesso, já podemos chamar nosso procedimento de
atualização e passar os parâmetros para atualizar o registro que temos na tabela.
CALL correntistaUpdate(1, 'Wagner MySQL Bianchi', '123.123.111-11');
Note que este procedimento poderá facilmente ser adaptado em qualquer sistema que receba o
identificador do registro a ser atualizado em uma tabela qualquer de um banco de dados.
Para finalizarmos, faremos um procedimento para excluir registros, que é o mais trivial de todos, basta
mais uma vez enviarmos o identificador do registro como parâmetro e efetuarmos a exclusão após a
conferência como estamos fazendo nos outros procedimentos.
Note que, em um sistema, você poderá implementar um único procedimento para exclusão de registros,
que receberá alguns parâmetros como o identificador, o nome da tabela e o nome da coluna, mas,
nesse momento, nos atentaremos para o simples, nos próximos artigos sofisticaremos um pouco mais
nossos procedimentos.
DELIMITER //
CREATE PROCEDURE correntistaDelete(v_id INT)
BEGIN
IF ((v_id > 0) && (v_id != '')) THEN
DELETE FROM tbl_correntista WHERE correntista_id =v_id;
ELSE
SELECT 'O identifiador do registro não foi informado!' AS Msg;
END IF;
END;
//
Agora já podemos excluir o registro que inserimos e atualizamos! Segue a sintaxe para isso:
CALL correntistaDelete(1);
Functions
Da mesma forma com que são criados os “Stored Procedures” são criadas as “Stored Functions”.
O que se difere entre os “Stored Procedures” das “Stored Functions” é que as “Stored Functions” tem
por definição retornar valores.
Veja neste exemplo como se faz uma “Stored Function” que retorna a media aritmética de quatro
números inteiros.
DELIMITER $$
CREATE FUNCTION `func_retorna_media` (n1 INT, n2 INT, n3 INT, n4 INT) RETURNS INT
BEGIN
DECLARE media INT;
SET media = (n1+n2+n3+n4)/4;
RETURN media;
END $$
DELIMITER ;
Já a chamada à esta função também é diferente do “Stored Procedure”:
SELECT func_retorna_media(10,0,10,0)
Para que se exclua uma Function ou um procedure, basta usar o seguinte comando:
DROP FUNCTION IF EXISTS `nome_da_funcao`;
DROP PROCEDURE IF EXISTS `nome_do_procedimento`;
Views
Basicamente VIEW é uma tabela virtual gerada a partir do resultado de uma instrução SELECT.
Uma VIEW contém linhas e colunas, como se fosse uma tabela real, os campos na VIEW são campos
obtidos em uma tabela de um banco de dados. E na VIEW pode-se chamar funções e cláusulas SQL
como WHERE e JOIN.
Obs: O projeto e a estrutura do banco de dados original não será alterado pelas funções utilizadas em
sua confecção, pelo WHERE, ou JOINs implementados na VIEW.
Um dos objetivos ao se implementar VIEWs é evitar a constante manutenção de códigos SQL em
aplicações, ou seja, pode-se implementar um SELECT * padrão na aplicação (que estará extraindo
dados previamente filtrados da VIEW) e controlar o que e como será mostrado diretamente do servidor,
alterando as características da VIEW.
A instrução para a criação de uma VIEW:
CREATE VIEW <nome da view> AS SELECT colunas(s)
FROM <tabela> WHERE <condição>
Exemplo:
CREATE VIEW comedias AS
SELECT *
FROM filmes
WHERE tipo = 'Comédia';
E uma VIEW pode ser removida.
A instrução para a remoção de uma VIEW:
DROP VIEW <nome da view>
O uso de VIEWs pode facilitar muito o trabalho do desenvolvedor, principalmente na manutenção das
informações que serão expostas, pois alterando apenas a VIEW no banco todos os clientes passarão a
contemplar a alteração.
Segue mais um exemplo de criação de uma View, agora com uma consulta aninhada???
CREATE VIEW `candidatos`.`pessoas_cidades` AS
SELECT
pesCodigo, pesNome, cidNome as cidMora, nasNome as cidNasceu
FROM
pessoas join
cidade join
(select cidCodigo as nasCodigo, cidNome as nasNome from cidade) nasci
WHERE
pes_cidCodigoMora = cidCodigo and
pes_cidCodigoNascimento = nasCodigo;
No MYSQL até a versão 5.0 não é possível criar uma view utilizando consulta aninhada!
Download