如何在PL SQL中为现有表创建唯一ID?

时间:2018-10-13 11:13:27

标签: oracle auto-increment ddl

情况是,当我将文件导入数据库时​​,我通常要做的第一件事就是为每条记录分配唯一的ID。

我通常在下面的TSQL中做

ALTER TABLE MyTable
    ADD ID INT IDENTITY(1,1)

我想知道PL SQL中是否有类似的东西?

我所有的搜索结果都通过多个步骤返回。

然后,我想知道PL SQL程序员通常在导入文件后对ID记录进行哪些操作。他们这样做吗? 对这些记录进行ID识别的主要目的是在进行操作/复制后对其进行追溯。

再次,我知道那里有解决方案,我的另一个问题是PL SQL程序员实际上是否这样做,或者还有其他替代方法使PL SQL不需要此步骤?

3 个答案:

答案 0 :(得分:0)

然后,就像在Oracle 11g上一样,那里没有identity列,因此-回到多个步骤。这是一个示例:

我正在创建一个模拟您的导入表的表:

SQL> create table tab_import as
  2    select ename, job, sal
  3    from emp
  4    where deptno = 10;

Table created.

添加ID列:

SQL> alter table tab_import add id number;

Table altered.

创建一个序列,该序列将用于填充ID列:

SQL> create sequence seq_imp;

Sequence created.

更新当前行:

SQL> update tab_import set
  2    id = seq_imp.nextval;

3 rows updated.

创建一个触发器,该触发器将处理以后的插入操作(如果有):

SQL> create or replace trigger trg_bi_imp
  2    before insert on tab_import
  3    for each row
  4  begin
  5    :new.id := seq_imp.nextval;
  6  end;
  7  /

Trigger created.

检查当前表格中的内容:

SQL> select * from tab_import;

ENAME      JOB              SAL         ID
---------- --------- ---------- ----------
CLARK      MANAGER         2450          1
KING       PRESIDENT       5000          2
MILLER     CLERK           1300          3

让我们 import 再添加一些行:

SQL> insert into tab_import (ename, job, sal)
  2    select ename, job, sal
  3    from emp
  4    where deptno = 20;

3 rows created.

触发器静默地填充了ID列:

SQL> select * From tab_import;

ENAME      JOB              SAL         ID
---------- --------- ---------- ----------
CLARK      MANAGER         2450          1
KING       PRESIDENT       5000          2
MILLER     CLERK           1300          3
SMITH      CLERK            800          4
JONES      MANAGER         2975          5
FORD       ANALYST         3000          6

6 rows selected.

SQL>

很快:您需要

  • 更改表并添加ID列
  • 创建序列
  • 创建触发器

结束。

答案 1 :(得分:0)

@Littlefoot给出的答案也将是我的建议-但我仍然想提一下以下变体,该变体仅在您不打算稍后在表中添加更多行时才有效。

docker exec -i $(docker-compose ps -q mysqldb) mysql ...

我的测试:

ALTER TABLE MyTable add id number(38,0); 
update MyTable set id = rownum;
commit;  

但是正如最初提到的那样-这只会解决更新时所拥有行的编号-您以后不会再为新行获取新的id值-如果需要,请按顺序进行解决方案。

答案 2 :(得分:0)

您可以使用单个语句将id列添加到表中(Oracle 11g,请参见dbfiddle):

alter table test_
add id raw( 16 ) default sys_guid() ;

示例:

-- create a table without an id column
create table test_ ( str )
as
select dbms_random.string( 'x', 16 )
from dual
connect by level <= 10 ;

select * from test_ ;

STR
ULWL9EXFG6CIO72Z
QOM0W1R9IJ2ZD3DW
YQWAP4HZNQ57C2UH
EETF2AXD4ZKNIBBF
W9SECJYDER793MQW

alter table test_
add id raw( 16 ) default sys_guid() ;

select * from test_ ;

STR                     ID
ULWL9EXFG6CIO72Z    0x782C6EBCAE2D7B9FE050A00A02005D65
QOM0W1R9IJ2ZD3DW    0x782C6EBCAE2E7B9FE050A00A02005D65
YQWAP4HZNQ57C2UH    0x782C6EBCAE2F7B9FE050A00A02005D65
EETF2AXD4ZKNIBBF    0x782C6EBCAE307B9FE050A00A02005D65
W9SECJYDER793MQW    0x782C6EBCAE317B9FE050A00A02005D65

测试

-- Are the id values unique and not null? Yes. 
alter table test_ 
add constraint pkey_test_ primary key ( id ) ;

-- When we insert more rows, will the id be generated? Yes.
begin 
  for i in 1 .. 100
  loop
    insert into test_ (str) values ( 'str' || to_char( i ) ) ;
  end loop ;
end ;
/

select * from test_ order by id desc ;
-- last 10 rows of the result
STR ID
str100  0x782C806E16A5E998E050A00A02005D81
str99   0x782C806E16A4E998E050A00A02005D81
str98   0x782C806E16A3E998E050A00A02005D81
str97   0x782C806E16A2E998E050A00A02005D81
str96   0x782C806E16A1E998E050A00A02005D81
str95   0x782C806E16A0E998E050A00A02005D81
str94   0x782C806E169FE998E050A00A02005D81
str93   0x782C806E169EE998E050A00A02005D81
str92   0x782C806E169DE998E050A00A02005D81
str91   0x782C806E169CE998E050A00A02005D81

关于您的其他问题:

{1}然后,我想知道PL SQL程序员通常在导入文件后对ID记录进行的操作。他们这样做吗?对这些记录进行ID识别的主要目的是在进行操作/复制后对其进行追溯。

->如您所知,ID的目的是:标识一行。我们不会“对ID做任何事情”。因此,您对ID的使用似乎是合法的。

{2}同样,我知道那里有解决方案,我的另一个问题是PL SQL程序员是否实际上是这样做的,还是有其他选择使得在PL SQL中不需要此步骤?

->不太确定您在这里要问什么。尽管存在ROWID()伪列(请参见documentation),但我们不应该使用它来标识行。

  

“您不应将ROWID用作表的主键。如果删除   然后使用“导入和导出”实用程序重新插入一行,例如,   那么其rowid可能会更改。如果删除一行,那么Oracle可能会   将其rowid重新分配给稍后插入的新行。”