【问题标题】:Referential integrity for invoice and task tables发票和任务表的参照完整性
【发布时间】:2013-09-02 16:55:45
【问题描述】:

我无法弄清楚如何为发票系统设计数据库。我想要一个发票表和一个任务表。我希望 invoices 表中的记录能够具有与其关联的可变数量的任务,但也保持参照完整性,以便无法添加任务表中不存在的任务。

到目前为止,我已经在 invoices 表上提出了 task_id1、task_id2 等字段,它们是 tasks 表中 task_id 字段的外键,但感觉可以放置的任务数量受到限制一张发票。

另外,invoices 表可以有一个逗号分隔的 task_id 列表,这将允许每个发票的任务数量可变,但如果列类型不同,我无法弄清楚如何创建外键。 (加上这感觉有点草率)。

我确定有一个我没有看到的简单答案。

【问题讨论】:

    标签: mysql database-design


    【解决方案1】:

    到目前为止,我已经在 作为 task_id 字段外键的 invoices 表

    另外,invoices 表可以有一个逗号分隔的列表 task_id 允许每张发票执行可变数量的任务

    不!!!

    在发票和任务之间建立多对多表,并在此表和发票和任务表之间进行约束。

    SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
    SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
    SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
    
    CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
    USE `mydb` ;
    
    -- -----------------------------------------------------
    -- Table `mydb`.`invoices`
    -- -----------------------------------------------------
    CREATE  TABLE IF NOT EXISTS `mydb`.`invoices` (
      `id` INT NOT NULL AUTO_INCREMENT ,
      `date` DATETIME NULL ,
      `amount` DECIMAL(7,2) NULL ,
      `whatever` VARCHAR(45) NULL ,
      PRIMARY KEY (`id`) )
    ENGINE = InnoDB;
    
    
    -- -----------------------------------------------------
    -- Table `mydb`.`tasks`
    -- -----------------------------------------------------
    CREATE  TABLE IF NOT EXISTS `mydb`.`tasks` (
      `id` INT NOT NULL AUTO_INCREMENT ,
      `whatever` VARCHAR(45) NULL ,
      PRIMARY KEY (`id`) )
    ENGINE = InnoDB;
    
    
    -- -----------------------------------------------------
    -- Table `mydb`.`invoices_has_tasks`
    -- -----------------------------------------------------
    CREATE  TABLE IF NOT EXISTS `mydb`.`invoices_has_tasks` (
      `invoices_id` INT NOT NULL ,
      `tasks_id` INT NOT NULL ,
      PRIMARY KEY (`invoices_id`, `tasks_id`) ,
      INDEX `fk_invoices_has_tasks_tasks1_idx` (`tasks_id` ASC) ,
      INDEX `fk_invoices_has_tasks_invoices_idx` (`invoices_id` ASC) ,
      CONSTRAINT `fk_invoices_has_tasks_invoices`
        FOREIGN KEY (`invoices_id` )
        REFERENCES `mydb`.`invoices` (`id` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION,
      CONSTRAINT `fk_invoices_has_tasks_tasks1`
        FOREIGN KEY (`tasks_id` )
        REFERENCES `mydb`.`tasks` (`id` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB;
    
    
    
    SET SQL_MODE=@OLD_SQL_MODE;
    SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
    SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
    

    【讨论】:

      【解决方案2】:

      创建发票表

      CREATE TABLE invoice (
          invoice_id INT NOT NULL,
          PRIMARY KEY (invoice_id)
      ) ENGINE=INNODB;
      

      要创建任务表,请使用

      CREATE TABLE tasks (
          task_id INT, 
          invoice_id INT,
          INDEX par_ind (invoice_id),
          FOREIGN KEY (invoice_id) 
              REFERENCES invoice(invoice_id)
              ON DELETE CASCADE
      ) ENGINE=INNODB;
      

      这就是你所需要的

      【讨论】:

      • invoice table PK 应该是 invoice_id,而不是 id(我确定是错字)。更重要的是,任务应该被规范化并分成两个表,一个用于实体任务,第二个将任务链接到发票(如果这是你想要的,那么你应该在任务链接表中添加第二个 FK 到任务实体表)。
      • 错字,没有。至于意见,我不认为这只是我的。
      • 有什么理由不这么认为?
      • dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html 这是原始查询的来源,我只是为了他的目的而采用它...我认为您似乎比开发指南了解更多
      • 这不是您创建 FK 的方式,而是任务未标准化。根据 OP(以及我的建议),任务将是一个单独的表。如何显示它,给定任务只能与单个发票相关联,并且信息需要在每个任务表中重复(即未标准化)。我通常也不推荐 CASCADE,但我想这只是我的意见(但可能是其他人)。如果您在复制的示例之后查看下一个示例(产品/客户),它描述了我所做的,但使用了复合键(任何一种方式都有效)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多