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

时间:2013-05-13 14:35:58

标签: 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)
)

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

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

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

如果我删除DISTINCT,语句会成功,但我会收到很多重复的条目。当然,如果我在SYS_GUID()中明确提供SELECT来电,则会产生完全相同的结果。

现在我发现如果我只是在我的周围添加另一个SELECT,它就可以正常运行,没有违反约束并插入不同的行:

INSERT INTO ...
SELECT x.* FROM (
    SELECT DISTINCT ...
) x

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

2 个答案:

答案 0 :(得分:1)

尝试这样的事情:

insert into test_t(t_guid, t_val1, t_val2)
  select sys_guid(), t_val1, t_val2
    from (select distinct to_number(substr(zip_code, 1, 1)) as t_val1, zip_code as t_val2
            from other_table_t
           where ...)

答案 1 :(得分:0)

用to_number()替换CAST并添加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
/

不同的GUID示例:

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

GID                                 DEPTNO
-------------------------------------------
DC9B9132492C1A45E04011AC3EEB463A    10
DC9B9132492B1A45E04011AC3EEB463A    20
DC9B9132492A1A45E04011AC3EEB463A    30