Rumah  >  Soal Jawab  >  teks badan

Pencetus MySQL tidak berfungsi selepas kemas kini dipadam

Maaf untuk bertanya soalan ini sekali lagi kerana terdapat banyak perkara di forum tentang isu ini. Tapi saya harap masalah saya lain dari yang lain. Maaf atas bahasa Inggeris saya yang teruk.

Mula-mula saya ada 2 meja (meja ibu bapa dan meja anak) Ibu bapa (lokasi)

loc_id saiz_loc
1 100
2 75

Kanak-kanak (Kawasan)

ar_id ar_loc_id saiz_ar
1 2 35
2 2 40

Ini adalah pencetus pasca padam saya.

CREATE TRIGGER after_delete_area_location
AFTER DELETE
   ON area FOR EACH ROW

BEGIN

UPDATE location SET loc_size = loc_size + old.ar_size WHERE loc_id=old.ar_loc_id

END;

Sebagai contoh, jika saya ingin memadam ar_id = '2', maka ar_size akan dikemas kini dalam position loc_size.

Memandangkan nilai loc_size ialah "0", nilainya ialah 40 selepas pencetus dijalankan.

Masalahnya ialah pencetus tidak berjalan dengan betul, selepas pencetus berjalan loc_size tidak dikemas kini sama sekali, hanya nilai "0".

Adakah saya terlepas sesuatu atau sesuatu sedang berlaku kerana ia tidak berfungsi.

Tolong bantu saya selesaikan masalah ini. Terima kasih banyak - banyak.

P粉155832941P粉155832941258 hari yang lalu340

membalas semua(1)saya akan balas

  • P粉639667504

    P粉6396675042024-02-04 20:57:10

    Saya tidak nampak salah dengan pencetus anda. Saya telah mengujinya dan ia berfungsi. Untuk melengkapkannya, saya menambah picu sisipan di atas meja 区域.

    create table location(loc_id int,loc_size int);
    create table area(ar_id int,ar_loc_id int,ar_size int);
    
    
    delimiter //
    
    CREATE TRIGGER after_insert_area_location
    AFTER insert
       ON area FOR EACH ROW
    
    BEGIN
    
    UPDATE location SET loc_size = loc_size - new.ar_size WHERE loc_id=new.ar_loc_id;
    
    -- Note: In reality, you should throw in an if statement before the UPDATE to make sure there is enough loca_size to be taken away by the ar_size.
    END//
    
    
    CREATE TRIGGER after_delete_area_location
    AFTER DELETE
       ON area FOR EACH ROW
    
    BEGIN
    
    UPDATE location SET loc_size = loc_size + old.ar_size WHERE loc_id=old.ar_loc_id;
    
    END//
    delimiter ;
    
    insert into location values(1,100),(2,75);
    
    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       75 |
    +--------+----------+
    
    select * from area;
    Empty set (0.00 sec)
    
    
    -- Test the insert
    insert into area values(1,2,35),(2,2,40);
    select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    |     2 |         2 |      40 |
    +-------+-----------+---------+
    
     select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |        0 |
    +--------+----------+
    
    -- test the delete
    delete from area where ar_id=2;
    
    select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    +-------+-----------+---------+
    
    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       40 |
    +--------+----------+

    Seperti yang anda lihat, dalam kedua-dua operasi sisip dan padam, nilai dikemas kini dengan sewajarnya.
    -- Dikemas kini dari sini --

    Ini ialah pernyataan pencetus after_insert_area_location 的增强版本,我将在其中演示新添加的 IF 语句以保持数据完整性。请注意,SIGNAL yang digunakan untuk menimbulkan ralat yang bertindak sebagai mesej amaran dan menamatkan operasi.

    -- First of all, I truncated my table so we can start from scratch.
    -- Make sure the original trigger is dropped before creating the newer one to avoid conflicts.
    
    drop trigger after_insert_area_location //
    CREATE TRIGGER after_insert_area_location
    AFTER insert
       ON area FOR EACH ROW
    
    BEGIN
    if (select loc_size from location where loc_id=new.ar_loc_id) - new.ar_size < 0 then
    signal sqlstate '77777' set message_text='You cannot take more land than you have'; -- Note: the sqlstate code and the message_text can be modified to your liking
    end if;
    UPDATE location SET loc_size = loc_size - new.ar_size WHERE loc_id=new.ar_loc_id;
    
    END//
    
    delimiter ;
    
    -- then let's populate the location table:
    insert into location values(1,100),(2,75);
    
    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       75 |
    +--------+----------+
    
    select * from area;
    Empty set (0.00 sec)
    
    -- Now we test the insert one row at a time:
     insert into area values(1,2,35);
    
     select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       40 |
    +--------+----------+
    
     select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    +-------+-----------+---------+
    
    -- now we add another row with an ar_size more than its location can afford:
    
    insert into area values(2,2,80);
    ERROR 1644 (77777): You cannot take more land than you have

    Seperti yang anda lihat, pencetus IF 语句中的 SIGNAL 语句引发了一个错误,其中包含 SQL_STATE 代码 77777 dan mesej: dipratetap. Ini akan membuat asal perubahan yang dibuat sejak baris baharu dimasukkan.

    select * from location;
    +--------+----------+
    | loc_id | loc_size |
    +--------+----------+
    |      1 |      100 |
    |      2 |       40 |
    +--------+----------+
    
    select * from area;
    +-------+-----------+---------+
    | ar_id | ar_loc_id | ar_size |
    +-------+-----------+---------+
    |     1 |         2 |      35 |
    +-------+-----------+---------+

    Ringkasnya, kita boleh menggunakan pernyataan IF dalam pencetus untuk mempunyai sedikit kawalan ke atas aliran data. Pernyataan SIGNAL boleh digunakan untuk sengaja memanggil ralat untuk menghentikan/membuat asal pelaksanaan pencetus dan memulakan tindakan pencetus. Seperti yang dinyatakan di atas, bukan sahaja pernyataan UPDATE 没有执行,引发触发器的 insert dalam pencetus juga dibuat asal.

    balas
    0
  • Batalbalas