用sqlite中的另一个集替换行集

时间:2016-07-27 20:33:35

标签: sql sqlite

我的表values包含这样的列:

id:       integer primary key
value:    varchar(128)
type_id:  integer (foreign key)
owner_id: integer (foreign key)

以及一些示例数据:

id     value  type_id  owner_id
...
5      aaa    0        1
6      bbb    0        2             // Rows
7      ccc    1        2             // to
8      ddd    1        2             // be
9      eee    2        2             // replaced
10     fff    0        3
...

现在我想用一组新数据替换owner_id == 2的所有行。简单方法是DELETE == 2和owner_id新行的所有行INSERT。不过我想知道是否还有其他解决方案?

就我而言:

  • 新集可能包含完全相同的数据(无需任何操作)。
  • 或者它可以包含相同的数据但只有一行(需要删除)。示例:不再bbb type_id == 0
  • 或者还有一行(需要插入)。示例:bbbcccdddeee的{​​{1}}加type_id ggg = 1的值完全相同
  • type_id列中的某个值已更改(需要更新)。示例:完全相同的数据,而不是values ccc == 1,type_id ggg == 1
  • 它也可以是上述任何操作的组合。

我试图避免type_id + DELETE我会有很多此类更新并使用此类方法INSERT的原因将开始快速增长。

1 个答案:

答案 0 :(得分:1)

由于您似乎没有回应评论,让我们开始吧 根据我上面的评论,我做了一些皱纹(看起来像我)的一些皱纹:

  • 在您的请求中:“不再使用type_id == 1 bbb” - 这不是您的示例数据的一部分 - 适用于 type_id 0)和
  • 您的示例数据:( s“ccc”“ddd”代表 type_id 1和 owner_id - 选择独特的 owner_id type_id 组合。) 如果适用,您可以通过以下方式强制执行后者:
    CREATE UNIQUE INDEX ValuesTable_TypeOwner ON ValuesTable(owner_id, type_id);

注意:我更改了表名,因为 VALUES 是一个SQL保留字。

您可能想要尝试(从名为更改的表中提取应用修改):

删除不再存在的 owner_id type_id 组合:

WITH
To_Delete (id) AS (
  SELECT
    id
  FROM ValuesTable V
  JOIN Changes C
    ON V.owner_id = C.owner_id
    AND V.type_id
        NOT IN (SELECT type_id
                FROM Changes
                WHERE owner_id = C.owner_id)
)
DELETE FROM ValuesTable
WHERE id IN (SELECT id FROM To_Delete)
;

更新偏离值:

WITH
To_Update (id) AS (
  SELECT
    id
  FROM ValuesTable V
  JOIN Changes C
    ON V.owner_id = C.owner_id
    AND V.type_id = C.type_id
    AND V.value <> C.value
)
UPDATE ValuesTable
SET value = (SELECT value
             FROM Changes
             WHERE ValuesTable.owner_id = owner_id
                   AND ValuesTable.type_id = type_id
            )
WHERE id IN (SELECT id FROM To_Update)
;

插入新的owner_id type_id组合:

WITH
To_Insert (value, type_id, owner_id) AS (
  SELECT
    value
    , type_id
    , owner_id
  FROM Changes
  WHERE NOT EXISTS
        (SELECT 1
         FROM ValuesTable
         WHERE Changes.owner_id = owner_id
         AND Changes.type_id = type_id
        )
)
INSERT INTO ValuesTable (value, type_id, owner_id)
SELECT value, type_id, owner_id FROM To_Insert
;

开始
ValuesTable                             Changes
| id | value | type_id | owner_id |    | value | type_id | owner_id |
|----|-------|---------|----------|    |-------|---------|----------|
|  5 |   aaa |       0 |        1 |    |   ccc |       1 |        2 |
|  6 |   bbb |       0 |        2 |    |   ddd |       2 |        2 |
|  7 |   ccc |       1 |        2 |    |   xxx |       3 |        2 |
|  8 |   ddd |       2 |        2 |    |   yyy |       4 |        2 |
|  9 |   eee |       3 |        2 |    
| 10 |   fff |       0 |        3 |    

它返回:

| id | value | type_id | owner_id |
|----|-------|---------|----------|
|  5 |   aaa |       0 |        1 |
|  7 |   ccc |       1 |        2 |
|  8 |   ddd |       2 |        2 |
|  9 |   xxx |       3 |        2 |
| 11 |   yyy |       4 |        2 |
| 10 |   fff |       0 |        3 |

查看实际操作:SQL Fiddle

注意:当然,WITH子句可以相应地扩展,而不是使用更改表。

请评论是否需要调整/进一步详细说明。