0

再次在这里寻求您的帮助!

我有两个问题要问你和两个 sql 表:

  • 表格1

    [ ID_T1, T1_NAME,      T1_VALUE   ]
    
        0 |   name_t1_0 |  value_t1_0
        1 |   name_t1_1 |  value_t1_1
        2 |   name_t1_2 |  value_t1_2
        3 |   name_t1_3 |  value_t1_3
    
  • 表_2

    [ ID_T2,  ID_T1_IN_T2,   T2_NAME,   T2_VALUE    ]
    
        0        | 0 |    name_t2_00 | value_t2_00
        1        | 0 |    name_t2_10 | value_t2_10
        2        | 0 |    name_t2_20 | value_t2_20
        3        | 0 |    name_t2_30 | value_t2_30
        0        | 1 |    name_t2_01 | value_t2_01
        1        | 1 |    name_t2_11 | value_t2_11
        0        | 2 |    name_t2_02 | value_t2_02
        1        | 2 |    name_t2_12 | value_t2_12
    

ID_T1 是唯一的渐进索引。TABLE_1 中的每个 ID_T1 可以在 ID_T1_IN_T2 列中出现 N 次。

ID_T2 是与每个 ID_T1 相关联的渐进索引。

这意味着对于 TABLE_1 中的每一行,我们可以在 TABLE_2 中有 N 行。

  • 问题 #1:当从 TABLE_1 中删除一行时,如何自动更新 ID_T1_IN_T2 值?

示例:从表 1 中删除 ID_T1 = 0 的行。预期结果如下(0 后的 ID_T1 减少,ID_T1_IN_T2 也减少)

表格1

 [ ID_T1,  T1_NAME,    T1_VALUE   ]
    0 |   name_t1_1 |  value_t1_1
    1 |   name_t1_2 |  value_t1_2
    2 |   name_t1_3 |  value_t1_3

表_2

[ ID_T2,  ID_T1_IN_T2,   T2_NAME,     T2_VALUE    ]
    0        | 0 |      name_t2_01 |  value_t2_01
    1        | 0 |      name_t2_11 |  value_t2_11
    0        | 1 |      name_t2_02 |  value_t2_02
    1        | 1 |      name_t2_12 |  value_t2_12

  • 问题 #2:如何在删除一行时自动更新 ID_T2 值?

示例:从刚刚更新的 TABLE_2 中删除 ID_T2 = 0 且 ID_T1_IN_T2=0 的行。预期结果如下(0后的ID_T2减少,ID_T1_IN_T2保持不变)

[ ID_T2,  ID_T1_IN_T2,   T2_NAME,     T2_VALUE    ]
    0        | 0 |      name_t2_11 |  value_t2_11
    0        | 1 |      name_t2_02 |  value_t2_02
    1        | 1 |      name_t2_12 |  value_t2_12

在这些情况下,您建议做什么?

请注意,删除表并重新创建它们不被视为解决方案,因为它很脏且性能极差(这是我暂时采用的解决方案)。

4

2 回答 2

2

您的 C++ 应用程序没有使用良好的数据库方法。我建议您使用视图触发器来解决此问题。

例子:

您的主表变为T1and T2

CREATE TABLE T1(ID, T1_NAME, T1_VALUE);
CREATE TABLE T2(ID, ID_T1, T2_NAME, T2_VALUE);

那些ID变得固定!你不应该改变它们!

接下来,辅助视图,将真实视图映射ID到动态视图:

CREATE VIEW T1_IDX AS SELECT DISTINCT ID, (SELECT COUNT() FROM (SELECT DISTINCT ID FROM T1 AS _ WHERE ID<T1.ID)) AS ID_T1 FROM T1;
CREATE VIEW T2_IDX AS SELECT DISTINCT ID, (SELECT COUNT() FROM (SELECT DISTINCT ID FROM T2 AS _ WHERE ID<T2.ID)) AS ID_T2 FROM T2;

TABLE_1并被TABLE_2模仿为视图:

CREATE VIEW TABLE_1 AS
    SELECT ID_T1, T1_NAME, T1_VALUE FROM T1
    JOIN T1_IDX ON T1.ID=T1_IDX.ID;
CREATE VIEW TABLE_2 AS
    SELECT ID_T2, T1_IDX.ID_T1 AS ID_T1_IN_T2, T2_NAME, T2_VALUE FROM T2
    JOIN T2_IDX ON T2.ID=T2_IDX.ID
    JOIN T1_IDX ON T2.ID_T1=T1_IDX.ID;

并且DELETE声明TABLE_1变成了以下映射TRIGGER

CREATE TRIGGER TABLE_1_DELETE INSTEAD OF DELETE ON TABLE_1 BEGIN
    DELETE FROM T2 WHERE ID_T1 = (SELECT ID FROM T1_IDX WHERE ID_T1=OLD.ID_T1);
    DELETE FROM T1 WHERE ID = (SELECT ID FROM T1_IDX WHERE ID_T1=OLD.ID_T1);
END;

通过这种自动化,您的 C++ 应用程序将看到TABLE_1计算索引,而不是真实索引,并且DELETE操作由 SQLite 引擎处理以对真实表进行操作。

注意:视图上的其他操作,超出SELECTDELETE FROM TABLE_1,如果需要,必须作为触发器实现!

于 2013-10-17T10:35:52.697 回答
1

另一个更简单的选择。

只需添加一个触发器:

CREATE TRIGGER TABLE_1_DELETE AFTER DELETE ON TABLE_1 BEGIN
    UPDATE TABLE_1 SET ID_T1=ID_T1-1 WHERE ID_T1>OLD.ID_T1;
    -- DELETE FROM TABLE_2 WHERE ID_T1_IN_T2=OLD.ID_T1;
    UPDATE TABLE_2 SET ID_T1_IN_T2=ID_T1_IN_T2-1 WHERE ID_T1_IN_T2>OLD.ID_T1;
    END;
CREATE TRIGGER TABLE_2_DELETE AFTER DELETE ON TABLE_2 BEGIN
    UPDATE TABLE_2 SET ID_T2=ID_T2-1 WHERE ID_T2>OLD.ID_T2 AND ID_T1_IN_T2=OLD.ID_T1_IN_T2;
    END;

这些触发器将在删除后立即更新索引。

如果你删除了注释行,delete onTABLE_1也会导致删除 中对应的记录TABLE_2

于 2013-10-17T10:59:34.307 回答