【问题标题】:Oracle UPDATE has no effectOracle UPDATE 没有效果
【发布时间】:2014-01-09 10:13:44
【问题描述】:

我正在开发 Sql Developper,我在一个包中创建了以下过程:

PROCEDURE VALIDER(a_session IN NUMBER) AS

i NUMBER;
TYPE type_tab IS TABLE OF PANIER%ROWTYPE;
tabSeances type_tab;

BEGIN
SELECT * BULK COLLECT INTO tabSeances
FROM PANIER
WHERE a_session = sessionweb;

i:=0;
FOR i IN 1 .. tabSeances.count LOOP
  -- UPADTE DU NOMBRE DE PLACES LIBRES
  BEGIN
    UPDATE PROJECTION
    SET remaining_seats = (remaining_seats - tabseances(i).nbrplaces)
    WHERE  num_copy = tabseances(i).num_copy 
      AND day = tabseances(i).dateseance
      AND time_slot = tabseances(i).time_slot 
      AND movie = tabseances(i).movie;
    COMMIT;

    --UPDATE ON PANIER
    UPDATE PANIER
    SET valide = 1
    WHERE sessionweb = a_session 
      AND num_copy = tabseances(i).num_copy 
      AND dateseance = tabseances(i).dateseance
      AND time_slot = tabseances(i).time_slot 
      AND movie = tabseances(i).movie;  
    COMMIT;
    EXCEPTION  
      WHEN NO_DATA_FOUND THEN raise_application_error(-20035, 'Pas de données');
      WHEN OTHERS THEN raise_application_error(-20006,'Autres Erreurs');
  END;
END LOOP; 
END VALIDER;

程序执行正常,我没有收到错误。

我有一种产品购物车:“PANIER”。我为一个人(会话)循环 thsi 购物车中的所有条目,以在数据库中验证它们并减少座位总数。

但第一次更新中的“剩余座位”字段(来自 PROJECTIONS)不起作用。该字段未更新。我已经尝试过其他值,但没有。

我确定该过程已执行,因为第二次更新仍然有效。它将购物车条目标记为“已确认”。
我在这个字段上没有任何触发器。

我的表包含有效数据(NULL)。

我像这样执行这个过程(在 BEGIN END; 块中):

CMDPLACES.VALIDER(1);

感谢您的回复。

【问题讨论】:

  • 这是一个存储过程。如果你只是按 F5,它就会编译。你真的在执行这个程序吗?如果是,那么你的输入参数是什么?
  • 您确定第一次更新的WHERE 子句返回任何记录吗?我建议添加一些调试输出来验证这一点。另附注:为什么不使用没有游标循环的直接 SQL 更新?
  • 剩余座位列的现有数据中是否有空值?因为null -/+ anything 为NULL。
  • 如果更新零行,UPDATE 不会抛出 NO_DATA_FOUND 异常,因为这不是错误。如果你想检查零行是否被更新并引发错误,那么你可以在UPDATE 语句之后立即执行IF SQL%ROWCOUNT = 0 THEN raise_application_error( ... ); END IF

标签: sql oracle stored-procedures plsql sql-update


【解决方案1】:

您的第一次更新是day 还是dateseance

UPDATE PROJECTION
SET remaining_seats = (remaining_seats - tabseances(i).nbrplaces)
WHERE  num_copy = tabseances(i).num_copy 
  AND dateseance = tabseances(i).dateseance
  AND time_slot = tabseances(i).time_slot 
  AND movie = tabseances(i).movie;

正如 @ThorstenKettner 提到的,日期中的 timestamp 数据在比较时可能会失败,所以我们有 TRUNCATE 使用 TRUNC() 的时间戳数据 [ 如果需要]!
如果日期列被索引,请注意索引不会被数据库使用。

要处理UPDATE 中的NO Data,您可以检查(SQL%ROWCOUNT > 0) 以确定更新的行数!

【讨论】:

  • 不,PROJECTION 和 PANIER 是两个具有其他字段名称的不同表。我处理了 No Data 异常并添加了 TRUNC() 但它不起作用。
  • 好的,另一种可能性是 CHARVARCHAR 字段比较。在此之前,您可以尝试使用您所拥有的WHERE 条件和值执行“SELECT”,以确保数据存在吗?另外,能否请您描述一下您的表的列定义?
【解决方案2】:

您的第一次更新比较了天数。这些是什么数据类型?如果您处理 DATETIME,请确保在没有时间部分的情况下进行比较(如果有)。使用 TRUNC 来实现这一点。

AND TRUNC(day) = TRUNC(tabseances(i).dateseance)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-30
    • 2018-05-21
    • 2018-07-28
    • 2018-05-15
    • 1970-01-01
    • 2011-10-01
    • 2015-05-31
    • 2020-10-19
    相关资源
    最近更新 更多