我是堆栈溢出的新手,所以当我发布这个时,如果我做错了,我会道歉。 我在使用这段代码时遇到了一些问题。我相信我的加入存在问题。
UPDATE rental_item ri
SET rental_item_price =
(SELECT p.amount
FROM price p INNER JOIN common_lookup cl1
ON p.price_type = cl1.common_lookup_id CROSS JOIN rental r
CROSS JOIN common_lookup cl2
WHERE p.item_id = ri.item_id AND ri.rental_id = r.rental_id
AND ri.rental_item_type = cl2.common_lookup_id
AND cl1.common_lookup_code = cl2.common_lookup_code
AND r.check_out_date
BETWEEN p.start_date AND p.end_date);
此代码块应使用上面指定的条件使用“AMOUNT”列中的数据填充“RENTAL_ITEM_PRICE”列。我无法删除WHERE和AND语句中的任何条件。
RENTAL_ITEM_ID RENTAL_ITEM_PRICE AMOUNT
-------------- ----------------- ------
1001 5
1002 5
1003 5
1004 5
1005 5
1006 5
1007 5
1008 5
1009 5
1010 3
1011 3
1012 10
1013 15
当我运行代码时,它表示已更新了13行,但您可以看到没有写入任何信息。它也不会返回任何错误。
它应该是这样的:
RENTAL_ITEM_ID RENTAL_ITEM_PRICE AMOUNT
-------------- ----------------- ----------
1001 5 5
1002 5 5
1003 5 5
1004 5 5
1005 5 5
1006 5 5
1007 5 5
1008 5 5
1009 5 5
1010 3 3
1011 3 3
1012 10 10
1013 15 15
答案 0 :(得分:1)
您的子查询没有返回任何行,因此更新将所有rental_item_price
值设置为null。单独运行子查询 - 替换rental_item
表中的实际值代替ri.*
列,因为当您运行select
部分时,该别名将不存在 - 可能会显示没有找到数据。
如果确实如此,则必须确定哪些连接或条件不正确,这是基本调试,但您可以先删除过滤条件,直到出现某些数据或检查连接条件。
我最初的猜测 - 现在已经确认 - 是price.end_date
可能为空,如果你有活跃的产品并且你没有设置一个人工魔术结束日期(例如9999-12-31
),这是有意义的,有一天会成为Y10K问题的一部分)。然后,between
子句无法匹配,因为实际日期和空值之间没有任何内容。
您可以将结束日期设置为表格中的魔术值,许多人认为这是一个讨厌的黑客,或将其视为一个神奇的未来日期作为查询的一部分,这不是更好,或使用比较日期为默认值:
r.check_out_date BETWEEN p.start_date
AND COALESCE(p.end_date, r.check_out_date)
我不确定你为什么使用交叉连接然后应用过滤条件,至少对于common_lookup
的自连接是这样;与这个问题没有多大关系,但从我的想法来看,我可能将子查询结构为:
SELECT p.amount
FROM rental r
CROSS JOIN common_lookup cl1
INNER JOIN common_lookup cl2
ON cl2.common_lookup_code = cl1.common_lookup_code
INNER JOIN price p
ON p.price_type = cl2.common_lookup_id
AND r.check_out_date BETWEEN p.start_date
AND COALESCE(p.end_date, r.check_out_date)
WHERE r.rental_id = ri.rental_id
AND cl1.common_lookup_id = ri.rental_item_type
AND p.item_id = ri.item_id
答案 1 :(得分:1)
此SQL的问题在p.end_date。 end_date可以为null。这就是为什么我们需要在发生这种情况时使用NVL添加值。 您的问题的解决方案是:
enter code here
UPDATE rental_item ri
SET rental_item_price =
(SELECT p.amount
FROM price p
INNER JOIN common_lookup cl1
ON p.price_type = cl1.common_lookup_id CROSS JOIN rental r
CROSS JOIN common_lookup cl2
WHERE p.item_id = ri.item_id AND ri.rental_id = r.rental_id
AND ri.rental_item_type = cl2.common_lookup_id
AND cl1.common_lookup_code = cl2.common_lookup_code
AND r.check_out_date
BETWEEN p.start_date AND NVL (p.end_date, TRUNC(SYSDATE + 1)));