Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
onde sero processados. Eles tambm so conhecidos como funes, este o motivo pelo qual quando nos referenciamos a uma stored procedure no PostgreSQL devemos utilizar o nome de Function. O PostgreSQL conta com trs formas diferentes de criar funes: - Funes em Linguagem SQL: So funes que utilizam a sintaxe SQL e se caracterizam por no possuirem estruturas de condio (if, else, case), estruturas de repetio (while, do while, for), no permitirem a criao de variveis e utilizam sempre algum dos seguintes comandos SQL: SELECT, INSERT, DELETE ou UPDATE. - Funes de Linguagens Procedurais: ao contrrio das funes SQL, aqui permitido o uso de estruturas de condio e repetio e o uso de variveis. As funes em linguagens procedurais caracterizam-se tambm por no possuirem apenas uma possibilidade de linguagem, mas vrias. Normalmente a mais utilizada conhecida como PL/PgSQL, linguagem fortemente semelhante ao conhecido PL/SQL utilizado no Oracle. - Funes em Liguagens Externas ou de Rotinas Complexas: So funes normalmente escritas em C++ que trazem consigo a vantagem de utilizarem uma linguagem com diversos recursos, na qual pode-se implementar algoritmos com grande complexidade. Tais funes so empacotadas e registradas no SGBD para seu uso futuro. Para criar uma funo utilizando SQL no PostgreSQL utiiza-se o comando CREATE FUNCTION, da seguinte forma: CREATE [ OR REPLACE ] FUNCTION nome ( [ tipo_do_parametro1 [, ...] ] ) RETURNS tipo_retornado AS ' Implementao_da_funo; ' LANGUAGE 'SQL'; Na qual CREATE FUNCTION o comando que define a criao de uma funo, [OR REPLACE] informa que se acaso existir uma funo com este nome, a atual funo dever sobrescrever a antiga. RETURNS tipo_retornado informa o tipo de dado que ser retornado ao trmino da funo. Tais tipos de retornos so os convencionais como o INTEGER, FLOAT, VARCHAR, etc. As funes em SQL tambm permitem o retorno de mltiplos valores e para isso informa-se como retorno SETOF. Implementao_da_funo, como o nome mesmo diz, traz as linhas de programao para a implementao da stored procedure. LANGUAGE est avisando qual linguagem em que est sendo implementada a funo. Quando passamos parmetros funo, no utilizamos nome nas variveis que esto dentro dos parnteses da assinatura da funo. Utilizamos apenas separados por vrgulas, o tipo da varivel de parmetro. Para acessarmos o valor de tais parmetros, devemos utilizar o '$' mais o nmero da posio que ocupa nos parmetros, seguindo a ordem da esquerda para a direita: CREATE FUNCTION soma(INTEGER, INTEGER) RETURNS INTEGER AS ' SELECT $1 + $2; ' LANGUAGE 'SQL';
Outro detalhe importante o fato de que as funes utilizando SQL sempre retornam valor, o que faz com que seja sempre necessrio que a ltima linha de comando da funo utilize o comando SELECT. CREATE FUNCTION cubo(INTEGER) RETURNS FLOAT AS ' SELECT $1 ^ 3; ' LANGUAGE 'SQL'; Quando desejar excluir uma funo do sistema utilize o comando: DROP FUNCTION nome_da_funcao(); Para excluir uma funo necessrio passar toda a sua assinatura: DROP FUNCTION nome_da_funcao(INTEGER); Ainda existe o fato que no momento da excluso voc pode excluir a funo passando mais um parmetro, como no exemplo a seguir: DROP FUNCTION totalNota(INTEGER) RESTRICT; ou DROP FUNCTION totalNota(INTEGER) CASCADE; Digite a funo abaixo no PostGres, no mesmo local onde se digita os comandos SQL.
Caso tenha obtido alguma mensagem de erro, preciso preparar o postgres para executar a linguagem plpgsql. Neste caso deve-se cadastrar no item LANGUAGES do POSTGRES a linguagem PSPGSQL. Veja figura.
Cada Sistema Gerenciador de Banco de Dados pode tratar as linguagens de forma diferente, aqui estamos configurando o POSTGRESQL para interpretar as FUNCTIONS. Caso sua funo tenha retornado o valor esperado, sinal de que voc j pode efetuar alguns exemplos, veja abaixo: Obs.: Digite todas os COMANDOS abaixo e os execute, pea ajuda ao professor se necessrio. CREATE TABLE genero ( id numeric(5) NOT NULL, nome varchar(100), CONSTRAINT genero_pkey PRIMARY KEY (id) ); CREATE TABLE filme ( nome varchar(100), duracao varchar(100), sinapse varchar(2000),
id numeric(5) NOT NULL, genero numeric(5), data timestamp, CONSTRAINT fk_genero_filme FOREIGN KEY (genero) REFERENCES genero (id) ON UPDATE NO ACTION ON DELETE NO ACTION );
CREATE FUNCTION duracao_filme(INTEGER) RETURNS VARCHAR AS 'SELECT duracao FROM filme WHERE id = $1;' LANGUAGE 'SQL';
select duracao_filme(1);
CREATE FUNCTION filmes_genero(integer) RETURNS SETOF varchar AS 'SELECT nome FROM filme WHERE genero = $1;' LANGUAGE 'SQL';
select filmes_genero(1);
RAISE NOTICE 'Minha primeira rotina em PL/pgSQL'; RETURN; END; $body$ LANGUAGE 'plpgsql';
select primeira_funcao();
CREATE OR REPLACE FUNCTION primeira_funcao(integer,integer) RETURNS integer AS $body$ declare soma integer; BEGIN RAISE NOTICE 'Minha primeira rotina em PL/pgSQL'; soma:=$1+$2; RETURN(soma); END; $body$ LANGUAGE 'plpgsql';
$body$ declare soma integer; BEGIN RAISE NOTICE 'Minha primeira rotina em PL/pgSQL'; if $1 > $2 then soma:=$1-$2; else soma:=$2-$1; end if; RETURN(soma); END; $body$ LANGUAGE 'plpgsql'; select * from primeira_funcao(5,1);
CREATE OR REPLACE FUNCTION primeira_funcao(n1 integer,n2 integer) RETURNS integer AS $body$ declare soma integer; BEGIN RAISE NOTICE 'Minha primeira rotina em PL/pgSQL'; if n1 > n2 then soma:=n1-n2; else
-- Argumentos -- Tipo de verificacao : 0 (PJ), 1 (PF) e 2 (Livre) pTipo ALIAS FOR $1; -- Numero do documento pNumero ALIAS FOR $2;
-- Variaveis i INT4; -- Contador iProd INT4; -- Somatrio iMult INT4; -- Fator iDigito INT4; -- Digito verificador calculado sNumero VARCHAR(20); -- numero do docto completo
BEGIN
-- verifica Argumentos validos IF (pTipo < 0) OR (pTipo > 2) THEN RETURN -1; END IF;
-- se for Livre, nao eh necessario a verificacao IF pTipo = 2 THEN RETURN 1; END IF;
sNumero := trim(pNumero); FOR i IN 1..char_length(sNumero) LOOP IF position(substring(sNumero, i, 1) in '1234567890') = 0 THEN RETURN -2; END IF; END LOOP; sNumero := '';
iMult := 2; iProd := 0;
FOR i IN REVERSE 12..1 LOOP iProd := iProd + to_number(substring(sNumero from i for 1),'9') * iMult; IF iMult = 9 THEN iMult := 2; ELSE iMult := iMult + 1; END IF; END LOOP;
FOR i IN REVERSE 13..1 LOOP iProd := iProd + to_number(substring(sNumero from i for 1),'9') * iMult; IF iMult = 9 THEN iMult := 2; ELSE iMult := iMult + 1;
FOR i IN 1..9 LOOP iProd := iProd + (to_number(substring(sNumero from i for 1),'9') * (11 - i)); END LOOP; iDigito := 11 - (iProd % 11); IF (iDigito) >= 10 THEN iDigito := 0; END IF;
-- segundo digito iProd := 0; FOR i IN 1..10 LOOP iProd := iProd + (to_number(substring(sNumero from i for 1),'9') * (12 - i)); END LOOP; iDigito := 11 - (iProd % 11); IF (iDigito) >= 10 THEN iDigito := 0; END IF; sNumero := substring(sNumero from 1 for 10) || trim(to_char(iDigito,'9'));
END IF;
-- faz a verificacao do digito verificador calculado IF pNumero = sNumero::bpchar THEN RETURN 1; ELSE RETURN -3; END IF; END; $BODY$ LANGUAGE 'plpgsql' VOLATILE;
Aps a digitao desta Funo escreva: SELECT f_cnpjcpf( 1, '12312312345' ); Verifique que o CPF invlido e desta maneira o registro no ser inserido. SELECT f_cnpjcpf( 1, 'Digite seu CPF' );
Vamos fazer uma tabela que faz uma condio para uma funo, digite a funo abaixo: Crie a tabela abaixo e verifique que em um dos CONSTRAINTS a funo chamada. drop table cadastro; CREATE TABLE cadastro ( id integer NOT NULL, nome character varying(50) NOT NULL, tipopessoa smallint NOT NULL, cpfcnpj character(20) NOT NULL, CONSTRAINT cadastro_pkey PRIMARY KEY (id), CONSTRAINT cadastro_check CHECK (f_cnpjcpf(tipopessoa::integer, cpfcnpj) = 1), CONSTRAINT cadastro_tipopessoa_check CHECK (tipopessoa = ANY (ARRAY[1, 2])) ); Vamos fazer uma funo que retorne um RecordSet, veja abaixo: drop function getcadastro(text); CREATE OR REPLACE FUNCTION getcadastro(text) RETURNS SETOF cadastro AS $BODY$ SELECT * FROM cadastro WHERE nome LIKE $1 || '%'; $BODY$ LANGUAGE 'sql' VOLATILE; Neste exemplo abaixo, podemos verificar que a funo faz o INSERT, basta que passemos os parmetros para ela. drop function insert_cadastro(integer,text,smallint,text); CREATE OR REPLACE FUNCTION insert_cadastro(integer,text,smallint,text) RETURNS text as $$ DECLARE valor1 ALIAS FOR $1;
valor2 ALIAS FOR $2; valor3 ALIAS FOR $3; valor4 ALIAS FOR $4; Begin INSERT INTO cadastro VALUES ($1,$2,$3,$4); return 'Sucesso!'; end; $$LANGUAGE 'plpgsql' volatile called ON NULL input security invoker; select insert_cadastro(11,'oi','2','123'); select getcadastro('o'); Ob.: Faa quantas vezes for necessrio cada exemplo, at entender como as coisas funcionam.
CREATE TABLE usuarios (nome varchar(30), senha char(32)); CREATE FUNCTION md5_senha() RETURNS TRIGGER AS $body$ BEGIN NEW.senha := md5(NEW.senha); RETURN NEW; END; $body$ LANGUAGE 'plpgsql';
usuarios FOR EACH ROW EXECUTE PROCEDURE md5_senha(); INSERT INTO usuarios VALUES ('usuario', 'senha'); SELECT * FROM usuarios;
Agora implementar um exemplo real: Vamos imaginar que voc possua uma loja de Ferragens e queira controlar o estoque de seus produtos, porm de desejo seu que o apontamento de movimentaes seja feito atravs do Bando de Dados a cada insero de Sada de Produto. drop table produtos; create table produtos ( id serial primary key, descricao varchar(30), qtd_estoque integer ); select * from produtos;
insert into produtos (descricao,qtd_estoque) values ('Parafuso',100); insert into produtos (descricao,qtd_estoque) values ('Porca',100); insert into produtos (descricao,qtd_estoque) values ('Arruela',100); insert into produtos (descricao,qtd_estoque) values ('Chave de Fenda',100); insert into produtos (descricao,qtd_estoque) values ('Chave de Boca',100); insert into produtos (descricao,qtd_estoque) values ('Chave Alen',100); insert into produtos (descricao,qtd_estoque) values ('Parafuso 3/4',100); insert into produtos (descricao,qtd_estoque) values ('Lana',100); insert into produtos (descricao,qtd_estoque) values ('Martelo',100); insert into produtos (descricao,qtd_estoque) values ('Colher de Pedreiro',100);
id serial primary key, id_produtos integer references produtos, tipo_es integer, qtd integer, data date, hora time );
Desta forma que est , deveramos dar baixa no estoque executando um UPDATE.
Assim mantemos o estoque atualizado, no mesmo: Porm, seria interessante que o Banco fizesse esta tarefa automaticamente Ento vamos criar um Funo que faa este trabalho para ns
$$
return new;
end; $$ language 'plpgsql'; create trigger tr_faz_movimento after insert or update or delete on movimento_estoque for each row execute procedure faz_movimento(); Agora, quando fizer uma insero na tabela de movimentos, o Banco de Dados executar a funo passando o registro atual (NEW) como parmetros para a funo que efetuar a baixa automtica na tabela Produtos. Vamos por a mo na Massa.
Trabalho para Nota valendo 5 pontos, na P2, os outro 5 pontos sero da P1. OBS.: Trabalhos que sejam iguais, ou contenham partes de outros trabalhos sero anulados.
Deve-se realizar um trabalho em grupo de 3 pessoas, que satisfaa os seguintes requisitos da empresa Bom de Servio. 1- Uma empresa de Cosmticos necessita de seu apoio para resolver a modelagem de seu sistema, porm opta por ter as regras de seu negcio dentro de um SGBD. Sendo assim ela necessita que voc modele e crie as regras de negcio usando PLPGSQL, e que satisfaa os seguintes requisitos. Obs.: No se apegue a detalhes. a. Todos os vendedores devem possuir CPF vlido. b. Todos os vendedores devem possuir mais que 18 anos. c. Todos os produtos devem ser mantidos em estoque, desta forma deve-se manter o estoque atualizado. d. Caso seja feito uma venda e um dos produtos esteja em falta este item deve ser anulado. e. Um vendedor pode enxergar os campos referentes aos produtos, porm o campo custo do produto no pode ser exibido. f. No permitido a venda de mais de 50 produtos iguais por pedido por vendedor por ms. g. Cada item pedido deve-se computar 5% do valor do item como comisso para o vendedor. h. Deve-se emitir uma ficha contendo todos os pedidos feitos pelo vendedor dizendo o nmero do pedido o total e a comisso lanada. Desta forma o vendedor sabe quanto ele vai receber. Este trabalho tem como objetivo melhorar a capacidade de informatizar processos usando como ferramenta gerenciadora o Banco de dados e suas funcionalidades.