【问题标题】:MySQL assertionMySQL 断言
【发布时间】:2013-07-23 14:40:00
【问题描述】:

我是 MySQL 和 SQL 新手,我刚刚发现 MySQL 不支持断言。

我有这些表:


create table stagione
  (
    nome           varchar(20), 
    biennio        char(9), 
    teatro         varchar(20),
    primary key(nome, biennio),
    foreign key (teatro) references teatro(nome) 
on update cascade on delete set null
  )
  ENGINE=InnoDB;

create table produzione
  (
    produttore     varchar(20), 
    spettacolo     varchar(40),
    primary key(produttore, spettacolo),
    foreign key (produttore) references produttore(nome)
                on update cascade on delete cascade,
    foreign key (spettacolo) references spettacolo(titolo)
                on update cascade on delete cascade
) ENGINE=InnoDB;

create table proposta
  (
   nomeStagione varchar(20),
   biennioStagione char(9),
   spettacolo varchar(40),
   primary key(nomeStagione, biennioStagione, spettacolo),
   foreign key (nomeStagione, biennioStagione) references stagione(nome, biennio)
on update cascade on delete cascade,
   foreign key (spettacolo) references spettacolo(titolo)
 on update cascade on delete cascade
  )
ENGINE=InnoDB;

使用 mysql 我无法编写断言。是否可以使用一个或多个触发器来模拟以下断言?


crate assertion RA2 check (
    not exists (
      select stagione.teatro, stagione.nome, stagione.biennio, count(*)
      from (stagione join proposta on 
           (stagione.nome = proposta.nomeStagione) and 
           (stagione.biennio = proposta.biennioStagione)) 
           join produzione on 
           (proposta.spettacolo = produzione.spettacolo) and
           (stagione.teatro = produzione.produttore)
      group by stagione.teatro, stagione.nome, stagione.biennio
      having count(*) > 2
    )
  );          

我应该如何编写那个触发器?

【问题讨论】:

  • 你能用简单的话解释一下你到底想达到什么目标吗?
  • 断言所指的规则是:一个剧院(teatro)在同一剧院季节(stagione)内不能上演超过两部自己制作(produzione)的戏剧(spettacolo)跨度>

标签: mysql sql triggers mysql-workbench assertion


【解决方案1】:

如果我正确理解您的架构,那么您可以通过这样的触发器强制执行您的规则

CREATE TRIGGER tg_proposta_before_insert
BEFORE INSERT ON proposta
FOR EACH ROW
  SET NEW.nomeStagione = IF(
    (
      SELECT COUNT(*) total
        FROM proposta p JOIN produzione d
          ON p.spettacolo = d.spettacolo
       WHERE p.nomeStagione = NEW.nomeStagione
         AND p.biennioStagione = NEW.biennioStagione
         AND d.produttore = 
             (
               SELECT produttore
                 FROM produzione
                WHERE spettacolo = NEW.spettacolo
                LIMIT 1
             )
    ) < 2,
    NEW.nomeStagione,
    NULL
  );

为了让它工作你必须在proposta 表中的nomeStagione 列上有NOT NULL 约束你最好对所有参与主键的列都有这样的约束

一些解释:

  1. 这是一个BEFORE 触发器,因为它是MySql 中唯一可以更改插入行的列值的事件。您可以使用 NEW 关键字访问这些值。
  2. 现在,当您尝试在proposta 中插入一行时,它会检查您尝试插入的同一戏剧是否已经有两部戏剧违反了NOT NULLnomeStagione 列的约束(它可以是任何其他列)有效地阻止此插入完成。

这里是 SQLFiddle 演示。 尝试取消注释最后一个插入语句和Build Schema。您会看到它不允许您插入该行。这将是该剧院本赛季的第三场演出

【讨论】:

  • 问题。使主键不强制执行 NOT NULL 约束吗?
  • 插入前用程序检查不是更好吗?
猜你喜欢
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多