2

我正在尝试查询 MySQL 服务器以确定有关数据库的信息,以便构建一些代码。

为此,我使用Java JDBCINFORMATION_SCHEMA表非常成功,但问题是我需要确定表关系是OneToOneOneToMany还是ManyToMany。我找不到实现这一目标的好方法,如果有人可以帮助我一点,并且如果它可能使用不是 MySQL 特定和可靠的解决方案,我会很高兴,因此它可以帮助其他人。

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

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

我试图在我的 Java 应用程序中对两个现有表之间的关系进行逆向工程,以确定一个表是OneToOneOneToMany还是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,它实际上能够猜到它,图中有正确的关系箭头!!!也许它将引用存储为唯一的某处,或者 InnoDB 在其自己的供应商特定的 INFORMATION_SCHEMA 上有此引用,但我想在我的应用程序上复制此行为。

关于如何实现这一目标的任何想法?

4

2 回答 2

2

经过进一步研究,我发现尽管 MySQL Workbench 能够以某种方式对1:11: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**
}

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

于 2014-09-30T20:04:54.097 回答
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通常的含义。

如果 table 中的列a_id恰好具有b唯一索引,则. 这就是OneToOne通常的意思。ba

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

Table: a
a_id    unique autoincrement primary key
a_info  other information

还有这张桌子

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

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

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

于 2014-09-29T15:52:55.843 回答