触发器中的“新”表有时包含列,有时不包含

Posted

技术标签:

【中文标题】触发器中的“新”表有时包含列,有时不包含【英文标题】:The "NEW" table in a trigger sometimes contains column and sometimes it does not 【发布时间】:2021-12-27 01:54:03 【问题描述】:

我一直在尝试创建一个 INSERT 触发器,并且在一个简单的触发器主体中我可以很好地访问“NEW”表。

但在“NEW”表在正文中更深入使用的示例中,它不再找到我需要的列。

我可以在以下位置找到“NEW.nr_legitimatie”列:

CREATE DEFINER=`root`@`localhost` 
TRIGGER `calculMedie` 
AFTER INSERT ON `note` 
FOR EACH ROW 
INSERT INTO medii (MEDII.nr_legitimatie, MEDII.medie_generala, medii.medie_an1, medii.medie_an2, medii.medie_an3)
VALUES (new.nr_legitimatie, 1, 2, 3, 4)

我在以下位置找不到“NEW.nr_legitimatie”列:

CREATE DEFINER=`root`@`localhost` 
TRIGGER `calculMedie` 
AFTER INSERT ON `note` 
FOR EACH ROW 
INSERT INTO medii (MEDII.nr_legitimatie, MEDII.medie_generala, medii.medie_an1, medii.medie_an2, medii.medie_an3)
WITH date AS (
    WITH medii_pe_coloane AS (
        SELECT medie1.nr_legitimatie, 
            AVG(medie1.maxim) as medie_an_1, 
            AVG(medie2.maxim) as medie_an_2, 
            AVG(medie3.maxim) as medie_an_3
        FROM 
        (
        SELECT nr_legitimatie, disciplina, an_studiu, MAX(nota) AS maxim 
        FROM note 
        WHERE an_studiu = 1 AND nr_legitimatie = new.nr_legitimatie
        GROUP BY nr_legitimatie, disciplina
        ) as medie1,
        (
        SELECT nr_legitimatie, disciplina, an_studiu, MAX(nota) AS maxim 
        FROM note 
        WHERE an_studiu = 2 AND nr_legitimatie = new.nr_legitimatie
        GROUP BY nr_legitimatie, disciplina
        ) as medie2,
        (
        SELECT nr_legitimatie, disciplina, an_studiu, MAX(nota) AS maxim 
        FROM note 
        WHERE an_studiu = 3 AND nr_legitimatie = new.nr_legitimatie
        GROUP BY nr_legitimatie, disciplina
        ) as medie3
    ),
    medii_union AS (
        SELECT medii_pe_coloane.medie_an_1 as medie from medii_pe_coloane
        UNION ALL
        SELECT medii_pe_coloane.medie_an_2 as medie from medii_pe_coloane
        UNION ALL
        SELECT medii_pe_coloane.medie_an_3 as medie from medii_pe_coloane
    ),
    medie_generala AS (
        SELECT AVG(medii_union.medie) as medie FROM medii_union
    )
        
    
    SELECT medii_pe_coloane.*, medie_generala.medie from medii_pe_coloane, medie_generala
)
SELECT nr_legitimatie, medie, medie_an_1, medie_an_2, medie_an_3
FROM date

我无法想象可能发生的事情。它没有被覆盖。也许它超出了它的范围?我怎么可能在 WHERE 子句中使用它?

错误是:

#1054 - Unknown column 'nr_legitimatie' in 'NEW'

为了对其进行测试,我在note 表中插入了一个新行,该行 100% 包含“nr_legitimatie”列。

MariaDB 10.4

【问题讨论】:

我使用了完全相同的触发器,但硬编码值“12345”而不是new.nr_legitimatie,它运行得很好 对不起,我会删除我之前的评论。 【参考方案1】:

我在手机上,所以还没有测试过,但也许你不能在同一个触发器中引用 NEW 三次?

如果是这样,我会重写您的查询,无论如何它看起来都有逻辑错误。

这是我建议的查询...

INSERT INTO
  medii (
    MEDII.nr_legitimatie, MEDII.medie_generala, medii.medie_an1, medii.medie_an2, medii.medie_an3
  )
WITH
  max_an_studiu AS
(
    SELECT nr_legitimatie, disciplina, an_studiu, MAX(nota) AS maxim 
      FROM note 
     WHERE an_studiu IN (1, 2, 3)
       AND nr_legitimatie = (SELECT nr_legitimatie FROM new)
  GROUP BY nr_legitimatie, disciplina, an_studiu
),
  medie AS
(
  SELECT
    nr_legitimatie,
    an_studiu,
    AVG(maxim) AS medie
  FROM
    max_an_studiu
  GROUP BY
    nr_legitimatie,
    an_studiu
)
SELECT
  nr_legitimatie,
  AVG(medie)                                AS medie,
  MAX(CASE WHEN an_studiu=1 THEN medie END) AS medie_an_1,
  MAX(CASE WHEN an_studiu=2 THEN medie END) AS medie_an_2,
  MAX(CASE WHEN an_studiu=3 THEN medie END) AS medie_an_3
FROM
  medie
GROUP BY
  nr_legitimatie

【讨论】:

非常感谢,这很好用。我只在您的解决方案中将 (SELECT nr_legitimatie FROM new) 更改为 new.nr_legitimatie 并且它有效!【参考方案2】:

这是一个带有误导性错误消息的MariaDB bug(尤其是this comment,其中有一个与您的问题相近的可重现示例)。

当您重用使用 new 的 CTE 时,您的错误会出现在触发器中。

在您的情况下,您在medii_union 中使用medii_pe_coloane(使用new)3 次,在date 的最终选择中使用一次。这会触发错误。

不过,您可以随心所欲地使用new 本身(在尽可能多的 CTE 中)。因此,一种解决方法是多次重新定义 CTE, 例如像

WITH medii_pe_coloane AS ( <query using "new"> ),
     medii_pe_coloane1 AS ( <same query using "new"> ),
     medii_pe_coloane2 AS ( <same query using "new"> ),
     medii_pe_coloane3 AS ( <same query using "new"> ),
...
medii_union AS (
           select medii_pe_coloane1.medie_an_1 ... from medii_pe_coloane1 
 union all select medii_pe_coloane2.medie_an_2 ... from medii_pe_coloane2
 union all select medii_pe_coloane3.medie_an_3 ... from medii_pe_coloane3)
... 
SELECT ... from medii_pe_coloane, medie_generala

使您的代码有点重复,但应该作为一般的解决方法。或者,您可能能够以其他方式重写和/或简化您的查询(参见例如MatBailies answer)。

【讨论】:

以上是关于触发器中的“新”表有时包含列,有时不包含的主要内容,如果未能解决你的问题,请参考以下文章

MySQL #1422 存储函数或触发器中不允许显式或隐式提交

SQL Server触发器认为没有时表中存在重复

SQL而不是触发器有时不会触发?

Firebase 函数有时会触发 onDelete 工作

如何在 phpmyadmin 中创建触发器,插入后将更新花药表中的字段?

Toad for Oracle - 从列选项卡中复制列而不包含所有详细信息