Sql 表记录的深度复制-复制记录和所有相关数据

Sql 表记录的深度复制-复制记录和所有相关数据,sql,postgresql,Sql,Postgresql,“深度复制”表中单个记录的有效方法是什么。“深度复制”指的是创建一个新记录,该记录是原始记录的副本(使用新的主键除外),然后还为与原始记录有关系的每个其他表中的每个数据点创建一个新的、重复的记录(除了这些记录现在会引用此新副本) 例如,如果有一个公司、部门和员工的表格,每个公司都有多个部门,员工可能在一个或多个部门工作,那么我如何创建一个新公司,它是另一个公司的完全复制品,包括相同的部门和相同的员工(除了不同的主键)在不知道表的结构的情况下,我只能做一些假设。我会这样做(见下文)。注意内联注释

“深度复制”表中单个记录的有效方法是什么。“深度复制”指的是创建一个新记录,该记录是原始记录的副本(使用新的主键除外),然后还为与原始记录有关系的每个其他表中的每个数据点创建一个新的、重复的记录(除了这些记录现在会引用此新副本)


例如,如果有一个公司、部门和员工的表格,每个公司都有多个部门,员工可能在一个或多个部门工作,那么我如何创建一个新公司,它是另一个公司的完全复制品,包括相同的部门和相同的员工(除了不同的主键)

在不知道表的结构的情况下,我只能做一些假设。我会这样做(见下文)。注意内联注释

CREATE OR REPLACE FUNCTION fn_copy_company(source_company_id INT)
RETURNS INT AS $$

    DECLARE new_company_id INT;

BEGIN

    -- Copy the company data
    INSERT INTO companies (name)
    SELECT name FROM companies WHERE id = source_company_id
    RETURNING id INTO new_company_id;

    -- Copy the departments and return the newly created record(s) as a CTE
    WITH new_departments AS
    (
        INSERT INTO departments (company_id, name)
        SELECT new_company_id, name FROM departments WHERE company_id = source_company_id
        RETURNING *
    )

    -- Copy all employees belonging to the department(s) with new department ids
    INSERT INTO employees (department_id, name)
    SELECT
        ndpt.department_id,
        emp.name
    FROM
        new_departments ndpt
    INNER JOIN
        departments sdpt
        ON  (ndpt.company_id = sdpt.company_id)
        AND (ndpt.name = sdpt.name)
    INNER JOIN
        employees emp
        ON  (sdpt.department_id = emp.department_id);

    -- Returns the new company id
    RETURN new_company_id;

END; $$ LANGUAGE PLPGSQL VOLATILE;

注意:假设每个表都有一个id字段,该字段有一个序列。

在不知道表结构的情况下,我只能做一些假设。我会这样做(见下文)。注意内联注释

CREATE OR REPLACE FUNCTION fn_copy_company(source_company_id INT)
RETURNS INT AS $$

    DECLARE new_company_id INT;

BEGIN

    -- Copy the company data
    INSERT INTO companies (name)
    SELECT name FROM companies WHERE id = source_company_id
    RETURNING id INTO new_company_id;

    -- Copy the departments and return the newly created record(s) as a CTE
    WITH new_departments AS
    (
        INSERT INTO departments (company_id, name)
        SELECT new_company_id, name FROM departments WHERE company_id = source_company_id
        RETURNING *
    )

    -- Copy all employees belonging to the department(s) with new department ids
    INSERT INTO employees (department_id, name)
    SELECT
        ndpt.department_id,
        emp.name
    FROM
        new_departments ndpt
    INNER JOIN
        departments sdpt
        ON  (ndpt.company_id = sdpt.company_id)
        AND (ndpt.name = sdpt.name)
    INNER JOIN
        employees emp
        ON  (sdpt.department_id = emp.department_id);

    -- Returns the new company id
    RETURN new_company_id;

END; $$ LANGUAGE PLPGSQL VOLATILE;

注意:假设每个表都有一个id字段,该字段有一个序列。

是否使用外键?如果是,您可能需要做更多的工作,因为您没有复制相同的主键。将使用外键,例如,如果我们复制一家公司,我们将创建新的、重复的部门,所有部门都将引用该新公司,等等。这是指一次性操作,还是希望在每次插入/更新后都执行?仅此一次就足够了,或者可以根据需要编写脚本并执行的。是否使用外键?如果是,您可能需要多做一些工作,因为您没有复制相同的主键。将使用外键,例如,如果我们复制一家公司,我们将创建新的、重复的部门,所有部门都将引用该新公司,等等。这是指一次性操作,还是希望在每次插入/更新后都执行?仅此一次就足够了,或者可以根据需要编写脚本并执行的脚本。