代码之家  ›  专栏  ›  技术社区  ›  BitLauncher

甲骨文-如何模拟位列和布尔和/或?

  •  0
  • BitLauncher  · 技术社区  · 2 年前

    我们必须在两个这样的列之间建立OR。 我也读过 this article here . 但是,对于OR(and和)功能、很少的锅炉板、程序员可读性(和性能)来说,什么是最好的呢?

    这里有一些测试代码来检查它:

    --drop table test_bool_number;
    create table test_bool_number (
        test_id NUMBER GENERATED BY DEFAULT AS IDENTITY,
        abool NUMBER(1),
        bbool NUMBER(1),
        cbool NUMBER(1)
        PRIMARY KEY(test_id)
    );
    
    INSERT INTO test_bool_number (abool, bbool, cbool)
                select 0, 0, null from dual
      union all select 0, 1, null from dual
      union all select 1, 0, null from dual
      union all select 1, 1, null from dual;
     
    SELECT * FROM test_bool_number ORDER BY test_id; -- to query the results
    

    -- option A + for OR, * for AND
    UPDATE test_bool_number
      SET
        cbool = abool + bbool;
    

    我发现,如果cbool在Java类boolean属性中反序列化,那么这个版本最有可能工作,但它不会总是工作:

    • cbool结果不满足上述条件,如果cbool>0
    • 如果对10个类似的布尔列求和,则结果为10,数字(1)导致ORA-01438错误

    -- option B greatest for OR, least for AND
    UPDATE test_bool_number
      SET
        cbool = greatest(abool, bbool);
    

    上述方法效果很好,因为结果总是0或1,但仅限于:

    • abool和bbool只能为0或1
    • 这也适用于10列或更多列。 对于,可以采用最小而不是最大的方法。

    假设所有不为0的值都表示为true(例如在C编程语言中)

    -- bool input values are not always only 1 in case of true!
    UPDATE test_bool_number
      SET abool = abool * -5, bbool = bbool * +5;
    
    -- option C standard SQL always correct   
    UPDATE test_bool_number
      SET cbool = case when ((abool <> 0) or (bbool <> 0)) then 1 else 0 end;
    

    所以我找到了另一个选择:

    -- option D ABS and SIGN
    UPDATE test_bool_number
      SET
        cbool = SIGN(ABS(abool) + ABS(bbool));
    

    比较短,总是正确的。它甚至适用于abool=9和bbool=7,中间结果是符号(16),其中16超出了数字(1)的范围,但性能如何?

    有没有一种更简单、甚至性能更好的方法来处理布尔值?

    -- option E ABS + > 0
    UPDATE test_bool_number
      SET
        cbool = case when ((ABS(abool) + ABS(bbool)) > 0) then 1 else 0 end;
    

    那么使用二进制或位or呢?

    -- option F BITOR for OR
    UPDATE test_bool_number
      SET
        cbool = BITOR(abool, bbool) <> 0 then 1 else 0 end;
    

    -- option G via text
    UPDATE test_bool_number
      SET
        cbool = ABS(SIGN(TO_NUMBER(abool || bbool)));
    

    在许多编程语言(C#,Java,…)中,最内部的可以理解为布尔值或类似值但在Oracle中,它是一个字符串连接运算符! 所以我们以“00”,“10”等结束。 最后,它只返回0或1,但前提是(abool和)bbool是正值或0!

    那么,您是如何在Oracle中处理布尔值的呢?为了能够为2个或更多其他布尔列构建一个可理解的OR(and)代码,哪种代码最合适,而且性能也很好?

    1 回复  |  直到 2 年前
        1
  •  1
  •   MT0    2 年前

    使用功能 BITAND (至少来自Oracle 11)和 BITOR (来自Oracle 21,尽管没有文档记录)并将 CHECK

    SELECT abool,
           bbool,
           BITAND(abool, bbool),
           BITOR(abool, bbool)
    FROM   test_bool_number
    ORDER BY test_id;
    

    对于样本数据:

    create table test_bool_number (
        test_id NUMBER GENERATED BY DEFAULT AS IDENTITY,
        abool NUMBER(1) CHECK (abool IN (0, 1)),
        bbool NUMBER(1) CHECK (bbool IN (0, 1))
        PRIMARY KEY(test_id)
    );
    
    INSERT INTO test_bool_number (abool, bbool)
                select 0, 0 from dual
      union all select 0, 1 from dual
      union all select 1, 0 from dual
      union all select 1, 1 from dual;
    

    BITOR(ABOOL,BBOOL)
    0 0
    1. 1.
    1. 0 0 1.
    1. 1. 1.

    create a user-defined function for BITOR .

    数据库(&L)&燃气轮机;不停摆弄 here