如何从应用程序级别复制数据?不是数据库级别

Posted

技术标签:

【中文标题】如何从应用程序级别复制数据?不是数据库级别【英文标题】:How to duplicate data from application level? Not database level 【发布时间】:2021-09-11 05:48:28 【问题描述】:

我被我的应用程序中的重复数据卡住了。

假设我有:

PetBooks Table:
id
book_name


Pet:
id
book_id
code
name
type

Petbooks
1 MyPet

Pet:
1 1 CAT1 Josh Cat
2 1 CAT2 Ron Cat
3 1 DOG1 Max Dog

问题 1: 如何复制 Petbook 及其所有宠物?

所以在我复制宠物书后,它应该是这样的

Petbooks
1 MyPet
2 MyPet(Copy)


Pet:
1 1 CAT1 Josh Cat
2 1 CAT2 Ron Cat
3 1 DOG1 Max Dog
4 2 CAT1 Josh Cat
5 2 CAT2 Ron Cat
6 2 DOG1 Max Dog

我认为的解决方案是,获取所有book_id = 1的宠物,然后循环并一个一个插入,但是特别是在有很多数据的情况下,速度很慢。

【问题讨论】:

从数据库中获取所有数据,然后将其插入数据库(尽管我不确定您为什么要从应用程序中执行此操作)。另外,如果有很多数据,复制和粘贴所有数据确实需要一段时间。 @DavidLee 感谢您的评论。是的,我认为是获取所有数据并一一插入,但问题是当数据增长时,获取所有数据时会溢出内存。而且一个一个插入的时候很慢。 【参考方案1】:

好吧,您可以稍微痛苦地执行此操作 - 假设 id 是自动分配的,并且除 id 之外的某些列在原始数据中是唯一的。让我将该专栏称为name

然后:

insert into petbooks (book_name)
    select concat('Copy of ', book_name)
    from petbooks;

那么对于pets,我们必须查找新的id。我们可以使用聚合动态创建查找表:

insert into pets (book_id, code, name, type)
    select pb.max_id, code, name, type)
    from pets p join
         (select name, min(id) as min_id, max(id) as max_id
          from petbooks
          group by name
         ) pb
         on pb.min_id = p.book_id

【讨论】:

谢谢回答,不知道如果id是UUID,应该由应用生成呢? @SusiS 。 . .这让它有点棘手。您可以包含 createdAt 日期/时间并改用它。【参考方案2】:

您可以一个一个地手动处理关系,并将它们组合成一个过程。您可以使用LAST_INSERT_ID() 函数获取最新的id。例如:

CREATE PROCEDURE copy_petbook(petbook_id INT)
BEGIN
    INSERT INTO PetBooks (book_name)
        SELECT CONCAT(book_name, '(Copy)')
        FROM Petbooks
        WHERE id = petbook_id;
    DECLARE last_insert_id BIGINT;
    SET last_insert_id = LAST_INSERT_ID();
    INSERT INTO Pet (book_id, code, name, type)
        SELECT lid.last_insert_id , code, name, type
        FROM Pet JOIN (SELECT last_insert_id) as lid
        WHERE book_id = petbook_id;
END

如果您想为id 列使用UUID,您可以将签名更改为CHAR(36),然后使用UUID() 函数:

CREATE PROCEDURE copy_petbook(petbook_id CHAR(36))
BEGIN
    DECLARE uuid CHAR(36);

    -- Generate an UUID which has not been used.
    REPEAT
        SET uuid = UUID();
    UNTIL (SELECT COUNT(*) FROM PetBooks WHERE id = uuid) = 0 END REPEAT;

    -- Insert rows with the UUID
    INSERT INTO PetBooks (id, book_name)
        SELECT u.uuid, CONCAT(book_name, '(Copy)')
        FROM Petbooks JOIN (SELECT uuid) as u
        WHERE id = petbook_id;
    INSERT INTO Pet (book_id, code, name, type)
        SELECT u.uuid, code, name, type
        FROM Pet JOIN (SELECT uuid) as u
        WHERE book_id = petbook_id;
END

如果您还对其他表中的id 列使用 UUID,则可以以相同方式生成更多 UUID。

最后,只需调用过程:

CALL copy_petbook(/* Put the id here. */);

【讨论】:

以上是关于如何从应用程序级别复制数据?不是数据库级别的主要内容,如果未能解决你的问题,请参考以下文章

使用复制向导时更改兼容性级别

如何使用 SQL Query 在 SQL Server 中的表级别进行镜像或复制

如何从应用程序级别设置 postgres 查询执行超时?

如何在 dll 级别读取 app.config。? [复制]

本地存储如何在域级别上工作?两个站点使用相同的密钥来存储数据? [复制]

MySQL 是如何实现四大隔离级别的