如何以编程方式确定表之间的MySQL关系类型(1:1,1:n,n:m)?

时间:2014-09-29 15:33:21

标签: mysql sql relationship reverse-engineering cardinality

我试图查询MySQL服务器以确定有关数据库的信息,以便支持某些代码。

我使用 Java JDBC INFORMATION_SCHEMA 表非常成功,但问题是我需要确定表关系是否为 OneToOne OneToMany ManyToMany 。我无法找到实现这一目标的好方法,如果有人可以帮助我,我会很高兴,如果有可能的解决方案不是MySQL特定的,那么它可以帮助其他人。

我在stackoverflow中发现了这个问题,但它不会解决问题: how-to-determine-cardinality-of-foreign-key-using-mysql

编辑(更多) 为了进一步解释我的问题,我将添加更多信息。目前,我正在使用带有InnoDB和MySQL Workbench的MySQL来创建EER图并生成SQL来创建数据库。

我试图在我的Java应用程序中对两个现有表格之间的关系进行逆向工程,以确定表格是 OneToOne OneToMany 还是 ManyToMany 即可。问题是,当我在MySQL Workbench中设计模型并在两个表之间创建关系时,我发现非识别1:1和非识别1:N之间的任何差异甚至他们的SQL输出都是相同的

非识别1:1

CREATE TABLE IF NOT EXISTS `TestDB`.`table1` (
  `var1` BIT(1) NOT NULL,
  `var2` BIT(8) NOT NULL,
  `var3` VARCHAR(45) NULL DEFAULT NULL,
  `var4` INT(11) NOT NULL,
  `table2_var1` INT(11) NOT NULL,
  PRIMARY KEY (`var1`, `var2`),
  INDEX `fk_table1_table2_idx` (`table2_var1` ASC),
  CONSTRAINT `fk_table1_table2`
    FOREIGN KEY (`table2_var1`)
    REFERENCES `TestDB`.`table2` (`var1`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci

非识别1:n

CREATE TABLE IF NOT EXISTS `TestDB`.`table1` (
  `var1` BIT(1) NOT NULL,
  `var2` BIT(8) NOT NULL,
  `var3` VARCHAR(45) NULL DEFAULT NULL,
  `var4` INT(11) NOT NULL,
  `table2_var1` INT(11) NOT NULL,
  PRIMARY KEY (`var1`, `var2`),
  INDEX `fk_table1_table2_idx` (`table2_var1` ASC),
  CONSTRAINT `fk_table1_table2`
    FOREIGN KEY (`table2_var1`)
    REFERENCES `TestDB`.`table2` (`var1`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci

当我使用MySQL Workbench反转数据库以查看它是否可以猜测它是 1:1 还是 1:n 时,出现了惊人的部分,它& #39; s实际上可以猜到它,图表有正确的关系箭头!也许它将引用存储在某个地方是唯一的,或者InnoDB在其自己的供应商特定的INFORMATION_SCHEMA上有这个,但我想在我的应用程序上复制这种行为。

我怎么能想到这个?

2 个答案:

答案 0 :(得分:2)

经过进一步研究后,我发现虽然MySQL Workbench能够以某种方式对 1:1 1:n 关系进行逆向工程,即使是非识别关系引用外键的属性不是PK或UQ,这可能与供应商特定(InnoDB)属性有关。

所有测试的其他SQL逆向工程工具显示非一致的关系,即OneToMany,即使他们在MySQL WorkBench中设计为OneToOne非识别。假设我执行了一个JOIN查询以检索必要的信息,以区分1:1和1:n 所以SQL如下所示:

' table1'

的示例
select INFORMATION_SCHEMA.COLUMNS.COLUMN_KEY, INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME, INFORMATION_SCHEMA.COLUMNS.TABLE_NAME from INFORMATION_SCHEMA.COLUMNS
join INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
on INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME=INFORMATION_SCHEMA.KEY_COLUMN_USAGE.COLUMN_NAME
where INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_NAME='table1' 
and referenced_table_name is not null

...最后

伪码

if (COLUMN_KEY == "PRI" || COLUMN_KEY == "UNI") { 
    //then you can assume is **OneToOne**
} else {
    //then you can assume is **OneToMany**
}

希望这有助于其他人的斗争,随时添加任何建议或替代方法,谢谢所有人。

答案 1 :(得分:1)

如果您有两个表格如下:

Table: a
a_id    unique autoincrement primary key
a_info  other information

Table: b
b_id    unique autoincrement primary key
a_id    a reference to a row in a
b_info  other information

在此设计中,b中每行a中有一行,零行,一行或多行。对于a中的每一行,b中都有一行内容。这通常是 OneToMany 的意思。

如果表a_id中的列b恰好具有唯一索引,则b中每行a中只有一行或一行。Table: a a_id unique autoincrement primary key a_info other information 。这通常是指 OneToOne

如果关系是 ManyToMany ,则需要一个额外的表格,如下所示:

Table: b
b_id    unique autoincrement primary key
b_info  other information

和这张表

Table: a_b
a_id    reference to a row in a
b_id    reference to a row in b

由此表联系在一起

a_b

此关系表实现 ManyToMany 。它唯一的主键是两列的串联。

这是一个相当传统的设计;当您对现有模式进行逆向工程时,您应该能够选择它。要查找的是关系({{1}})样式表。