By now I’m sure you have seen the excitement due to the arrival (finally) of the new Boolean datatype in the Oracle database. If not, check out my video at the bottom of this post for a rapid fire introduction. But there is more to having a datatype to just storing it. We also want to be able to query it and use all the power of SQL to get the results we need. And with new datatypes, comes some cool new functions as well.

Let’s start with a copy of SCOTT.EMP



SQL> create table t as
  2  select
  3    empno,
  4    ename,
  5    deptno,
  6    hiredate,
  7    job
  8  from scott.emp;

Table created.

I’m going to tweak a few values just so my examples cover all of the scenarios I want to cover.



SQL> update t
  2  set hiredate = hiredate + 365
  3  where empno in (7782,7839);

2 rows updated.

Let’s say I want a new Boolean column called LONGTERM which indicates if you have been a long and valued employee of this organisation. I’ll add the column and populate it based on the HIREDATE


SQL> alter table t add longterm boolean;

Table altered.

SQL> update t
  2  set longterm =   hiredate < date '1982-01-01';

14 rows updated.

SQL> select * from t
  2  order by deptno, hiredate;

     EMPNO ENAME          DEPTNO HIREDATE  JOB       LONGTERM
---------- ---------- ---------- --------- --------- -----------
      7934 MILLER             10 23-JAN-82 CLERK     FALSE
      7782 CLARK              10 09-JUN-82 MANAGER   FALSE
      7839 KING               10 17-NOV-82 PRESIDENT FALSE
      7369 SMITH              20 17-DEC-80 CLERK     TRUE
      7566 JONES              20 02-APR-81 MANAGER   TRUE
      7902 FORD               20 03-DEC-81 ANALYST   TRUE
      7788 SCOTT              20 09-DEC-82 ANALYST   FALSE
      7876 ADAMS              20 12-JAN-83 CLERK     FALSE
      7499 ALLEN              30 20-FEB-81 SALESMAN  TRUE
      7521 WARD               30 22-FEB-81 SALESMAN  TRUE
      7698 BLAKE              30 01-MAY-81 MANAGER   TRUE
      7844 TURNER             30 08-SEP-81 SALESMAN  TRUE
      7654 MARTIN             30 28-SEP-81 SALESMAN  TRUE
      7900 JAMES              30 03-DEC-81 CLERK     TRUE

14 rows selected.

Whilst all of the standard “simple” SQL predicates will work fine on a Boolean like any other column, what about questions that are specific to the Boolean nature of this column. For example, what if I wanted to know if all of the employees per department were long-termers? It’s nice to discover that the standard aggregation functions work fine with a Boolean.


SQL> select
  2    deptno,
  3    max(longterm)
  4  from t
  5  group by deptno
  6  order by 1;

    DEPTNO MAX(LONGTER
---------- -----------
        10 FALSE
        20 TRUE
        30 TRUE

But that doesn’t really answer my question. I can say from the above results that definitely department 10 has no long term employees (because FALSE is sorted lower than TRUE, hence the MAX aggregation means that all values are FALSE for department 10), but I need more information for departments 20 and 30, because some of the values are FALSE and some are TRUE. So I need to look at the MIN as well.


SQL> select
  2    deptno,
  3    max(longterm),
  4    min(longterm)
  5  from t
  6  group by deptno
  7  order by 1;

    DEPTNO MAX(LONGTER MIN(LONGTER
---------- ----------- -----------
        10 FALSE       FALSE
        20 TRUE        FALSE
        30 TRUE        TRUE

I have all the information I need now, but it still takes more tinkering to convert into this to become the answer of “Are all employees long term?”


SQL> select
  2    deptno,
  3    case
  4      when max(longterm) = min(longterm) and min(longterm) = false then 'ALL FALSE'
  5      when max(longterm) = min(longterm) and max(longterm) = true then 'ALL TRUE'
  6      else 'MIXED'
  7    end result
  8  from t
  9  group by deptno
 10  order by 1;

    DEPTNO RESULT
---------- ---------
        10 ALL FALSE
        20 MIXED
        30 ALL TRUE

Luckily, we can avoid having to resort to this kind of jiggery-pokery because we have a couple of brand new Boolean-specific aggregation functions in 23ai. The BOOLEAN_OR_AGG function will aggregate Boolean values in a logical “OR” fashion, thus returning TRUE if any row value is true, and BOOLEAN_AND_AGG will aggregate Boolean values in a logical “AND” fashion, returning TRUE only if all row values are true.


SQL> select
  2    deptno,
  3    boolean_or_agg(longterm) b_or,
  4    boolean_and_agg(longterm) b_and
  5  from t
  6  group by deptno
  7  order by 1;

    DEPTNO B_OR        B_AND
---------- ----------- -----------
        10 FALSE       FALSE
        20 TRUE        FALSE
        30 TRUE        TRUE

It becomes much easier and more intuitive now once we fold those functions into our query to get the results we wanted.


SQL> select
  2    deptno,
  3    case
  4      when boolean_or_agg(longterm) = false then 'ALL FALSE'
  5      when boolean_and_agg(longterm) = true then 'ALL TRUE'
  6      else 'MIXED'
  7    end result
  8  from t
  9  group by deptno
 10  order by 1;

    DEPTNO RESULT
---------- ---------
        10 ALL FALSE
        20 MIXED
        30 ALL TRUE

SQL>

In case you were wondering, the thumbnail for this post it George Boole, the man we can thank for all of this 🙂

4 responses to “More Boolean features in 23ai”

  1. Pavel Vasilenko Avatar
    Pavel Vasilenko

    good feature, but expression “something = true” looks creepy.
    It looks like somebody doesn’t get used to boolean is SQL yet… 🙂

    1. I was hoping someone would spot that 🙂
      It’s not ignorance but a bug in the 23c beta. If you leave it out, the statement fails (currently)

      SQL> with t as
      2 ( select true x union all select false union all select null)
      3 select
      4 case
      5 when min(x) then ‘i am true’
      6 when not min(x) then ‘i am false’
      7 else ‘null’
      8 end
      9 from t;
      when min(x) then ‘i am true’
      *
      ERROR at line 5:
      ORA-00920: invalid relational operator

Got some thoughts? Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Trending