2013-03-08 25 views
30

我正在運行MySQL查詢。但是,當一個新的行從表單輸入添加我得到這個錯誤:MySql錯誤:無法更新存儲的函數/觸發器中的表,因爲它已被調用此存儲函數/觸發器的語句使用

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

從代碼:

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

這個錯誤是什麼意思?

+0

什麼是你想用你的觸發器做什麼?表架構,示例數據和示例INSERT查詢將幫助很多 – Steve 2013-03-08 18:22:50

+0

我想將案例更改爲enrered行值的大寫。所以我希望這個觸發器能夠在輸入一行時自動爲我執行此操作。我不想要JavaScript。 – 2013-03-08 18:30:33

+0

@EricLeschinski我不知道他在那個問題上做了什麼。 – 2013-03-08 18:32:53

回答

51

而INSERT觸發器被解僱你不能改變一個表。 INSERT可能會執行一些可能導致死鎖的鎖定。另外,從觸發器更新表格會導致同一個觸發器在無限遞歸循環中再次觸發。這些原因都是MySQL阻止你這樣做的原因。

但是,根據您要實現的內容,您可以使用NEW.fieldname或舊值(如果使用OLD進行UPDATE)訪問新值。

如果你有一排名爲full_brand_name,你想用前兩個字母作爲一個簡短的名字在外地small_name您可以使用:

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

正如另一個SO問題所引用的(http://stackoverflow.com/questions/1582683/mysql-trigger -stored-trigger-is-already-used-by-statement-which-invoked-stored-t),MySQL不支持這個功能(http://forums.mysql.com/read.php? 99,122354,240978#msg-240978),即使其競爭對手也這麼做。 – 2013-06-18 18:46:16

+1

它很有意義@Steve! – 2013-10-09 10:16:38

+0

@Steve我遇到了同樣的問題。當我嘗試:update employee_audit set lastName ='Sharma'其中employeeNumber = 112; – 2017-07-10 08:43:20

4

正確的語法是:

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

MySQL說:後續觸發不允許更新新行。 :( – 2013-03-08 18:43:06

+1

對不起,您需要將它從AFTER INSERT更改爲BEFORE INSERT,如在Steve的答案中 – rsanchez 2013-03-08 18:44:19

+0

It worked :)謝謝 – 2013-03-08 18:56:44

2

我有同樣的問題並解決添加「新「。在更新字段之前。我在這裏發表充滿觸發有人想寫一個觸發器

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 ; 

希望這有助於有人

1

A「之前,插入」 - 觸發器是實現對插入相同的表更新的唯一途徑,並且只能從MySQL 5.5+開始。但是,自動增量字段的值僅適用於「AFTER-INSERT」觸發器 - 它在BEFORE-case中默認爲0。因此下面的示例代碼將設置基礎上,自動遞增值id將編譯一個預先計算的代理鍵的值,但實際並不起作用,因爲NEW.id將始終爲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); 
相關問題