仅使用SQL的MySQL插入
是否可以仅使用SQL和MySQL获得下面的“输出” 示例数据:为了更好地用一个示例进行阐述,让我们假设我正在加载一个文件,其中包含员工姓名、他们过去占用过的办公室以及他们的职务历史,并用一个选项卡隔开 文件: 输出:在这种情况下也是如此。这些表应该如下所示:仅使用SQL的MySQL插入,sql,mysql,insert,Sql,Mysql,Insert,是否可以仅使用SQL和MySQL获得下面的“输出” 示例数据:为了更好地用一个示例进行阐述,让我们假设我正在加载一个文件,其中包含员工姓名、他们过去占用过的办公室以及他们的职务历史,并用一个选项卡隔开 文件: 输出:在这种情况下也是如此。这些表应该如下所示: 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 S
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;
也许您可以通过使用MySQL语法使其工作 根据规格,您可以这样使用:
LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
LINES TERMINATED BY '\n' STARTING BY ''
并设置如下选项:
LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
LINES TERMINATED BY '\n' STARTING BY ''
编辑:添加一个提案:
至于临时表的建议,我
只是不明白临时表格
与“真实”表格不同;
意思是我知道什么是临时表,
只是不知道这会是什么样的结果
加载过程中的差异
临时表允许您将数据加载到单个平面表中。例如,您可以在SQL中实现以下过程:
插入到。。。从
中选择以将数据加载到主表中(员工、职务、办公室-so 3查询)这就是我的意思,它必须是脚本。MySQL无法神奇地从平面数据映射关系。你需要自己去做。您可以使用上面的步骤在SQL中编写它,但使用您熟悉的脚本语言似乎更简单,这样可以避免使用
加载数据时可能出现的各种权限/访问问题。定期或从您的呼叫应用程序中删除此表,无论何时完成
create table TmpEmp (
EmployeeName char(50) not null,
OfficeHistory int null,
JobLevelHistory char(30) null);
在此表上创建触发器
delimiter |
CREATE TRIGGER tg_TmpEmp BEFORE INSERT ON TmpEmp
FOR EACH ROW
BEGIN
IF not exists (select * from Employee where Name = NEW.EmployeeName) THEN
INSERT INTO Employee(name)
select NEW.EmployeeName;
END IF;
IF not exists (select * from Office where office_number = NEW.OfficeHistory) THEN
INSERT INTO Office(office_number)
select NEW.OfficeHistory;
END IF;
IF not exists (select * from JobTitle where title = NEW.JobLevelHistory) THEN
INSERT INTO JobTitle(title)
select NEW.JobLevelHistory;
END IF;
INSERT INTO Employee2JobTitle(employee_id,job_title_id)
select E.id, T.id
from Employee E
inner join JobTitle T on T.title = NEW.JobLevelHistory
where E.Name = NEW.EmployeeName
AND not exists (select *
from Employee2JobTitle J
where J.employee_id = E.id and J.job_title_id = T.id);
INSERT INTO Employee2Office(employee_id,office_id)
select E.id, O.id
from Employee E
inner join Office O on O.office_number = NEW.OfficeHistory
where E.Name = NEW.EmployeeName
AND not exists (select *
from Employee2Office J
where J.employee_id = E.id and J.office_id = O.id);
END; |
delimiter ;
注意:此触发器和表的好处在于,无论您使用的是加载文件还是普通插入,它都可以工作。触发器被触发,并在需要的地方添加数据
测试一下
insert tmpEmp(EmployeeName,OfficeHistory,JobLevelHistory)
select 'John Smith',501,'Engineer' union all
select 'John Smith',601,'Senior Engineer' union all
select 'John Smith',701,'Manager' union all
select 'Alex Button',601,'Senior Assistant' union all
select 'Alex Button',454,'Manager';
truncate table tmpEmp;
我相信你可能会以某种方式使用临时表,但我认为为一个广泛安装的解释器(sh、bash、php、python、perl等等)编写一个shell脚本要容易得多。我真的不明白你想说什么。是否希望使用一个insert查询将所有加载的数据一次插入到所有表中?请你进一步解释一下你想做什么好吗?对不起,我很难理解你到底想做什么。您希望将数据导入到已经创建的数据库中,还是动态创建数据库,或者具体是什么?@Bullers:如果您希望将数据文件加载到与数据具有相同列的表中,这将是一件事。你可以开箱即用(参见hade的答案)。。。但是没有一种机制可以从一个平面数据文件创建多个相关记录。你必须把它写下来。。。您可能可以直接用SQL编写脚本,但正如我所说,除非您没有其他可用语言,否则我看不出使用SQL比其他语言有多大优势。您在“输出:所以在本例中,表应该是:”下写的内容正是数据库的布局方式。目前它根本没有正常化。这就是为什么你对MySQL不能为你做这件事感到惊讶的原因:它不应该这样做。这只适用于将单个表输入呈现到数据库中的单个表。在我的示例中,它是一个按行插入的单表输入。在执行插入之前,每行插入都会检查数据是否已经存在。并将主键从每个insert传递到复合表Employee2JobTitle和Employee2Office;支持多对多关系。可能是因为我误解了你的答案,因为我甚至不是SQL新手,但这是我对它的理解。谢谢你的发帖@错误,你是对的。不如像@prodigitalson在评论中建议的那样,先把所有东西都放到临时表中。从那里,您可以遍历该表,将数据插入适当的表中。对不起,这里没有像样的帮助…+2没什么大不了的,你的评论都投了赞成票,因为你是想帮忙;由于答案不能直接回答我的问题,所以无法投票,但我也没有包括我知道一对一上传是可能的。至于临时表的建议,我只是不明白临时表与“真实”表有何不同;意思是我知道什么是临时表,只是不知道它在加载过程中会有什么不同。@错误:我又添加了一个可行的解决方案。我很快就试过了,它似乎正好构建了Employee2Office映射表。我希望它更接近:)。+1很酷,谢谢-我一直在考虑你的更新,试图解决它,我会再次回复,一旦我有机会解决它,并尝试它…:-)关闭外键检查不是一个选项,因为它会破坏引用完整性;这意味着,如果关闭该控件,即使将其重新打开,也永远不会知道数据库的状态是否与引用完整性相关。原因是,当控件重新打开时,将不会检查在关闭检查时发生的任何事务;这意味着引用完整性可能会被破坏,但数据库没有被设置为知道它是;至少MySQL是这样工作的。@大错特错:如果你愿意的话,你可以让它开着。我通常会在这种情况下禁用它们,因为不会有约束中断的实例(
insert tmpEmp(EmployeeName,OfficeHistory,JobLevelHistory)
select 'John Smith',501,'Engineer' union all
select 'John Smith',601,'Senior Engineer' union all
select 'John Smith',701,'Manager' union all
select 'Alex Button',601,'Senior Assistant' union all
select 'Alex Button',454,'Manager';
truncate table tmpEmp;