2013-03-08 9 views
30

Sto eseguendo una query MySQL. Ma quando una nuova riga viene aggiunta dall'input forma ottengo questo errore:Errore MySql: impossibile aggiornare la tabella in funzione/trigger memorizzati perché è già utilizzata dall'istruzione che ha invocato questa funzione/trigger memorizzato

Error: Can't update table 'brandnames' in stored function/trigger because it is 
already used by statement which invoked this stored function/trigger. 

Dal codice:

CREATE TRIGGER `capital` AFTER INSERT ON `brandnames` 
FOR EACH 
ROW UPDATE brandnames 
SET bname = CONCAT(UCASE(LEFT(bname, 1)) , LCASE(SUBSTRING(bname, 2))) 

Che cosa significa questo errore?

+0

quello che stai cercando di fare con il grilletto? Lo schema della tabella, i dati di esempio e la query INSERT di esempio aiuterebbero molto – Steve

+0

Voglio cambiare il caso in maiuscolo di un valore di riga invulnerato. Quindi voglio che questo trigger lo faccia automaticamente ogni volta che viene inserita una riga. Non voglio javascript. –

+0

@EricLeschinski Non so cosa abbia fatto su quella domanda. –

risposta

51

Non è possibile modificare un tavolo mentre il trigger INSERT sta sparando. L'INSERT potrebbe eseguire un blocco che potrebbe causare un deadlock. Inoltre, l'aggiornamento della tabella da un trigger causerebbe l'attivazione dello stesso trigger in un loop ricorsivo infinito. Entrambi questi motivi sono il motivo per cui MySQL ti impedisce di farlo.

Tuttavia, in base a ciò che si sta tentando di ottenere, è possibile accedere ai nuovi valori utilizzando NEW.fieldname o anche i vecchi valori - se si esegue un UPDATE - con OLD.

Se tu avessi una riga denominata full_brand_name e si voleva utilizzare le prime due lettere come nome breve nel campo small_name si potrebbe usare:

CREATE TRIGGER `capital` BEFORE INSERT ON `brandnames` 
FOR EACH ROW BEGIN 
    SET NEW.short_name = CONCAT(UCASE(LEFT(NEW.full_name,1)) , LCASE(SUBSTRING(NEW.full_name,2))) 
END 
+1

Come indicato in un'altra domanda SO (http://stackoverflow.com/questions/1582683/mysql-trigger -stored-trigger-is-already-used-by-statement-which-invoked-stored-t), MySQL non supporta (ancora?) questa funzione (http://forums.mysql.com/read.php? 99,122354,240978 # msg-240978), anche se i suoi concorrenti lo fanno. –

+1

Ha perfettamente senso @Steve! –

+0

@Steve Sto ricevendo lo stesso problema. quando sto provando: update employee_audit set lastName = 'Sharma' dove employeeNumber = 112; –

4

La sintassi corretta è:

FOR EACH ROW SET NEW.bname = CONCAT(UCASE(LEFT(NEW.bname, 1)) 
            , LCASE(SUBSTRING(NEW.bname, 2))) 
+0

MySQL dice: L'aggiornamento della nuova riga non è consentito dopo l'attivazione. :( –

+1

Spiacente, è necessario modificarlo da DOPO INSERIMENTO a PRIMA DI INSERISCI, come nella risposta di Steve – rsanchez

+0

Ha funzionato :) Grazie –

2

Ho lo stesso problema e di risolverlo da aggiungere "nuova ". prima che il campo sia aggiornato. E ho posto pieno grilletto qui che qualcuno voglia di scrivere un trigger

DELIMITER $$ 

USE `nc`$$ 

CREATE 
    TRIGGER `nhachung_province_count_update` BEFORE UPDATE ON `nhachung` 
    FOR EACH ROW BEGIN 

    DECLARE slug_province VARCHAR(128); 
    DECLARE slug_district VARCHAR(128); 

    IF old.status!=new.status THEN /* neu doi status */ 
     IF new.status="Y" THEN 
      UPDATE province SET `count`=`count`+1 WHERE id = new.district_id; 
     ELSE 
      UPDATE province SET `count`=`count`-1 WHERE id = new.district_id; 
     END IF; 
    ELSEIF old.province_id!=new.province_id THEN /* neu doi province_id + district_id */ 

     UPDATE province SET `count`=`count`+1 WHERE id = new.province_id; /* province_id */ 
     UPDATE province SET `count`=`count`-1 WHERE id = old.province_id; 
     UPDATE province SET `count`=`count`+1 WHERE id = new.district_id; /* district_id */ 
     UPDATE province SET `count`=`count`-1 WHERE id = old.district_id; 

     SET slug_province = (SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1); 
     SET slug_district = (SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1); 
     SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district); 

    ELSEIF old.district_id!=new.district_id THEN 

     UPDATE province SET `count`=`count`+1 WHERE id = new.district_id; 
     UPDATE province SET `count`=`count`-1 WHERE id = old.district_id; 

     SET slug_province = (SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1); 
     SET slug_district = (SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1); 
     SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district); 

    END IF; 


    END; 
$$ 

DELIMITER ; 

Spero che questo aiuto qualcuno

1

un "prima-INSERT" -trigger è l'unico modo per realizzare gli aggiornamenti dello stesso tavolo su un inserto ed è possibile solo da MySQL 5.5+. Tuttavia, il valore di un campo di autoincremento è disponibile solo per un trigger "AFTER-INSERT" - esso assume come valore predefinito 0 nel caso BEFORE. Pertanto, il seguente codice di esempio che impostare un valore chiave surrogata precedentemente calcolata sulla base del valore di incremento automatico id compilerà, ma in realtà non funzionare in quanto NEW.id sarà sempre 0:

create table products(id int not null auto_increment, surrogatekey varchar(10), description text); 
create trigger trgProductSurrogatekey before insert on product 
for each row set NEW.surrogatekey = 
    (select surrogatekey from surrogatekeys where id = NEW.id); 
Problemi correlati