如何通过添加序列列插入列?

Posted

技术标签:

【中文标题】如何通过添加序列列插入列?【英文标题】:How to insert columns with adding sequence column? 【发布时间】:2016-07-02 01:53:27 【问题描述】:

在 Oracle 数据库 (11gR2) 中,我有一个表 my_table,其中包含列 (sequencecol1col2col3)。我想将值插入从其他表查询的表中,即insert into my_table select <query from other tables>。问题是主键是四列,因此我需要添加一个从 0 开始直到要插入的行数的序列(顺序不是问题)。

我尝试使用这样的循环:

DECLARE
    j    NUMBER;
    r_count number;
BEGIN
    select count(1) into r_count from <my query to be inserted>;
    FOR j IN 0 .. r_count
    LOOP
        INSERT INTO   my_table
              select <my query, incorporating r_count as sequence column> ;
    END LOOP;
END;

但它不起作用,实际上循环r_count 次尝试每次插入整行,从逻辑上讲它应该这样做。如何通过添加序列列来实现预期目标并插入行?

【问题讨论】:

【参考方案1】:

不要循环执行此操作。只需使用row_number()

INSERT INTO my_table(seq, . . .)
     select row_number() over (order by NULL) - 1, . . .
     from . . .;

【讨论】:

【参考方案2】:

让我们用示例数据创建表(以模拟您的数据源)

-- This is your source query table (can be anything)
CREATE TABLE source_table
  (
    source_a VARCHAR(255),
    source_b VARCHAR(255),
    source_c VARCHAR(255)
  );

insert into source_table (source_a, source_b, source_c) values ('A', 'B', 'C');
insert into source_table (source_a, source_b, source_c) values ('D', 'E', 'F');
insert into source_table (source_a, source_b, source_c) values ('G', 'H', 'I');

然后创建目标表,id 和 3 个数据列。

-- This is your target_table
CREATE TABLE target_table
  (
    id       NUMBER(9,0),
    target_a VARCHAR2(255),
    target_b VARCHAR2(255),
    target_c VARCHAR2(255)
  );

-- This is sequence used to ensure unique number in 1st column
CREATE sequence target_table_id_seq start with 0 minvalue 0 increment BY 1;

最后,执行插入,从序列中加载id,从源表中加载其余数据。

INSERT INTO target_table
SELECT target_table_id_seq.nextval,
  source_a,
  source_b,
  source_c
FROM source_table;

结果可能看起来像

1   A   B   C
2   D   E   F
3   G   H   I

如果您稍后添加一些值,它们将继续编号为 4、5、6 等。或者您只想在组内获得订单?因此,如果您再添加 2 行 JKL 和 MNO,目标表将如下所示

1   A   B   C
2   D   E   F
3   G   H   I
1   J   K   L
2   M   N   O

为此,您需要不同的解决方案(甚至不需要排序器)

SELECT
  RANK() OVER (ORDER BY source_a, source_b, source_c),
  source_a,
  source_b,
  source_c
FROM source_table;

从技术上讲,您可以直接使用 ROWNUM,但由于结果一致,我选择了 RANK() OVER 分析函数。请注意,如果您尝试两次插入相同的行,这将破坏您的复杂主键(我的第一个解决方案没有)

【讨论】:

【参考方案3】:

显然,您应该使用 Oracle 序列。 首先,创建一个序列:

create sequence seq_my_table start with 0 minvalue 0 increment by 1;

然后使用它:

INSERT INTO   my_table (sequence, ...) 
select seq_my_table.nextval, <the rest of my query>;

序列号会连续插入。

【讨论】:

【参考方案4】:

那么,您已经有了表,它具有所需的行数,现在您想在名为 sequence 的列中添加从 0 到总行数减一的数字? (也许不是“序列”,而是不太可能与 Oracle 保留字发生冲突的东西?)

那么这应该可以工作:

update my_table set seq = rownum - 1;

【讨论】:

不,我已经有了表格,但这些是我想插入的新行。我正在从其他几个表中检索并想添加一个序列。 ...但是您需要确保新数字不会与序列中已有的数字发生冲突? 你是对的。幸运的是,在这个特定的场景中 col1 是一个新的唯一值,只是针对这个特定的插入,所以其他序列不会因为它们有不同的 col1 而发生冲突。

以上是关于如何通过添加序列列插入列?的主要内容,如果未能解决你的问题,请参考以下文章

比较两个序列列,并基于条件将元素添加到 Dataframe

SQL Server Compact Edition - 序列列?

同一 INSERT 期间另一列中序列列的参考值

根据其他列在列中插入实数 OLD INSERTs

db2数据库导入时自动增长的ID列如何填写

如何通过中序和层序序列建立二叉树