INSERT INTO/SELECT DISTINCT导致SYS_GUID的主键冲突

mhd*_*mhd 5 sql oracle

我有一些问题从另一个表批量插入数据到一个新表.目标看起来有点像这样:

CREATE TABLE TEST_T (
      T_GUID RAW(16) DEFAULT SYS_GUID() NOT NULL,
      T_VAL1 NUMBER(10) NOT NULL,
      T_VAL2 VARCHAR2(10) NOT NULL,
      PRIMARY KEY (T_GUID)
)
Run Code Online (Sandbox Code Playgroud)

我打算用数据填充它的语句的简化版本:

INSERT INTO TEST_T (T_VAL1, T_VAL2)
SELECT DISTINCT
     CAST(SUBSTR(zip_code, 1,1) AS NUMBER) as  t_val1,
     zip_code as t_val2
FROM OTHER_TABLE_T
WHERE ...
ORDER BY t_val1
Run Code Online (Sandbox Code Playgroud)

由于我没有提供T_GUID有价值的,我会假设我SYS_GUID为每个新行提供了一个函数.但是出了点问题,我得到了主键的唯一性约束违规.

如果我删除了DISTINCT,语句成功,但我得到了很多重复的条目.当然,如果我明确地SYS_GUID()在我的电话中提供呼叫SELECT,则结果完全相同.

现在我发现如果我只是把另一个放在我的SELECT周围,​​它可以正常工作,没有约束违规并且插入了不同的行:

INSERT INTO ...
SELECT x.* FROM (
    SELECT DISTINCT ...
) x
Run Code Online (Sandbox Code Playgroud)

那么重复的guids来自哪里?如果完整的行集没有问题,为什么通过不同的方法删除行会造成麻烦?由于SYS_GUID为每个调用创建了一个唯一的标识符,我只能想象在不同的​​情况下,它只会被整个子句调用一次,这是由周围的包装解决的SELECT.如果有人可以解释在这种情况下执行的不同,我会很高兴.

Art*_*Art 0

将 CAST 替换为 to_number() 并添加 guid。首先测试您的选择,然后插入...:

SELECT DISTINCT
    sys_guid() guid 
    To_Number(SUBSTR(zip_code, 1,1)) as  t_val1,
    zip_code as t_val2
 FROM OTHER_TABLE_T
/
Run Code Online (Sandbox Code Playgroud)

不同的 GUID 示例:

SELECT sys_guid() gid, deptno
  FROM
 (
 SELECT distinct deptno FROM scott.emp
 )
ORDER BY deptno
/

GID                                 DEPTNO
-------------------------------------------
DC9B9132492C1A45E04011AC3EEB463A    10
DC9B9132492B1A45E04011AC3EEB463A    20
DC9B9132492A1A45E04011AC3EEB463A    30
Run Code Online (Sandbox Code Playgroud)