MySQL Workbench 手册  /  ...  /  教程:使用 MyISAM 生成外键

C.6.2 教程:使用 MyISAM 生成外键

EER 图可用于可视化复杂的数据库模式。它们通常是为现有数据库创建的,用于阐明其用途或记录它们。MySQL Workbench 提供了对现有数据库进行逆向工程,然后自动创建 EER 图的功能。在这种情况下,将自动绘制表中外键之间的关系线。这种图形表示使表之间的关系更容易理解。但是,较旧的 MyISAM 存储引擎不支持外键。这意味着对逆向工程的 MyISAM 表不会自动绘制表之间的关系线,从而使数据库更难理解。本教程中创建的插件通过使用外键的命名约定通常为 tablename_primarykeyname 的事实来解决此问题。使用此约定,可以在对数据库进行逆向工程后自动创建外键,这将导致在 EER 图中绘制关系线。

算法

此任务的基本算法如下

for each table in the schema
   for each column in the table
      look for another table whose name and primary key name match the current column name
      if such a table is found, add a foreign key referencing it

由于迭代完整表列表以查找匹配项对于具有大量表的模型来说可能很慢,因此有必要通过预先计算给定模式中所有可能的外键名称来进行优化。

import grt

def auto_create_fks(schema):
   fk_name_format = "%(table)s_%(pk)s"
   possible_fks = {}
   # create the list of possible foreign keys from the list of tables
   for table in schema.tables:
      if table.primaryKey:
         format_args = {'table':table.name, 'pk':table.primaryKey.name}
         fkname = fk_name_format % format_args
         possible_fks[fkname] = table

   # go through all tables in schema, this time to find columns that may be a fk
   for table in schema.tables:
      for column in table.columns:
         if possible_fks.has_key(column.name):
            ref_table = possible_fks[column.name]
            if ref_table.primaryKey.formattedType != column.type:
               continue
            fk = table.createForeignKey(column.name+"_fk")
            fk.referencedTable = ref_table
            fk.columns.append(column)
            fk.referencedColumn.append(ref_table.primaryKey)
            print "Created foreign key %s from %s.%s to %s.%s" \
            % (fk.name, table.name, column.name, ref_table.name, ref_table.primaryKey.name)

auto_create_fks(grt.root.wb.doc.physicalModels[0].catalog.schemata[0])

从脚本创建插件

要从任意脚本创建插件,首先需要使文件成为模块,并从中导出所需函数。然后需要将模块声明为插件,并指定返回类型和输入参数。

from wb import *
import grt

ModuleInfo = DefineModule(name="AutoFK", author="John Doe", version="1.0")

@ModuleInfo.plugin("sample.createGuessedForeignKeys",
  caption="Create Foreign Keys from ColumnNames",
  input=[wbinputs.objectOfClass("db.mysql.schema")],
  groups=["Overview/Utility"])

@ModuleInfo.export(grt.INT, grt.classes.db_mysql_Schema)
def auto_create_fks(schema):
   ...

通过添加前面的代码,将导出 auto_create_fks() 函数,并将其添加到模型概述中的架构上下文菜单中。调用时,它会接收当前选择的架构作为其输入。