MySQL 工作台  / 附录 C 扩展工作台  / C.6 教程:编写插件  /  C.6.2 教程:使用 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()函数将被导出并将添加到模型概述中的模式上下文菜单中。调用时,它接收当前选择的模式作为其输入。