ORA-01427与过程中使用的表别名

时间:2013-03-19 04:54:46

标签: oracle stored-procedures subquery ora-01427

我在存储过程中有以下代码段:

(注意,这不是原始代码段,但与它完全相似,只是表和列名称已被更通用的代码替换,以便更好地理解以及防止提供客户端代码。)

UPDATE table_Orders c SET order_type = 
(
SELECT 'PE' FROM 
table_Orders A, 
table_Orders b, 
(SELECT DISTINCT order_id, cust_id, order_date FROM table_Orders WHERE shipment_type = 'T' AND order_availability = 'P' AND order_amt > 500 
AND cust_category = 'PREMIUM' ) d 
WHERE
A.order_id = d.order_id AND A.order_date = d.order_date AND A.cust_id= d.cust_id
AND A.order_id = b.order_id AND A.order_date = b.order_date AND A.cust_id= b.cust_id
AND A.shipment_type = b.shipment_type AND A.order_availability = b.order_availability AND A.product_id <> b.product_id
AND ((A.order_amt > 500 AND b.shipment_amt > 50) OR (A.shipment_amt > 50 AND b.order_amt > 500))
AND A.order_id = c.order_id AND A.order_date = c.order_date AND A.cust_id = c.cust_id 
AND A.shipment_type = c.shipment_type AND  A.order_availability = c.order_availability AND A.product_id = c.product_id 
);
COMMIT;

现在,我的问题是我在执行程序时收到错误ORA-01427 single-row subquery returns more than one row。我尝试使用IN子句将子查询放在语句的末尾,如下所示,但即使这样也不起作用:

UPDATE table_Orders c SET order_type =
(
SELECT 'PE' FROM 
table_Orders A, 
table_Orders b
WHERE
A.order_id = d.order_id AND A.order_date = d.order_date AND A.cust_id= d.cust_id
AND A.order_id = b.order_id AND A.order_date = b.order_date AND A.cust_id= b.cust_id
AND A.shipment_type = b.shipment_type AND A.order_availability = b.order_availability AND A.product_id <> b.product_id
AND ((A.order_amt > 500 AND b.shipment_amt > 50) OR (A.shipment_amt > 50 AND b.order_amt > 500))
AND A.order_id = c.order_id AND A.order_date = c.order_date AND A.cust_id = c.cust_id 
AND A.shipment_type = c.shipment_type AND  A.order_availability = c.order_availability AND A.product_id = c.product_id 
AND (A.order_id, A.cust_id, A.order_date) IN
(SELECT DISTINCT order_id, cust_id, order_date FROM table_Orders 
    WHERE shipment_type = 'T' AND order_availability = 'P' AND order_amt > 500 AND cust_category = 'PREMIUM')
);
COMMIT;

有人可以指导我朝着正确的方向发展,关于我在哪里搞砸这个问题,或者子查询是如何搞砸的?

代码加入 - &gt;这使得在“JOIN”语句

之前的c.product_Id缺少右括号
UPDATE table_Orders c SET order_type =
(
 SELECT 'PE' FROM 
table_Orders A, 
table_Orders b
WHERE
A.order_id = d.order_id AND A.order_date = d.order_date AND A.cust_id= d.cust_id
AND A.order_id = b.order_id AND A.order_date = b.order_date AND A.cust_id= b.cust_id
AND A.shipment_type = b.shipment_type AND A.order_availability = b.order_availability AND A.product_id <> b.product_id
AND ((A.order_amt > 500 AND b.shipment_amt > 50) OR (A.shipment_amt > 50 AND b.order_amt > 500))
AND A.order_id = c.order_id AND A.order_date = c.order_date AND A.cust_id = c.cust_id 
AND A.shipment_type = c.shipment_type AND  A.order_availability = c.order_availability AND A.product_id = c.product_id 
JOIN
SELECT DISTINCT order_id, cust_id, order_date FROM table_Orders 
WHERE shipment_type = 'T' AND order_availability = 'P' AND order_amt > 500 AND cust_category = 'PREMIUM' d
ON A.order_id = d.order_id AND A.order_date = d.order_date AND A.cust_id= d.cust_id
COMMIT;

1 个答案:

答案 0 :(得分:0)

对于某些c.order_id, c.order_date, c.cust_id, c.shipment_type, c.order_availability, c.product_id

,子查询可能会返回多行

在不知道您的表格结构和数据的情况下,我们很难说出来。

但你可以这样做:

UPDATE table_Orders c SET order_type = 'PE'
WHERE (c.order_id, c.order_date, c.cust_id, c.shipment_type, c.order_availability, c.product_id) IN 
(
SELECT A.order_id, A.order_date, A.cust_id, A.shipment_type, A.order_availability, A.product_id 
FROM 
table_Orders A, 
table_Orders b, 
(SELECT DISTINCT order_id, cust_id, order_date FROM table_Orders WHERE shipment_type = 'T' AND order_availability = 'P' AND order_amt > 500 
AND cust_category = 'PREMIUM' ) d 
WHERE
A.order_id = d.order_id AND A.order_date = d.order_date AND A.cust_id= d.cust_id
AND A.order_id = b.order_id AND A.order_date = b.order_date AND A.cust_id= b.cust_id
AND A.shipment_type = b.shipment_type AND A.order_availability = b.order_availability AND A.product_id <> b.product_id
AND ((A.order_amt > 500 AND b.shipment_amt > 50) OR (A.shipment_amt > 50 AND b.order_amt > 500))
);

COMMIT;
顺便说一下,为什么不使用“JOIN语法”?


UPDATE 相同的解决方案,但使用ANSI连接语法:

UPDATE table_Orders c 
   SET order_type = 'PE'
 WHERE (c.order_id, c.order_date, c.cust_id, c.shipment_type, c.order_availability, c.product_id) IN 
(
SELECT A.order_id, A.order_date, A.cust_id, A.shipment_type, A.order_availability, A.product_id 
FROM 
table_Orders A 
JOIN 
table_Orders b ON A.order_id = b.order_id AND A.order_date = b.order_date AND A.cust_id= b.cust_id AND A.shipment_type = b.shipment_type AND A.order_availability = b.order_availability AND A.product_id <> b.product_id 
JOIN 
(SELECT DISTINCT order_id, cust_id, order_date FROM table_Orders WHERE shipment_type = 'T' AND order_availability = 'P' AND order_amt > 500 
AND cust_category = 'PREMIUM' ) d ON A.order_id = d.order_id AND A.order_date = d.order_date AND A.cust_id= d.cust_id
WHERE ((A.order_amt > 500 AND b.shipment_amt > 50) OR (A.shipment_amt > 50 AND b.order_amt > 500))
);