Escolar Documentos
Profissional Documentos
Cultura Documentos
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) );
ID
NM_LOGIN
DS_SENHA
FG_BLOQUEADO
NU_TENTATIVA_LOGIN
1 2 3
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; $$
ID
NM_LOGIN
DS_SENHA
FG_BLOQUEADO
NU_TENTATIVA_LOGIN
1 2 3
1 0 2
Como foi passada a senha errada, o nmero de tentativas foi incrementado em 1. Caso seja executado a SQL:
ID
NM_LOGIN
DS_SENHA
FG_BLOQUEADO
NU_TENTATIVA_LOGIN
1 2 3
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
0 0 3
Teremos o valor da coluna nu_tentativa_login alterado para ZERO, pois desta vez o valor do campo senha estava correto.
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';
indica que todas as colunas recebero algum valor. Voc precisa especificar quais colunas estar valorando.
view plaincopy to clipboardprint?
1.
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
$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;
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;