• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Baderous

MySQL Trigger

9 mensagens neste tópico

Estou a tentar fazer um trigger em que, após inserir um registo numa tabela, insiro noutra tabela alguns dados sobre esse último registo.

Já tentei de 2 maneiras e não consigo resolver:

//Versão 1
CREATE TRIGGER trg_historico AFTER INSERT ON ficheiros
FOR EACH ROW BEGIN
	DECLARE utilizador VARCHAR;
	DECLARE date TIMESTAMP;
	DECLARE nome VARCHAR;
	SELECT username INTO utilizador FROM ficheiros WHERE id_ficheiro = (SELECT MAX(id_ficheiro) FROM ficheiros);
	SELECT date INTO date FROM ficheiros WHERE id_ficheiro = (SELECT MAX(id_ficheiro) FROM ficheiros);
	SELECT name INTO nome FROM ficheiros WHERE id_ficheiro = (SELECT MAX(id_ficheiro) FROM ficheiros);
	INSERT INTO historico (username,date,name) VALUES (utilizador,date,nome);
END;

//Versão 2
CREATE TRIGGER trg_historico AFTER INSERT ON ficheiros
FOR EACH ROW
	BEGIN
		SELECT username,data,name INTO historico (username,data,name) FROM ficheiros WHERE id_ficheiro = (SELECT MAX(id_ficheiro) FROM ficheiros);
	END;

A tabela "histórico" possui os campos:

- id_historico

- username

- data

- nome

A tabela "ficheiros" possui, entre outros, os seguintes campos:

- id_ficheiro

- username

- data

- name

Na versão 1 o erro que dá é: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3 .

Na versão 2 é: #1327 - Undeclared variable: historico . Acho estranho ele dizer isto, porque no w3schools diz que o que vem a seguir ao INTO é o nome de uma tabela, mas o que é certo é que já vi exemplos, quer em MySQL quer em Oracle, e realmente, o que aparece a seguir ao INTO é uma variável.  :bored:

Agradecia uma mãozinha.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já consegui fazer:

DELIMITER $$ CREATE TRIGGER trg_historico AFTER  INSERT  ON ficheiros
FOR EACH
ROW 
INSERT  INTO historico( username, 
DATA , name ) 
SELECT username, 
DATA , name
FROM ficheiros
WHERE id_ficheiro = ( 
SELECT MAX( id_ficheiro ) 
FROM ficheiros ) ;

$$

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Isso não funciona lá muito bem se houver concorrência no SGBD, ou se forem introduzidos mais que um registo. Porque não utilizas a tabela INSERTED?

INSERT INTO historico(username, DATA, name)
SELECT username, DATA, name FROM INSERTED;

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O que é suposto ser a tabela INSERTED? É uma segunda tabela onde também coloco ficheiros?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não, é uma tabela que contém os dados que foram inseridos. Tem a mesma estrutura que a tabela sobre a qual foi feito o insert.

EDIT: parece que a tabela INSERTED se chama NEW no MySQL. Não tinha reparado que estás a usar MySQL. INSERTED é do MSSQL.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Refiz o trigger de acordo com a tua sugestão e ficou assim:

CREATE TRIGGER `filesbd`.`trg_historico` AFTER INSERT ON `filesbd`.`ficheiros`
FOR EACH ROW INSERT INTO historico( username,
DATA , name )
SELECT username,
DATA , name
FROM ficheiros
WHERE id_ficheiro = NEW.id_ficheiro;

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Parece que ficou um bocadinho mais bonito ;)

Não sabia que era preciso o FOR EACH ROW. Nunca tinha utilizado triggers em MySQL. Também já não mexo a sério em MySQL há anos...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

No MySQL se faz assim:

//*********************

SET NEW.campo = valor;

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Refiz o trigger de acordo com a tua sugestão e ficou assim:

CREATE TRIGGER `filesbd`.`trg_historico` AFTER INSERT ON `filesbd`.`ficheiros`
FOR EACH ROW INSERT INTO historico( username,
DATA , name )
SELECT username,
DATA , name
FROM ficheiros
WHERE id_ficheiro = NEW.id_ficheiro;

Nem sei para que é que a MySQL/Oracle força o uso de FOR EACH ROW... sendo um trigger que executa ao ser inserida uma linha, é óbvio que é para cada linha, não? A não ser que o scope do trigger é por instrução-'INSERT' em vez de linha inserida.... porque aí pode haver múltiplos inserts numa instrução ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora