如何为 PL SQL 中的现有表创建唯一 ID?
Posted
技术标签:
【中文标题】如何为 PL SQL 中的现有表创建唯一 ID?【英文标题】:How to create a unique id for an existing table in PL SQL? 【发布时间】:2019-03-18 10:33:24 【问题描述】:情况是,当我将文件导入数据库时,我通常做的第一件事就是为每条记录分配一个唯一的 ID。
我通常在 TSQL 中执行以下操作
ALTER TABLE MyTable
ADD ID INT IDENTITY(1,1)
我想知道PL SQL中是否有类似的东西?
我的所有搜索结果都包含多个步骤。
然后我想知道 PL SQL 程序员在导入文件后通常对 ID 记录做什么。他们这样做吗? 我识别这些记录的主要目的是在操作/复制后对其进行追溯。
再一次,我知道那里有解决方案,我的进一步问题是 PL SQL 程序员是否真的这样做,或者还有其他替代方法使得这一步在 PL SQL 中不是必需的?
【问题讨论】:
Add a auto increment primary key to existing table in oracle的可能重复 这是一个副本的副本。根据我链接到的帖子,以及它作为副本链接到的帖子,oracle 中没有自动增量列。 您使用哪个数据库(及其版本)? PL SQL 是 Oracle 11,TSQL 是 SQL Server 2012 很多答案都是从创建表开始的,但我的场景是从现有表开始的。 【参考方案1】:好吧,因为您使用的是 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
让我们导入更多行:
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 列 创建序列 创建触发器结束。
【讨论】:
这看起来像是标准解决方案。感谢您的示例,并在最后进行总结。【参考方案2】:@Littlefoot 给出的答案也是我的建议 - 但我仍然认为我可以提及以下变体,该变体仅在您以后不打算向表中添加更多行时才有效。
ALTER TABLE MyTable add id number(38,0);
update MyTable set id = rownum;
commit;
我的测试:
SQL> create table tst as select * from all_tables;
Table created.
SQL> alter table tst add id number(38,0);
Table altered.
SQL> update tst set id = rownum;
3815 rows updated.
SQL> alter table tst add constraint tstPk primary key (id);
Table altered.
SQL>
SQL> select id from tst where id < 15;
ID
----------
1
2
3
4
5
6
7
8
9
10
11
ID
----------
12
13
14
14 rows selected.
但正如最初提到的那样,这仅修复了更新时您拥有的行的编号 - 您不会在以后的任何时候为新行获取新的 id 值 - 如果您需要,请按顺序执行解决方案。
【讨论】:
这就是我想要找到的。我无意在这些表上插入更多记录。导入它们后,我的主要任务是在每一行上附加更多属性,有时将其复制到单独的表中以进行其他处理。这就是为什么 ID 过程对于追踪源头对我来说很重要。谢谢!!【参考方案3】:您可以使用单个语句将 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 的使用似乎是合法的。
2 同样,我知道那里有解决方案,我进一步的问题是 PL SQL 程序员是否真的这样做了,或者还有其他替代方法使得这一步在 PL SQL 中不是必需的?
-> 不太清楚你在这里问什么。虽然有一个 ROWID() 伪列(参见documentation),但我们不应该使用它来识别行。
"你不应该使用 ROWID 作为表的主键。如果你删除 并使用导入和导出实用程序重新插入一行,例如, 那么它的rowid可能会改变。如果你删除一行,那么 Oracle 可能 将其 rowid 重新分配给稍后插入的新行。”
【讨论】:
以上是关于如何为 PL SQL 中的现有表创建唯一 ID?的主要内容,如果未能解决你的问题,请参考以下文章