如何使用计算值更新带有 PL\SQL 的列

Posted

技术标签:

【中文标题】如何使用计算值更新带有 PL\\SQL 的列【英文标题】:How can I update a column with PL\SQL by using a calculated value如何使用计算值更新带有 PL\SQL 的列 【发布时间】:2017-02-10 09:55:51 【问题描述】:

出于学习目的,我创建了一个虚拟数据库,并故意在其中一个表中创建了一些重复的记录。在每种情况下,我都想将其中一条重复记录标记为 Latest='Y',将另一条记录标记为 'N',并且对于每条记录,Latest 标记将是 'Y'。

我尝试使用 PlSQL 来检查我的所有记录,但是当我尝试使用之前计算的值(这会表明它是重复记录)时,它会说:

ORA-06550:第 20 行,第 17 列: PLS-00201:必须声明标识符“COUNTER”

这是我尝试使用的语句:

DECLARE CURSOR cur IS SELECT order_id, order_date, person_id, amount, successfull_order, country_id, latest, ROWCOUNT AS COUNTER FROM (SELECT order_id, order_date, person_id, amount, successfull_order, country_id, latest, ROW_NUMBER () OVER (PARTITION BY order_id, order_date, person_id, amount, successfull_order, country_id ORDER BY order_id, order_date, person_id, amount, successfull_order, country_id) ROWCOUNT FROM orders) orders FOR UPDATE OF orders.latest; rec cur%ROWTYPE; BEGIN FOR rec IN cur LOOP IF MOD (COUNTER, 2) = 0 THEN UPDATE orders SET latest = 'N' WHERE CURRENT OF cur; ELSE UPDATE orders SET latest = 'Y' WHERE CURRENT OF cur; END IF; END LOOP; END;

我是 PlSQL 的新手,所以我尝试修改我在这里找到的语句: http://www.adp-gmbh.ch/ora/plsql/cursors/for_update.html

我应该在我的陈述中改变什么,或者我应该使用不同的方法?

提前感谢您的回答! 波顿

【问题讨论】:

您应该从光标引用访问它,例如 MOD (rec.COUNTER, 2) 【参考方案1】:

您将光标中的ROWNUM 称为COUNTER。 获取时,您应该从光标引用访问它,例如 MOD (rec.COUNTER, 2)

【讨论】:

谢谢你的回答,但这样我就有了一个新问题。它不想更新,因为我使用分区。我使用了一种解决方法而不是这个。【参考方案2】:

您需要声明变量 COUNTER,然后您需要在循环中维护(即递增)它。 我怀疑你的例子只是为了学习 PL/SQL。但是请注意,与使用游标循环相比,使用单个 SQL 语句执行操作通常更高效。

【讨论】:

谢谢 我使用了一种解决方法,通过创建一个包含一些辅助列的全新表。这样我就不必使用 PLSQL。【参考方案3】:

您的问题是 COUNTER 是游标记录 rec 的属性,而不是 PL/SQL 变量。所以:

IF MOD (COUNTER, 2) = 0

应该是:

IF MOD (rec.COUNTER, 2) = 0

但是,您不需要使用 PL/SQL 或游标,可以在单个 MERGE 语句中完成:

Oracle 设置

CREATE TABLE orders ( order_id, order_date, latest ) AS
SELECT 1, DATE '2017-01-01', CAST( NULL AS CHAR(1) ) FROM DUAL UNION ALL
SELECT 1, DATE '2017-01-02', NULL FROM DUAL UNION ALL
SELECT 1, DATE '2017-01-03', NULL FROM DUAL UNION ALL
SELECT 2, DATE '2017-01-04', NULL FROM DUAL UNION ALL
SELECT 2, DATE '2017-01-01', NULL FROM DUAL UNION ALL
SELECT 3, DATE '2017-01-06', NULL FROM DUAL;

更新声明

MERGE INTO orders dst
USING ( SELECT ROW_NUMBER() OVER ( PARTITION BY order_id
                                   ORDER BY order_date DESC ) AS rn
        FROM   orders
      ) src
ON ( src.ROWID = dst.ROWID )
WHEN MATCHED THEN
  UPDATE SET latest = CASE src.rn WHEN 1 THEN 'Y' ELSE 'N' END;

输出

SELECT * FROM orders;

ORDER_ID ORDER_DATE LATEST
-------- ---------- ------
       1 2017-01-01 N
       1 2017-01-02 N
       1 2017-01-03 Y
       2 2017-01-04 Y
       2 2017-01-01 N
       3 2017-01-06 Y

【讨论】:

以上是关于如何使用计算值更新带有 PL\SQL 的列的主要内容,如果未能解决你的问题,请参考以下文章

pl sql触发器如何比较触发器中的列值

如何使用PL / SQL更改您在FOR循环IN子句中查询的表

如何在带有子查询的列中“更新选择”某些值?

PL/SQL 使用一张表中的列数据更新表,基于不同表之间的相等性

如何在 Oracle PL/SQL 过程的开始部分之后声明游标

使用带有布尔输入参数的 PL/SQL 在 oracle 中调用 java 存储过程