Você está na página 1de 7

Postgresql Funes

Neste post, veremos as funes (FUNCTIONS ou PROCEDURES), um recurso muito importante quando estamos falando de bancos de dados. Cada banco de dados implementa funes de uma forma um pouco diferente uns dos outros. Para os exemplos aqui listados, veremos como funciona as funes no SGBD PostgreSQL. Funes (ou procedimentos) so trechos de cdigo que ficam armazenados dentro do banco de dados. Da mesma forma que existem funes prontas no banco de dados (exemplo: SUM, AVG, MAX), podemos criar nossas prprias funes. Para o Postgresql, o mesmo suporta muitos tipos de linguagem para a criao de funes dentro do banco de dados. Aqui veremos a linguagem PL/pgSQL, que a mais utilizada. A sintaxe para a criao de uma nova funo ou procedimento (de forma simplificada):

1 CREATE OR REPLACE FUNCTION nome_da_funcao ( parametros ) 2 RETURNS tipo_retorno AS 3 $$ 4 DECLARE --declaracao de variaveis 5 BEGIN 6 --conteudo da funcao 7 END; 8 $$ LANGUAGE linguagem; 9 Exemplo prtico: Temos a seguinte tabela no banco de dados: 1 2 3 4 5 6 7 8 Na
CREATE TABLE usuario ( id integer NOT NULL, nm_login character varying, ds_senha character varying, fg_bloqueado boolean, nu_tentativa_login integer, CONSTRAINT pk_usuario PRIMARY KEY (id) );

tabela usuario, temos os seguintes dados:

ID

NM_LOGIN

DS_SENHA

FG_BLOQUEADO

NU_TENTATIVA_LOGIN

1 2 3

hallan joao maria

hallan2011 123456 abcd1234

False False False

0 0 2

Um exemplo bsico de uma funo seria criar uma funo onde passamos o login do usurio e queremos que a funo retorne o seu ID. Apesar de ser um exemplo sem muito sentido, servir de base para o prximo exemplo. Podemos criar, ento, a funo da seguinte forma:

1 CREATE OR REPLACE FUNCTION get_id ( varchar ) RETURNS integer AS 2 $$ 3 DECLARE 4 variavel_id INTEGER; BEGIN 5 SELECT INTO variavel_id id FROM usuario WHERE nm_login = $1; 6 RETURN variavel_id; 7 END; 8 $$ LANGUAGE 'plpgsql'; 9 A funo acima (chamada get_id) recebe como parmetro um VARCHAR e retorna um INTEGER, e funciona da seguinte forma: - declara uma varivel chamada variavel_id, do tipo INTEGER; - faz um select na tabelas de usurio onde a coluna nm_login igual ao varchar recebido como parmetro, e colocar o valor de id encontrado dentro da varivel variavel_id (atravs do comandoSELECT INTO); - retorna a variavel_id. O $1 representa o primeiro parmetro recebido, o $2 o segundo, e assim por diante.
Agora, se executarmos a seguinte instruo SQL:
SELECT get_id( 'joao' ); 1 teremos o seguinte resultset:

GET_ID

2 Um exemplo mais complexo Vamos supor que queremos agora criar uma regra que, se o usurio entrar com a senha errada trs vezes seguidas, ele deve ser bloqueado. A coluna fg_bloqueado mostra se o usurio est bloqueado ou no, e a coluna nu_tentativa_login mostra quantas vezes seguidas este usurio inseriu sua senha errada. Exemplo: se um usurio que tem o nmero de tentativas (coluna nu_tentativa_login) = 1 entrar com sua senha errada, o numero de tentativas dever ser alterado para 2. Caso entre novamente com a senha errada, o nmero de tentativas dever ser alterado para 3 E a coluna fg_bloqueado dever ser alterada para TRUE. Caso um usurio com o nmero de tentativas = 2 tenha entrado com a senha correta, o valor do nmero de tentativas dever voltar a ser 0. Toda esta lgica pode ser implementada diretamente no banco de dados, atravs de uma funo. SIM! Vejamos a seguinte funo:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

CREATE OR REPLACE FUNCTION set_tentativa_login ( VARCHAR, VARCHAR ) RETURNS VOID AS $$ DECLARE registro RECORD; tentativas INTEGER; BEGIN SELECT INTO registro id, fg_bloqueado, nu_tentativa_login FROM usuario WHE IF registro IS NULL THEN SELECT INTO tentativas nu_tentativa_login FROM usuario WHERE nm_login tentativas := tentativas + 1; IF tentativas > 2 THEN UPDATE usuario SET nu_tentativa_login = tentativas, fg_bloqueado ELSE UPDATE usuario SET nu_tentativa_login = tentativas where nm_login END IF; ELSE UPDATE usuario SET nu_tentativa_login = 0 where nm_login = $1; END IF; END; $$

20 21 LANGUAGE 'plpgsql'; 22 23 24 SIM!!!!!


possvel realizar estruturas de deciso e de repetio em funes de bancos de dados. Explicando um pouco: A funo set_tentativa_login recebe dois parmetros: um sendo o login e o outro a senha do usurio. Primeiro verificado se existe um usurio com o login e senha informado. O resultado colocado dentro de uma varivel do tipo RECORD, que representa um registro (com vrias colunas) de uma tabela. Caso exista o usurio, seu nmero de tentativas alterado para ZERO. Caso no exista, efetuada outra consulta, desta vez somente atravs de seu login. O nmero de tentativas armazenado na varivel tentativas, e este valor incrementado em 1. Alm de atualizar o nmero de tentativas, verificado se este valor maior que 2. Caso seja, altera o valor da coluna fg_bloqueado para TRUE. Na prtica: Utilizamos ento a seguinte instruo:
SELECT set_tentativa_login( 'hallan', 'senha_errada' ); 1 A tabela de usurios ficar da seguinte forma:

ID

NM_LOGIN

DS_SENHA

FG_BLOQUEADO

NU_TENTATIVA_LOGIN

1 2 3

hallan joao maria

hallan2011 123456 abcd1234

false false false

1 0 2

Como foi passada a senha errada, o nmero de tentativas foi incrementado em 1. Caso seja executado a SQL:

SELECT set_tentativa_login( 'maria', 'senha_errada' ); 1 A tabela de usurios ficar da seguinte forma:

ID

NM_LOGIN

DS_SENHA

FG_BLOQUEADO

NU_TENTATIVA_LOGIN

1 2 3

hallan joao maria

hallan2011 123456 abcd1234

false false true

1 0 3

Alm da senha, o usurio maria teve sua coluna fg_bloqueado alterado para TRUE. Por fim, se executarmos:
SELECT set_tentativa_login( 'hallan', 'hallan2011' ); 1 A tabela de usurios ficar da seguinte forma:

ID

NM_LOGIN

DS_SENHA

FG_BLOQUEADO

NU_TENTATIVA_LOGIN

1 2 3

hallan joao maria

hallan2011 123456 abcd1234

false false true

0 0 3

Teremos o valor da coluna nu_tentativa_login alterado para ZERO, pois desta vez o valor do campo senha estava correto.

possvel resolver muitas operaes complexas atravs de funes de bancos de dados.

Oii gente! tenho uma tabela Usurio:


view plaincopy to clipboardprint?

1. 2. 3. 4. 5. 6.

CREATE TABLE Usuario ( cod_u serial NOT NULL PRIMARY KEY, nome_u VARCHAR(30) NOT NULL, nick_u VARCHAR(10) NOT NULL, email_u VARCHAR(20) NOT NULL, pass_u VARCHAR(8) NOT NULL

7.

);

e quero fazer uma funo (uso o postgresql) para que insira um novo usurio, mas que verifique se o mesmo exista e retorne a password dele, estou com dvidas quanto aos parmetros, pois o cdigo serial, ai no sei se devo passar ele ou no na funo.
view plaincopy to clipboardprint?

1. 2. 3. 4. 5. 6. 7. 8. 9.

CREATE OR REPLACE FUNCTION inserir_usuario (varchar(30), varchar(10), varchar(20), varchar(8)) RETURNS integer AS $body$ BEGIN insert into Usuario values ($1,$2,$3,$4); END; $body$

LANGUAGE 'plpgsql';

Isso por que a query 1.

view plaincopy to clipboardprint?

insert into Usuario values ($1,$2,$3,$4);

indica que todas as colunas recebero algum valor. Voc precisa especificar quais colunas estar valorando.
view plaincopy to clipboardprint?

1.

insert into Usuario (col2, col3, col4, col5) values ($1,$2,$3,$4);

Isso se e apenas se, o codigo for gerenciado pelo banco, seno, ou voc trata isso na aplicao ou cria uma outra forma de gerar o cdigo dentro da procedure.

ai fiz assim, e aparentemente funcionou, ele acusa quando tem algum usuario igual(compara o nicki e o email) e retorna na tela isso: NOTA: ja existe ERRO: controle atingiu o fim da funo sem RETURN CONTEXT: funo PL/pgSQL "inserir_usuario" Olha como ficou:
view plaincopy to clipboardprint?

1. 2.

CREATE OR REPLACE FUNCTION inserir_usuario (varchar(30), varchar(10), varchar(20), varchar(8)) RETURNS integer AS

3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.

$body$ DECLARE existe integer; BEGIN existe:=0; SELECT count(*) INTO ecount FROM Usuario WHERE nick_u=$2 AND email_u=$3; if existe=0 then INSERT INTO Usuario (nome_u, nick_u, email_u, pass_u) VALUES ($1,$2,$3,$4); RETURN $4; else existe:=1; RAISE NOTICE 'ja existe'; end if;

16. END; 17. $body$ 18. 19. LANGUAGE 'plpgsql';

Obrigada mais uma vez, ajudou muito, agora eu queria fazer uma outra funo, uma para mudar a password do usuario, mas to com dvida se na hora de executar a funo o usuario iria entrar com a nova password ou com todos os campos.
view plaincopy to clipboardprint?

1. 2. 3. 4. 5. 6. 7. 8. 9.

CREATE OR REPLACE FUNCTION atualizar_usuario(varchar(8)) RETURNs integer AS $BODY$ declare pass varchar(8); BEGIN update Usuario set pass_u = pass where pass_u = $1; return $1; END;

10. $BODY$ 11. LANGUAGE 'plpgsql';

Você também pode gostar