根据时间戳将主键添加到表中

时间:2011-05-23 19:58:31

标签: sql oracle primary-key

我们假设我们有以下表结构和值:

FooTable:
    foo1    foo2   timestamp
     1       1      1
     2       2      1
     2       1      2

目前桌面上没有主键约束。

问题:

在Oracle中,将foo1作为表的主键的最佳方法是什么?假设:

  1. 没有两行具有相同的时间戳和foo1值
  2. 具有最新时间戳的行优先(应删除具有相同foo1值的其他行)。
  3. 因此,这是查询后所需的表结构:

    FooTable:
        foo1(pk)  foo2   timestamp
         1         1      1
         2         1      2
    

    注意:主要问题是删除旧的重复行。完成此操作后,可以使用以下查询来设置主键,而不必担心重复:

    alter table FooTable modify foo1 primary key;

3 个答案:

答案 0 :(得分:3)

请记住,您在此处销毁数据。确保您有良好的数据库备份。

我不与Oracle合作,但我认为这很通用。我不知道Oracle是否允许在DELETE子句中使用表别名,因此您可能需要对其进行调整:

DELETE FT1
FROM FooTable FT1
WHERE EXISTS (
    SELECT *
    FROM FooTable FT2
    WHERE
        FT2.foo1 = FT1.foo1 AND
        FT2.timestamp > FT1.timestamp
)

答案 1 :(得分:1)

如果foo1和timestamp的组合是唯一的,您可以创建一个复合键,然后创建一个只显示最大时间戳的视图。

这样可以保存您的数据。

答案 2 :(得分:-1)

DELETE FROM foo_table WHERE EXISTS 
  (    
       WITH q0 AS (SELECT foo1 AS f, timestamp AS ts, row_number() AS rn 
         FROM foo_table OVER (PARTITION BY foo1 ORDER by timestamp DESC) )
       SELECT 1 FROM q0 WHERE q0.f=foo1 AND q0.timestamp=ts AND rn>1
  );

其他一些版本的SQL允许相关子查询使用JOIN样式。