使用Pentaho Kettle,如何在保持参照完整性的同时从单个表中加载多个表?

时间:2010-11-14 00:50:39

标签: mysql etl pentaho kettle

需要将具有100,000多条记录的单个文件中的数据加载到MySQL上的多个表中,以维护文件/表中定义的关系;意味着关系已经匹配。该解决方案应该适用于最新版本的MySQL,并且需要使用InnoDB引擎; MyISAM不支持外键。

我是使用Pentaho数据集成(又名Kettle)的全新手段,任何指针都会受到赞赏。

我可能会补充说,要求不禁用外键约束。由于我的理解是,如果数据库的引用完整性存在问题,MySQL将不会在重新打开外键约束时检查引用完整性。 消息来源: 5.1.4。服务器系统变量 - foreign_key_checks

如果插入失败,或者无法保持参照完整性,则所有方法都应包括验证和回滚策略中的一些。

同样,对此全新,并尽力提供尽可能多的信息,如果您有任何疑问或要求澄清 - 请告诉我。

如果您能够从超级的kjb和ktr文件(作业/转换)发布XML。甚至可能追捕你在任何地方所做的每一条评论/答案,然后投票给他们...... :-) ......真的,找到答案对我来说真的很重要。

谢谢!


示例数据:为了更好地举例说明,我们假设我正在尝试加载包含员工姓名的文件,他们过去占用的办公室以及由标签分隔的职位名称历史记录

文件:

EmployeeName<tab>OfficeHistory<tab>JobLevelHistory
John Smith<tab>501<tab>Engineer
John Smith<tab>601<tab>Senior Engineer
John Smith<tab>701<tab>Manager
Alex Button<tab>601<tab>Senior Assistant
Alex Button<tab>454<tab>Manager

注意:单个表数据库是完全规范化的(与单个表一样多) - 例如,在“John Smith”的情况下,只有一个John Smith;意思是没有重复会导致参照完整性的冲突。

MyOffice数据库架构包含以下表格:

Employee (nId, name)
Office (nId, number)
JobTitle (nId, titleName)
Employee2Office (nEmpID, nOfficeId)
Employee2JobTitle (nEmpId, nJobTitleID)

所以在这种情况下。表格应如下所示:

Employee
1 John Smith
2 Alex Button

Office
1 501
2 601
3 701
4 454

JobTitle
1 Engineer
2 Senior Engineer
3 Manager
4 Senior Assistant

Employee2Office
1 1
1 2
1 3
2 2
2 4

Employee2JobTitle
1 1
1 2
1 3
2 4
2 3

这是创建数据库和表格的MySQL DDL:

create database MyOffice2;

use MyOffice2;

CREATE TABLE Employee (
      id MEDIUMINT NOT NULL AUTO_INCREMENT,
      name CHAR(50) NOT NULL,
      PRIMARY KEY (id)
    ) ENGINE=InnoDB;

CREATE TABLE Office (
  id MEDIUMINT NOT NULL AUTO_INCREMENT,
  office_number INT NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE JobTitle (
  id MEDIUMINT NOT NULL AUTO_INCREMENT,
  title CHAR(30) NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE Employee2JobTitle (
  employee_id MEDIUMINT NOT NULL,
  job_title_id MEDIUMINT NOT NULL,
  FOREIGN KEY (employee_id) REFERENCES Employee(id),
  FOREIGN KEY (job_title_id) REFERENCES JobTitle(id),
  PRIMARY KEY (employee_id, job_title_id)
) ENGINE=InnoDB;

CREATE TABLE Employee2Office (
  employee_id MEDIUMINT NOT NULL,
  office_id MEDIUMINT NOT NULL,
  FOREIGN KEY (employee_id) REFERENCES Employee(id),
  FOREIGN KEY (office_id) REFERENCES Office(id),
  PRIMARY KEY (employee_id, office_id)
) ENGINE=InnoDB;



我对回答所选答案的说明:

PREP:

  1. (a)使用示例数据,通过将<TAB>更改为逗号分隔来创建CSV。
  2. (b)使用MySQL DDL示例安装MySQL并创建示例数据库
  3. (c)安装Kettle(它是基于Java的,将运行任何运行Java的东西)
  4. (d)下载KTR文件
  5. 逐步数据流:(我的笔记)

    1. 在Kettle中打开KTR文件,然后双击“CSV文件输入”并浏览到您创建的CSV文件。分隔符应已设置为逗号。然后单击OKAY。
    2. 双击“插入员工”并选择数据库连接器,然后按照Creating a New Database Connection
    3. 上的说明进行操作

1 个答案:

答案 0 :(得分:33)

我根据您提供的内容整理了一个示例transformation(right click and choose save link)。我觉得有点不确定的唯一步骤是最后一个表输入。我基本上是将连接数据写入表中,如果已存在特定关系则让它失败。

注意:

此解决方案并未真正满足“所有方法都应包含一些验证和回滚策略,如果插入失败,或者无法保持参照完整性。”标准,虽然它可能不会失败。如果你真的想要设置复杂的东西我们可以,但这绝对可以让你进行这些转换。

alt text

按步骤分组数据

1。我们首先阅读您的文件。在我的情况下,我将其转换为CSV,但标签也很好。 alt text

2. 现在我们要使用combination lookup/update将员工姓名插入到Employee表中。 在插入之后,我们将employee_id作为id附加到我们的数据流,并从数据流中删除EmployeeName

alt text

3。我们只是使用“选择值”步骤将id字段重命名为employee_id alt text

4. 插入职位名称就像我们做员工一样,并将标题ID附加到我们的数据流中,同时从数据流中删除JobLevelHistory

alt text

5. 简单地将标题ID重命名为title_id(参见步骤3) alt text

6. :插入办公室,获取ID,从流中删除OfficeHistory。

alt text

7. 简单地将办公室ID重命名为office_id(参见步骤3)

alt text

8. 将数据从最后一步复制到两个分别为employee_id,office_idemployee_id,title_id的流中。

alt text alt text

9. 使用表插入来插入连接数据。我已选择忽略插入错误,因为可能存在重复,PK约束会使某些行失败。

输出表

alt text

alt text

alt text

alt text

alt text