Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
仅使用SQL的MySQL插入_Sql_Mysql_Insert - Fatal编程技术网

仅使用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

是否可以仅使用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 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;