我们必须在两个这样的列之间建立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)代码,哪种代码最合适,而且性能也很好?