rei*_*ost 8 foreign-keys foreign-key-relationship database-diagramming database-diagram
快速调查数据库中信息的一种好方法是应用一个工具,自动创建所有表的数据库图以及它们之间的所有关系.
根据我的经验,这些工具使用外键作为关系,我尝试它们的大多数数据库都不包含这些关系.当然,它们满足与外键相对应的约束,但不强制执行它们.而且我最终会得到一个由一堆不相关的表组成的"图表".
所以我正在寻找的是可以计算"未声明的外键"的软件
你知道任何可以做到这一点的免费工具吗?
有趣的问题。您正在寻找一种解析数据库模式和数据的方法,以确定哪些表相关或应该相互关联,而无需对该关系进行任何严格的定义。实际上,您正在尝试推断一种关系。
我看到两种推断这种关系的方法。首先,我要说的是,您的方法可能会因所使用的数据库而异。我想到了许多问题(我不想要答案,但是值得思考)
注意,这种类型的推断几乎肯定会给出错误的结果,并且是基于许多假设的。
因此,我提供了两种方法供我共同使用。
通过结构/命名推断关系(符号分析)
常见的数据库设计是在表名之后(例如CustomerId在表上Customer)命名PK列,或者简单地命名PK列Id。
与另一个表具有FK关系的表通常将其相关列命名为与相关表相同。在Order表中,我希望有一个CustomerId列引用表中的CustomerId/ Id列Customer。
这种类型的分析将包括
FirstCustomerId&和SecondCustomerId都引用表中的CustomerId列Customer)通过数据推断关系(统计分析)
正如您所建议的那样,查看数据将使您确定“可能的”参考。如果表中的CustomerId列Order包含表中的Id列不存在的值,Customer那么有理由怀疑这是有效的关系(尽管您永远不知道!)
数据分析的一种简单形式是使用日期和时间。彼此紧邻创建的行更可能彼此相关。如果对于Order创建的每一行,Item在几秒钟内还创建了2至5 行,则这两者之间可能存在关联。
更详细的分析可能会查看使用值的范围和分布。
例如,如果Order表中有一St_Id列-您可能会使用符号分析推断出该列可能与State表或Status表相关。该St_Id列具有6个离散值,并且90%的记录由2个值覆盖。该State表有200行,该Status表有9行。您可以很合理地推断出该St_Id列与Status表有关-它可以更广泛地覆盖表中的行(2/3的行已“使用”,而仅State使用表中3%的行))。
如果您在现有数据库上执行数据分析以收集“现实生活中的数据”,我希望可以将某些模式用作结构推断的指南。当具有大量记录的表的一列具有多次重复的少量值(不一定按顺序排列)时,此列更可能与具有相应少量行的表相关。
综上所述
祝你好运。这是一个有趣的问题,我只是在这里提出了一些想法,但这很大程度上是一个反复试验,数据收集和性能调整的情况。
这是一个不平凡的在大多数情况下,练习。如果您有幸为现代框架(例如 Ruby on Rails 或 CakePHP 或类似框架)分析架构,并且开发人员对遵循列约定非常严格,那么您有合理的机会找到很多,但不是全部, 隐含关系。
即,如果您的表使用列user_id来引用表中的条目users。
请注意:某些实体名称的复数形式可能不规则(entity一个很好的例子:entities,不是entitys)并且这些更难以捕捉(但仍然可能)。但是,无法推断诸如admin_id开发人员加入用户表的键user.id。您需要手动处理这些情况。
您没有指定 RDBMS,但我经常使用 MySQL,我目前正在为自己解决这个问题。
以下 MySQL 脚本将推断列名暗示的大多数关系。然后它会列出它无法找到表名的所有关系,因此至少您知道缺少哪些关系。列出了推断的父母和孩子,以及单数和复数名称,以及隐含的关系:
-- this DB is where MySQL keeps schema information
use information_schema;
-- change this to the DB you want to analyse
set @db_name = "example_DB";
-- infer relationships
-- NB: this won't catch names that pluralise irregularly like category -> categories or bus_id -> buses etc.
select LEFT(COLUMN_NAME, CHAR_LENGTH(COLUMN_NAME) - 3 ) as inferred_parent_singular
, CONCAT(LEFT(COLUMN_NAME, CHAR_LENGTH(COLUMN_NAME) - 3 ),"s") as inferred_parent_plural
, C.TABLE_NAME as child_table
, CONCAT(LEFT(COLUMN_NAME, CHAR_LENGTH(COLUMN_NAME)-3), "s has many ", C.TABLE_NAME) as inferred_relationship
from COLUMNS C
JOIN TABLES T on C.TABLE_NAME = T.TABLE_NAME
and C.TABLE_SCHEMA = T.TABLE_SCHEMA
and T.TABLE_TYPE != "VIEW" -- filter out views; comment this line if you want to include them
where COLUMN_NAME like "%_id" -- look for columns of the form <name>_id
and C.TABLE_SCHEMA = T.TABLE_SCHEMA and T.TABLE_SCHEMA = @db_name
-- and C.TABLE_NAME not like "wwp%" -- uncomment and set a pattern to filter out any tables you DON'T want included, e.g. wordpress tables e.g. wordpress tables
-- finally make sure to filter out any inferred names that aren't really tables
and CONCAT(LEFT(COLUMN_NAME, CHAR_LENGTH(COLUMN_NAME) - 3 ),"s") -- this is the inferred_parent_plural, but can't use column aliases in the where clause sadly
in (select TABLE_NAME from TABLES where TABLE_SCHEMA = @db_name)
;
Run Code Online (Sandbox Code Playgroud)
这将返回如下结果:

然后,您可以检查检测到的任何命名约定异常:
-- Now list any inferred parents that weren't real tables to see see why (irregular plurals and columns not named according to convention)
select LEFT(COLUMN_NAME, CHAR_LENGTH(COLUMN_NAME) - 3 ) as inferred_parent_singular
, CONCAT(LEFT(COLUMN_NAME, CHAR_LENGTH(COLUMN_NAME) - 3 ),"s") as inferred_parent_plural
, C.TABLE_NAME as child_table
from COLUMNS C
JOIN TABLES T on C.TABLE_NAME = T.TABLE_NAME
and C.TABLE_SCHEMA = T.TABLE_SCHEMA
and T.TABLE_TYPE != "VIEW" -- filter out views, comment this line if you want to include them
where COLUMN_NAME like "%_id"
and C.TABLE_SCHEMA = T.TABLE_SCHEMA and T.TABLE_SCHEMA = @db_name
-- and C.TABLE_NAME not like "wwp%" -- uncomment and set a pattern to filter out any tables you DON'T want included, e.g. wordpress tables e.g. wordpress tables
-- this time only include inferred names that aren't real tables
and CONCAT(LEFT(COLUMN_NAME, CHAR_LENGTH(COLUMN_NAME) - 3 ),"s")
not in (select TABLE_NAME from TABLES where TABLE_SCHEMA = @db_name)
;
Run Code Online (Sandbox Code Playgroud)
这将返回如下结果,您可以手动处理:

您可以修改这些脚本以输出对您有用的任何内容,如果您愿意,可以包括外键创建语句。在这里,最后一列是一个简单的“有很多”关系语句。我在我构建的一个名为 pidgin 的工具中使用了它,这是一种快速建模工具,可以根据用非常简单的语法(称为“pidgin”)编写的关系语句动态绘制关系图。您可以在http://pidgin.gruffdavies.com 上查看
我已经在演示数据库上运行了上述脚本,以向您展示您可以预期的结果类型:

我没有在我的脚本中处理不规则复数,但我也可能会尝试一下,至少对于以 -y 结尾的实体。如果您想自己尝试一下,我建议您编写一个存储函数,该函数将<name>_id列名作为参数,剥离该_id部分,然后应用一些启发式方法来尝试正确地进行复数化。
希望有用!
以下产品都声称提供外键发现功能:
ERwin http://www.ascent.co.za/products/ca_erwin_data_profiler.html
和 XCaseForI http://xcasefori.com/discovering/index.html
正如柯克所建议的,能够提供一种相似性排名(例如范围分布和创建时间)的统计方法似乎是正确的方法。..我需要使用 SAS EG 或任何免费工具来实现它。
| 归档时间: |
|
| 查看次数: |
2903 次 |
| 最近记录: |