mysql使用触发器更新另一个表

时间:2018-05-02 14:49:00

标签: php mysql stored-procedures triggers

我需要更新" video_upload"将一行插入" video_ratings"表。在此之前,我需要获取RATINGS列的计数,然后应该使用该值进行更新。下面提到了所需的逻辑。

  1. 从video_ratings中获取所有0的计数,并更新video_upload的RATE_BAD列。
  2. 从video_ratings中获取所有1的计数,并更新video_upload的RATE_AVERAGE列。
  3. 从video_ratings中获取所有2的计数,并更新video_upload的RATE_GOOD列。
  4. 从video_ratings中获取所有3个的计数,并更新video_upload的RATE_BEST列。
  5. video_upload表

      CREATE TABLE `video_upload` (
      `ID` int(10) NOT NULL,
      `USER_ID` int(10) NOT NULL,
      `VIDEO_NAME` varchar(75) COLLATE utf32_sinhala_ci NOT NULL,
      `VIDEO_URL` varchar(100) COLLATE utf32_sinhala_ci DEFAULT NULL,
      `PIC1_URL` varchar(100) COLLATE utf32_sinhala_ci DEFAULT NULL,
      `PIC2_URL` varchar(100) COLLATE utf32_sinhala_ci DEFAULT NULL,
      `PIC3_URL` varchar(100) COLLATE utf32_sinhala_ci DEFAULT NULL,
      `ATT_URL` varchar(100) COLLATE utf32_sinhala_ci DEFAULT NULL,
      `TYPE` varchar(7) COLLATE utf32_sinhala_ci NOT NULL,
      `DESCRIPTION` varchar(2000) COLLATE utf32_sinhala_ci NOT NULL,
      `IsAPPROVED` int(1) NOT NULL DEFAULT '0',
      `RATE_BAD` int(10) NOT NULL,
      `RATE_AVERAGE` int(10) NOT NULL,
      `RATE_GOOD` int(10) NOT NULL,
      `RATE_BEST` int(10) NOT NULL,
      `UPLOADED_ON` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `UPDATED_ON` timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf32 COLLATE=utf32_sinhala_ci;
    

    video_ratings表

        CREATE TABLE `video_ratings` (
      `VID_ID` int(10) NOT NULL,
      `STU_ID` int(10) NOT NULL,
      `RATINGS` int(1) NOT NULL,
      `RATED_ON` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `UPDATED_ON` timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf32 COLLATE=utf32_sinhala_ci;
    

    我正在计划使用触发器执行此操作。我还从互联网上找到了一些mysql触发器代码。

    //Rating count trigger
    create trigger rate_count_update
    after insert on video_ratings for each row begin
    DECLARE updatecount INT;
      set updatecount = ( select count(RATINGS) AS TOTAL from video_ratings where RATINGS='0' AND RATINGS='1' AND RATINGS='2' AND RATINGS='3' );
      if updatecount=4
        then
          update video_upload set RATE=TOTAL;
      end if;
    end//
    

    但我无法根据我的要求修改它。请帮忙。

1 个答案:

答案 0 :(得分:1)

几个笔记......

我可以肯定地保证没有满足条件的行

  FROM video_ratings
 WHERE RATINGS='0' 
   AND RATINGS='1'
   AND RATINGS='2'

想一想。如果其中一个条件(比较)评估为TRUE,那么其他比较将评估为FALSE,并且

  TRUE  AND  FALSE  AND  FALSE 

将评估为FALSE。

因此该语句上的COUNT()聚合将计算为0。

在此UPDATE语句中,

update video_upload set RATE=TOTAL;

它成功了,它将更新video_upload表中的每个行。好像我们只想更新video_upload表上的一行行,该行的ID值与我们刚刚插入{{I}}的行匹配VID_ID {1}}表。

我们可以通过引用

获取刚插入的行的videos_ratings列的值
VID_ID
触发器体中的

。我们可能想要一个看起来像这样的更新语句:

 NEW.VID_ID 

如果我们要为UPDATE video_upload v SET ... WHERE v.ID = NEW.VID_ID ; RATE_BADRATE_AVERAGERATE_GOOD列分配值,我们需要SET子句来引用这些列...

RATE_BEST

也许我们想要做这样的事情,以获得评级的计数并将这些计数存储在局部变量中,以便我们可以在触发器中稍后引用它们。

UPDATE video_upload v
   SET v.RATE_BAD      = some_expr 
     , v.RATE_AVERAGE  = another_expr
     , v.RATE_GOOD     = expr_for_good
     , v.RATE_BEST     = expr_for_best
 WHERE v.ID = NEW.VID_ID ; 

<强>后续

我推荐这种模式用于触发器名称:SELECT IFNULL(SUM(r.RATINGS='0'),0) AS cnt_r0 , IFNULL(SUM(r.RATINGS='1'),0) AS cnt_r1 , IFNULL(SUM(r.RATINGS='2'),0) AS cnt_r2 , IFNULL(SUM(r.RATINGS='3'),0) AS cnt_r3 FROM video_ratings r WHERE r.VID_ID = NEW.VID_ID INTO li_cnt_r0 , li_cnt_r1 , li_cnt_r2 , li_cnt_r3 ; + table_name

_suffix之一是&#39; _ad&#39;,&#39; _ai&#39;,&#39; _au&#39;,&#39; _bd&#39;,&# 39; _bi&#39;,&#39; _bu&#39; (对于删除/插入/更新之前/之后)

遵循此命名约定可避免命名冲突,当我们在表上查找触发器时,我们将知道在哪里找到它们。通过按字母顺序列出触发器,给定表的所有触发器将按table_name(大多数)组合在一起。 (边缘情况,我们有可能进行一些混合是一个表名,以另一个表的名称开头,后跟_a ..或_b ..)

(在早期开发中,当你有两个表和六个触发器时,这种命名约定的优点并不明显。但是当数据库包含大量表和触发器时,它就变得很明显了。 )

另请注意,MySQL仅为给定表上的每个BEFORE / AFTER INSERT / UPDATE / DELETE支持单个触发器。

使用局部变量支持用户定义的变量,除非使用用户定义的变量有特定原因。

_suffix