Panggil prosedur tersimpan dari pemicu

17

Saya telah membuat prosedur tersimpan di mysql menggunakan sintaks berikut.

DROP PROCEDURE IF EXISTS `sp-set_comment_count`;

DELIMITER $$

CREATE PROCEDURE `sp_set-comment_count` (IN _id INT)
BEGIN
   -- AC   - AllCount
   DECLARE AC INT DEFAULT 0;

   SELECT COUNT(*) AS ac
     INTO AC
     FROM usergroups AS ug
LEFT JOIN usergroup_comments AS ugm ON ugm.`gid` = ug.`id`
LEFT JOIN mediagallery AS dm ON ugm.mid = dm.`id`
    WHERE dm.`status` NOT IN (200, 201, 202, 203, 204, 205)
      AND ug.`id` = _id;

   UPDATE usergroups
      SET allCount = AC,
    WHERE usergroups.`id` = _id;

END $$
DELIMITER ;

FYI Saya sudah sangat menyederhanakan prosedur tersimpan tetapi saya tahu ini bekerja tanpa masalah.

Yang ingin saya lakukan adalah menyiapkan pemicu dari usergroup_comments yang berfungsi seperti ini.

DROP TRIGGER IF EXISTS `usergroups_comments_insert` 

CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
    FOR EACH ROW
    BEGIN
       CALL sp-set-comment_count(NEW.`gid`);
    END;

Tetapi untuk beberapa alasan setiap kali saya melakukan mysql melempar kesalahan pada saya yang kurang membantu menyatakan bahwa ada kesalahan sintaks pada baris 4.

Saya telah menyisir dokumentasi mysql dan menemukan beberapa informasi tentang batasan pemicu tetapi ternyata cukup berbelit-belit.

http://dev.mysql.com/doc/refman/5.1/en/stored-program-restrictions.html

Setiap ide akan sangat membantu.

Markus D
sumber
Jadi ternyata masalah dengan prosedur tersimpan di atas dipanggil adalah fakta bahwa ia memiliki tanda hubung dalam namanya. Mengubah nama prosedur tersimpan ke sp_set_comment_count menyelesaikan masalah.
Mark D

Jawaban:

24

Ada alasan bagus mengapa Anda tidak boleh menyebut prosedur tersimpan dari dalam pemicu.

Pemicu pada dasarnya adalah prosedur tersimpan. Tindakan mereka sebenarnya sulit untuk dibatalkan . Bahkan jika semua tabel yang mendasari adalah InnoDB, Anda akan mengalami volume proporsional kunci baris bersama dan intermittency yang mengganggu dari kunci baris eksklusif. Ini akan menjadi kasus jika pemicu memanipulasi tabel dengan INSERT dan UPDATE sedang mandek untuk melakukan tugas berat MVCC di dalam setiap panggilan ke pemicu .

Jangan lupa bahwa Pemicu membutuhkan overhead. Padahal, menurut Pemrograman Prosedur yang Disimpan MySQL , halaman 256 di bawah kepala "Trigger Overhead" mengatakan yang berikut:

Penting untuk diingat bahwa, karena kebutuhan, pemicu menambahkan overhead pada pernyataan DML yang mereka terapkan. jumlah aktual overhead akan tergantung pada sifat pemicu, tetapi --- karena semua pemicu MySQL mengeksekusi UNTUK SETIAP BARIS --- overhead dapat dengan cepat terakumulasi untuk pernyataan yang memproses sejumlah besar baris. Karena itu Anda harus menghindari menempatkan pernyataan SQL mahal atau kode prosedural dalam pemicu.

Penjelasan lebih lanjut tentang overhead pemicu diberikan pada halaman 529-531. Titik penutup dari bagian itu menyatakan sebagai berikut:

Pelajaran di sini adalah ini: karena kode pemicu akan dieksekusi sekali untuk setiap baris yang dipengaruhi oleh pernyataan DML, pemicu dapat dengan mudah menjadi faktor paling signifikan dalam kinerja DML. Kode di dalam tubuh pemicu harus seringan mungkin dan - khususnya - pernyataan SQL apa pun dalam pemicu harus didukung oleh indeks bila memungkinkan.

Saya menjelaskan aspek-aspek buruk lain dari Pemicu dalam posting sebelumnya.

RINGKASAN

Saya sangat merekomendasikan untuk tidak memanggil prosedur tersimpan dari Pemicu , bahkan jika MySQL mengizinkannya. Anda harus memeriksa pembatasan saat ini untuk MySQL 5.5 .

RolandoMySQLDBA
sumber
Menarik, terima kasih atas perhatiannya. Kurangnya pertanyaan transaksional di lingkungan kita mengurangi masalah transaksi. Namun saya dapat menghargai gagasan mengakumulasi overhead. Saya kira saya akan menonton db sebentar untuk melihat apa hasil dari perubahan ini.
Mark D
Saya tidak berpikir itu akurat untuk mengacaukan pemicu dengan prosedur tersimpan. Minimal, valid untuk memulai dan melakukan transaksi dalam prosedur tersimpan. MySQL mengeluh jika Anda mencoba melakukan hal yang sama pada trigger. Yang konyol, karena memiliki pemicu yang perlu memperbarui satu atau lebih tabel secara transaksi sebagai respons terhadap beberapa perubahan adalah kasus penggunaan yang sepenuhnya valid yang harus didukung secara langsung.
Agustus
Jadi saya punya pemicu ini, itu sangat besar. Itu melakukan beberapa perhitungan di meja saya, baik setelah memasukkan dan memperbarui. Pemicu dalam Mysql dapat benar-benar menjadi menyakitkan ketika mereka kompleks. Akan lebih mudah untuk memecah pelatuk menjadi prosedur.
Lamar
8

Jadi ternyata ini adalah masalah yang mengganggu saya selama beberapa jam, percaya atau tidak.

Saya dapat dengan mudah mendefinisikan prosedur yang disebut, sp_set-comment_count. Namun ketika memanggil prosedur tersebut, itu tidak bekerja dengan cara yang sama.

CALL sp_set-comment_count (Saya hanya dapat berasumsi ini karena server mengartikan - sebagai minus).

Sejak itu saya mengubah nama prosedur tersimpan untuk hanya menggunakan garis bawah dan sepertinya telah menyelesaikan semuanya.

Markus D
sumber
Terlambat ke pesta tetapi: Anda telah membuat SP menggunakan pengenal yang dikutip, yang memungkinkan karakter khusus dalam namanya, jadi Anda harus CALL `sp-set-comment_count`(NEW.`gid`);
merujuknya dengan
5

Jika dikatakan tentang kesalahan sintaksis, kemungkinan besar Anda lupa mengubah pembatas (seperti yang Anda lakukan untuk prosedur tersimpan). Jadi kamu butuh

DELIMITER $$
CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
FOR EACH ROW
BEGIN
   CALL sp_set_count(NEW.`gid`);
END;
$$
a1ex07
sumber
Terima kasih, ini membuat saya berpikir di jalur yang benar. Sebenarnya sp saya disebut sp-set_comment_count. Ketika dipanggil oleh pemicu, tampaknya bahwa masalahnya adalah ketika memanggil SP dari pemicu - terus melempar kesalahan.
Mark D
1

Sepertinya koma setelahnya ACadalah kesalahan sintaksis:

UPDATE usergroups
   SET allCount = AC,
 WHERE ........
pengguna22800
sumber
Poin yang valid, tetapi bukan penyebab sebenarnya dari kesalahan dalam kasus ini. Saya hanya memangkas beberapa set tambahan dari permintaan itu dan lupa menghapus,
Mark D