我必须收集和存储有关我工作的许多事情的统计数据,特别是我突然在一张桌子上遇到问题。获取这些统计信息的过程的相关部分涉及将数据转储到临时表中,并将该表中的任何新数据插入主表中。所以我有这样的事情:
CREATE TABLE "TEMP_SCHEMA"."STATS_ORDERS"
(
"ORDER_NO" NUMBER(10,0) NOT NULL ENABLE,
"ORDER_DATE" DATE NOT NULL ENABLE,
"ORDER_TYPE" VARCHAR2(1 BYTE) NOT NULL ENABLE
); /
GRANT SELECT,INSERT,UPDATE,DELETE
ON "TEMP_SCHEMA"."STATS_ORDERS" TO "MY_SCHEMA"; /
CREATE TABLE "MY_SCHEMA"."STATS_ORDERS"
(
"ORDER_NO" NUMBER(10,0) NOT NULL ENABLE,
"ORDER_DATE" DATE NOT NULL ENABLE,
"ORDER_TYPE" VARCHAR2(1 BYTE) NOT NULL ENABLE,
CONSTRAINT "PK_STATS_ORDERS" PRIMARY KEY ("ORDER_NO", "ORDER_TYPE")
); /
将数据转储到“TEMP_SCHEMA”。“STATS_ORDERS”我正在尝试这样的事情:
INSERT INTO MY_SCHEMA.STATS_ORDERS (ORDER_NO,ORDER_DATE,ORDER_TYPE)
SELECT
DISTINCT TMP.ORDER_NO,TMP.ORDER_DATE,TMP.ORDER_TYPE
FROM
(SELECT DISTINCT * FROM TEMP_SCHEMA.STATS_ORDERS) TMP
LEFT JOIN MY_SCHEMA.STATS_ORDERS ORD
ON TMP.ORDER_NO = ORD.ORDER_NO AND TMP.ORDER_TYPE = ORD.ORDER_TYPE
WHERE ORD.ORDER_NO IS NULL AND ORD.ORDER_TYPE IS NULL; /
当我运行它时,我收到以下错误:
SQL Error: ORA-00001: unique constraint (MY_SCHEMA.PK_STATS_ORDERS) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
我运行以下查询以查找导致错误的行:
SELECT ORDER_NO,ORDER_DATE,ORDER_TYPE
FROM
MY_SCHEMA.STATS_ORDERS O
INNER JOIN (
SELECT DISTINCT TMP.ORDER_NO,TMP.ORDER_DATE,TMP.ORDER_TYPE
FROM (SELECT DISTINCT * FROM TEMP_SCHEMA.STATS_ORDERS) TMP
LEFT JOIN MY_SCHEMA.STATS_ORDERS ORD
ON TMP.ORDER_NO = ORD.ORDER_NO AND TMP.ORDER_TYPE = ORD.ORDER_TYPE
WHERE ORD.ORDER_NO IS NULL AND ORD.ORDER_TYPE IS NULL
) N
ON O.ORDER_NO = N.ORDER_NO AND O.ORDER_TYPE = N.ORDER_TYPE; /
据推测,这应该返回导致违规的任何行,但当然它什么都不返回,因为我明确地排除了任何可能重复的行。
我做错了什么?
编辑:我不小心把原来的名字留给了我的例子。将其更改为我的示例中的名称。
答案 0 :(得分:6)
识别有问题行的最简单方法通常是使用DML error logging。如果您创建错误表
BEGIN
dmbs_errlog.create_error_log( dml_table_name => 'STATS_ORDERS',
err_log_table_name => 'STATS_ORDERS_ERR',
err_log_table_owner => 'MY_SCHEMA' );
END;
然后您可以在DML中使用LOG ERRORS INTO
子句
INSERT INTO MY_SCHEMA.STATS_ORDERS (ORDER_NO,ORDER_DATE,ORDER_TYPE)
SELECT DISTINCT TMP.ORDER_NO,TMP.ORDER_DATE,TMP.ORDER_TYPE
FROM (SELECT DISTINCT * FROM TEMP_SCHEMA.STATS_ORDERS) TMP
LEFT JOIN MY_SCHEMA.STATS_ORDERS ORD
ON TMP.ORDER_NO = ORD.ORDER_NO AND TMP.ORDER_TYPE = ORD.ORDER_TYPE
WHERE ORD.ORDER_NO IS NULL AND ORD.ORDER_TYPE IS NULL
LOG ERRORS INTO stats_orders_err
REJECT LIMIT UNLIMITED;
这会将约束拒绝的任何行写入stats_orders_err
错误表。
答案 1 :(得分:1)
确认您没有达到这种情况:
SQL> CREATE TABLE STATS_ORDERS_TMP
2 (
3 ORDER_NO NUMBER(10,0) NOT NULL ENABLE,
4 ORDER_DATE DATE NOT NULL ENABLE,
5 ORDER_TYPE VARCHAR2(1 BYTE) NOT NULL ENABLE
6 );
Table created.
SQL>
SQL> CREATE TABLE STATS_ORDERS
2 (
3 ORDER_NO NUMBER(10,0) NOT NULL ENABLE,
4 ORDER_DATE DATE NOT NULL ENABLE,
5 ORDER_TYPE VARCHAR2(1 BYTE) NOT NULL ENABLE,
6 CONSTRAINT PK_STATS_ORDERS PRIMARY KEY (ORDER_NO, ORDER_TYPE)
7 );
Table created.
SQL> insert into STATS_ORDERS_TMP values (1, sysdate, 'A');
1 row created.
SQL> insert into STATS_ORDERS_TMP values (1, sysdate-1, 'A');
1 row created.
SQL> commit;
Commit complete.
SQL> insert into stats_orders (order_no,order_date,order_type)
2 select
3 distinct tmp.order_no,tmp.order_date,tmp.order_type
4 from
5 (select distinct * from stats_orders_tmp) tmp
6 left join stats_orders ord
7 on tmp.order_no = ord.order_no and tmp.order_type = ord.order_type
8 where ord.order_no is null and ord.order_type is null;
insert into stats_orders (order_no,order_date,order_type)
*
ERROR at line 1:
ORA-00001: unique constraint (DTD_TRADE.PK_STATS_ORDERS) violated
即。您在“temp”表中有给定订单+类型的重复日期。
您的验证无法看到它们(因为它们不在主表中):
SQL> SELECT o.ORDER_NO,o.ORDER_DATE,o.ORDER_TYPE
2 FROM
3 STATS_ORDERS O
4 INNER JOIN (
5 SELECT DISTINCT TMP.ORDER_NO,TMP.ORDER_DATE,TMP.ORDER_TYPE
6 FROM (SELECT DISTINCT * FROM STATS_ORDERS_TMP) TMP
7 LEFT JOIN STATS_ORDERS ORD
8 ON TMP.ORDER_NO = ORD.ORDER_NO AND TMP.ORDER_TYPE = ORD.ORDER_TYPE
9 WHERE ORD.ORDER_NO IS NULL AND ORD.ORDER_TYPE IS NULL
10 ) N
11 ON O.ORDER_NO = N.ORDER_NO AND O.ORDER_TYPE = N.ORDER_TYPE;
no rows selected
但确实存在:
SQL> select order_no, order_type, count(*) from stats_orders_tmp group by order_no, order_type having count(*) > 1;
ORDER_NO O COUNT(*)
---------- - ----------
1 A 2