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

Sign in to follow this  
Baderous

MySQL Trigger

Recommended Posts

Baderous

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.

Share this post


Link to post
Share on other sites
Baderous

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 ) ;

$$

Share this post


Link to post
Share on other sites
TheDark

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;


Desaparecido.

Share this post


Link to post
Share on other sites
Baderous

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

Share this post


Link to post
Share on other sites
TheDark

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.


Desaparecido.

Share this post


Link to post
Share on other sites
Baderous

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;

Share this post


Link to post
Share on other sites
TheDark

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...


Desaparecido.

Share this post


Link to post
Share on other sites
mAiN_iNfEcTiOn

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 ;)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.