【问题标题】:PLSQL - Find two values are equal when they are NULLPLSQL - 当它们为NULL时找到两个值相等
【发布时间】:2020-01-02 14:44:21
【问题描述】:

我正在使用 IF 条件来检查 2 个值是否相等。在一种情况下,我使用的所有值都是 NULL,但它无法识别它们是否相等。

IF training_event_rec_.training_fee = course_rec_.course_fee AND training_event_rec_.training_fee_unit = course_rec_.course_fee_unit AND training_event_rec_.currency = course_rec_.currency AND training_evaluation_temp_ = course_evaluation_temp_ THEN
    RETURN FALSE;
ELSE
     RETURN TRUE;
END IF;

在这里,所有比较的变量都是 NULL,但它总是命中 ELSE 部分。 在这种情况下如何比较值。

【问题讨论】:

  • null != null 是 SQL 的公理。这就是为什么测试总是采用 ELSE 分支。

标签: oracle plsql null


【解决方案1】:

使用 IS NULL:

IF     (training_event_rec_.training_fee = course_rec_.course_fee OR
       (training_event_rec_.training_fee IS NULL AND course_rec_.course_fee IS NULL))
   AND (training_event_rec_.training_fee_unit = course_rec_.course_fee_unit OR
        (training_event_rec_.training_fee_unit IS NULL AND course_rec_.course_fee_unit IS NULL))
   AND (training_event_rec_.currency = course_rec_.currency OR
        (training_event_rec_.currency IS NULL AND course_rec_.currency IS NULL))
   AND (training_evaluation_temp_ = course_evaluation_temp_ OR
        (training_evaluation_temp_ IS NULL AND course_evaluation_temp_ IS NULL))
THEN
    RETURN FALSE;
ELSE
     RETURN TRUE;
END IF;

注意:

  • 您也可以比较像 NVL(COLUMN_A,'X') = NVL(COLUMN_B,'X') 这样的 Null,前提是您确定 COLUMN_A 和 COLUMN_B 不包含值“X”。所以不推荐这种方法。

【讨论】:

  • 显式测试空值是更安全的选择,除非业务规则给我们一个默认值,我们可以用它来代替空值。
  • 感谢您的信息。最初我认为再次检查 null 可能效率不高,正如您提到的那样,使用 NVL 对我的业务逻辑不安全。
  • 在某些情况下,您可以指定无法与现有值匹配的默认值,但正如 APC 所说,这取决于您的业务规则和数据模型。例如,如果course_feenumber(6,2),那么它永远不会匹配0.0011e9binary_double_nan,如果currencyvarchar2(3),那么它永远不会匹配'####'。 (我很想使用chr(0),但我想这是一个hack。)
【解决方案2】:

我认为非空值和空值可能有不同的组合。一种选择是全部检查,或者——也许更简单——使用NVL,例如:

IF     nvl(training_event_rec_.training_fee, 0)      = nvl(course_rec_.course_fee, 0)
   AND nvl(training_event_rec_.training_fee_unit, 0) = nvl(course_rec_.course_fee_unit, 0)
   AND nvl(training_event_rec_.currency, 0)          = nvl(course_rec_.currency, 0)
   AND nvl(training_evaluation_temp_, 0)             = nvl(course_evaluation_temp_, 0)
THEN
   RETURN FALSE;
ELSE
   RETURN TRUE;
END IF;

根据数据类型,您可能需要使用其他东西,而不是 0。例如,货币可能是美元或欧元或类似的东西,所以你会使用

nvl(training_event_rec_.currency, 'x')

【讨论】:

  • 使用 NVL() 的危险在于可能会产生错误的匹配。如果course_rec_.course_fee = 0 和training_event_rec_.training_fee 为空,那么它们就不一样了。也许业务规则说我们可以将它们视为相同,但没有说明。所以我认为明确测试 IS NULL 是更安全的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 2018-09-22
  • 1970-01-01
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多