2014-09-29 53 views
2

我想查询一个MySQL服务器以确定有关数据库的信息,以支撑一些代码。如何以编程方式确定表之间的MySQL关系类型(1:1,1:n,n:m)?

我一直很成功使用的Java JDBCINFORMATION_SCHEMA表这一点,但问题是,我需要确定一个表关系OneToOne一对多多对多。我无法找到实现这一目标的好方法,如果有人能够帮助我一点,并且如果可能的解决方案不是MySQL特有的,并且可以帮助其他人,我也会很乐意。

我发现这个问题的计算器,但它不会解决问题: how-to-determine-cardinality-of-foreign-key-using-mysql

EDIT(更多) 为了进一步说明我的问题,我会添加更多的信息。目前我使用InnoDB和MySQL Workbench来创建EER图并生成SQL来创建数据库。

我试图反向工程在我的Java应用程序中现有的两个表之间的关系,以确定是否一个表是OneToOne一对多多对多。问题是,当我在MySQL Workbench中设计模型时,我在两个表之间创建了一个关系,但我看不到Non-Identifying 1:1和Non-Identifying 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工作台,看看数据库它可以猜测它是否是一个1:11:n,它实际上能够猜到它,图有正确的关系箭!也许它将引用存储为唯一的地方,或者InnoDB在自己的供应商特定的INFORMATION_SCHEMA上有这个引用,但我想在我的应用程序中复制这种行为。

任何想法,我怎么能做到这一点?

回答

1

进一步研究后,我发现,虽然莫名其妙的MySQL Workbench是能够反向工程1:11:偶数n关系时是一个非确定关系,其中引用的外键ISN”属性t PK或UQ,这可能适用于特定于供应商(InnoDB)的属性。

ALL其他经过测试的SQL反向工程师工具显示出与OneToMany无关的关系,即使他们在MySQL WorkBench中设计为OneToOne无法识别。假设这我预制一个JOIN查询来检索必要的信息来区分1:1 1:N 所以SQL变为如下所示:

实施例关于“表1”

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

如果你有两个表如下:

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 

有本质上,在这个设计中,零个,一个或多个行中ba每一行。对于b中的每一行,在a中固有地存在单行。这通常意味着OneToMany

如果表b中的a_id列恰好具有唯一索引,则中的每一行都有b中的零或一行。这通常是由OneToOne

如果关系是多对多,则需要额外的表,如下所示:

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)样式表。

+0

我最初认为** OneToOne **和** OneToMany **之间的主要可见区别是@OllieJones在前面的答案中指出的,外键引用(在本例中为** a_id **在**表b **)被标记或标记为UQ(唯一),但令我惊讶的是,在InnoDB中使用MySQL工作台时,我发现1:1和1:N都没有标记为UQ,而当我做反向该数据库使用MySQL工具,它以某种方式设法检测1:1和1:N之间的差异。我想知道在这种情况下如何处理这个问题。 感谢您的时间和精力奥利琼斯 – Lethe 2014-09-29 16:34:37

相关问题