【问题标题】:How to copy nested SQL tables (implementing a change history)如何复制嵌套 SQL 表(实现更改历史记录)
【发布时间】:2020-09-16 09:25:40
【问题描述】:

我是一名软件开发学徒,目前正在尝试实施一个简单的清单,但同时还增加了跟踪所述清单的每个版本/每次更改的麻烦。这意味着,无论何时添加新类别或更改其名称(问题相同),都会在“ChecklistVersion”表中创建一个新行,并将最新 ChecklistVersion 的所有类别和问题复制到新行。这是保存整个更改历史所必需的。请参阅以下database scheme

这个数据库的另一个怪癖是,它由不使用主键自动增量的 CMS (Intrexx) 使用和创建。

为了进一步说明,该方案用于表示以下内容:

  • 清单 A

    • 版本 1
      • 类别 1
        • 问题 1
        • ...
        • 问题n
      • 类别 2
        • 问题 3
    • 版本 2
      • 类别 1
        • 问题 1
  • 清单 B

    • 版本 1
    • ...

到目前为止,复制过程适用于类别,但我一直在复制问题。这些是我的疑问:

首先,创建一个新的 ChecklistVersion 条目并返回其 ID:

insert into ChecklistVersion
(
    ID,
    ChecklistID
)
values
(
    (
        select coalesce(max(ID)+1, 1) /* Get next ID */
        from ChecklistVersion
    ),
    ? /* This value gets replaced by the checklist ID in Java code */
)
returning ID;

下一步是复制类别:

insert into Category
(
    ID,
    ChecklistVersionID,
    Name
)
select
       (select max(ID)+1 from Category) - 1 + ROW_NUMBER() over (order by ID), /* See (1) below */
       ?, /* This gets replaced by the ChecklistVersion ID returned by the previous query */
       Name
from Category
where ChecklistVersionID = ?; /* Gets replaced in code by the most recent ChecklistVersion ID
                                 which serves as the source for the categories to be copied */

(1):该行生成类别的下一个最高 ID,它很难看,但我不知道更好的方法。子选择只执行一次,因此 ROW_NUMBER() 需要进一步递增。

现在想象以下表格条目:

           Category                              Question

| ID | ChecklistVersionID | Name |    | ID | CategoryID | Text      |
|----|--------------------|------|    |----|------------|-----------|
| 1  | 1                  | Cat1 |    | 1  | 2          | Question1 |
| 2  | 1                  | Cat2 |    | 2  | 1          | Question2 |
                                      | 3  | 2          | Question3 |

成功复制 ID 为 1 的 ChecklistVersion 后,预期会出现以下结果:

           Category                              Question

| ID | ChecklistVersionID | Name |    | ID | CategoryID | Text      |
|----|--------------------|------|    |----|------------|-----------|
| 1  | 1                  | Cat1 |    | 1  | 2          | Question1 |
| 2  | 1                  | Cat2 |    | 2  | 1          | Question2 |
| 3  | 2                  | Cat1 |    | 3  | 2          | Question3 |
| 4  | 2                  | Cat2 |    | 4  | 4          | Question1 |
                                      | 5  | 3          | Question2 |
                                      | 6  | 4          | Question3 |

所以每个问题不仅需要复制,还需要分配相应的new CategoryID。因此,不知何故,我需要获取类别的先前 ID 和新 ID 之间的映射(本例中为 1 -> 3 和 2 -> 4)。

我希望我的问题很清楚,感谢任何帮助!

【问题讨论】:

    标签: sql postgresql jdbc copying


    【解决方案1】:

    我已经找到了使用临时表的解决方案,以便在插入类别和问题时使用选择语句中的映射,这是我的解决方案:

    /* Create temporary table with the categories that will be copied,
       provides the mapping between the old and new category IDs (CopyID and ID).
       This is pretty much equivalent to the select statement in the original insertion
       query. */
    create temp table CategoriesToCopy as
    select (select max(ID)+1 from Category) - 1 + ROW_NUMBER() over (order by ID) as CopyID,
           ? as ChecklistVersionID,
           Name,
           ID
    from Category
    where ChecklistVersionID = ?;
    
    /* Insert categories just like before, but using the temporary
       table instead */
    insert into Category
    (
        ID,
        ChecklistVersionID,
        Name
    )
    select CopyID, ChecklistVersionID, Name
    from CategoriesToCopy;
    
    /* Insert questions using mapping of temporary table */
    insert into Question
    (
        ID,
        CategoryID,
        QuestionText
    )
    select
        (select max(ID)+1 from Question) - 1 + ROW_NUMBER() over (order by Question.ID),
        CategoriesToCopy.CopyID, /* use new category ID for copied question */
        Question.QuestionText
    from Question
    inner join CategoriesToCopy /* join rows which correspond to the old category IDs */
        on CategoriesToCopy.ID = Question.CategoryID;
    
    /* Delete temporary table */
    drop table CategoriesToCopy;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-31
      • 1970-01-01
      • 2012-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-19
      • 1970-01-01
      相关资源
      最近更新 更多