The End of Y/N and 0/1 Workarounds
For decades, Oracle developers have used NUMBER(1) with 0/1 values or VARCHAR2(1) with Y/N flags to represent Boolean logic in database tables. Every team had its own convention, every application its own mapping layer, and every table its own set of CHECK constraints to enforce valid values. Oracle Database 23ai/26ai finally introduces a native BOOLEAN data type that works across SQL, PL/SQL, table columns, and application bind variables – bringing Oracle in line with the SQL standard and eliminating years of ambiguity.
Why This Matters
The native BOOLEAN type delivers several immediate benefits:
- Code clarity:
WHERE is_activereplacesWHERE is_active = 1orWHERE is_active = 'Y' - ORM compatibility: Modern frameworks like Hibernate, Entity Framework, and Django expect Boolean column support – no more custom type mappings
- Implicit conversions: Oracle handles conversion between BOOLEAN and numeric (TRUE=1, FALSE=0) and character (‘TRUE’/’FALSE’) types automatically
- SQL/PL/SQL unification: BOOLEAN now works seamlessly in both contexts, including function return values used directly in SQL queries
Example 1: Creating Tables with BOOLEAN Columns
You can now define BOOLEAN columns with defaults, NOT NULL constraints, and use TRUE/FALSE literals directly.
CREATE TABLE customers (
customer_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
customer_name VARCHAR2(200) NOT NULL,
email VARCHAR2(200) NOT NULL,
is_active BOOLEAN DEFAULT TRUE NOT NULL,
is_verified BOOLEAN DEFAULT FALSE,
accepts_marketing BOOLEAN DEFAULT FALSE NOT NULL
);
INSERT INTO customers (customer_name, email, is_active, is_verified, accepts_marketing)
VALUES ('Ahmed Baraka', 'ahmed@example.com', TRUE, TRUE, FALSE);
INSERT INTO customers (customer_name, email)
VALUES ('Sara Khan', 'sara@example.com');
-- is_active defaults to TRUE, is_verified to FALSE, accepts_marketing to FALSE
Example 2: Querying with Boolean Expressions
BOOLEAN columns can be used directly in WHERE clauses without comparison operators. Oracle also supports IS TRUE, IS FALSE, and IS NOT NULL predicates.
-- Direct Boolean predicate (no = TRUE needed)
SELECT customer_name, email
FROM customers
WHERE is_active
AND NOT accepts_marketing;
-- Using IS TRUE / IS FALSE for explicit readability
SELECT customer_name,
is_active,
is_verified,
CASE WHEN is_verified IS TRUE THEN 'Confirmed' ELSE 'Pending' END AS status
FROM customers
WHERE is_verified IS FALSE;
-- Implicit conversion: BOOLEAN to NUMBER in aggregation
SELECT COUNT(*) AS total_customers,
SUM(TO_NUMBER(is_active)) AS active_count,
SUM(TO_NUMBER(is_verified)) AS verified_count
FROM customers;
Example 3: BOOLEAN in PL/SQL Functions Used in SQL
Previously, PL/SQL BOOLEAN functions couldn’t be called from SQL. Now they can be used directly in queries, SELECT lists, and WHERE clauses.
CREATE OR REPLACE FUNCTION is_premium_customer(
p_customer_id IN NUMBER
) RETURN BOOLEAN IS
v_order_total NUMBER;
BEGIN
SELECT NVL(SUM(order_amount), 0)
INTO v_order_total
FROM orders
WHERE customer_id = p_customer_id;
RETURN v_order_total > 10000;
END;
/
-- Call Boolean function directly in SQL
SELECT customer_name,
is_premium_customer(customer_id) AS is_premium
FROM customers
WHERE is_active;
Example 4: Migrating Legacy Flag Columns to BOOLEAN
For existing tables using NUMBER(1) or VARCHAR2 flags, you can migrate to native BOOLEAN using ALTER TABLE with implicit conversion and maintain backward compatibility through views.
-- Original legacy table
-- ALTER TABLE employees ADD is_manager_bool BOOLEAN;
-- UPDATE employees SET is_manager_bool = (is_manager = 1);
-- Simplified approach: add new BOOLEAN column with conversion
ALTER TABLE employees ADD (
is_manager_new BOOLEAN DEFAULT FALSE NOT NULL
);
UPDATE employees
SET is_manager_new = CASE WHEN is_manager = 1 THEN TRUE ELSE FALSE END;
-- Backward-compatible view for legacy applications
CREATE OR REPLACE VIEW employees_legacy_v AS
SELECT employee_id,
employee_name,
is_manager_new AS is_manager_bool,
TO_NUMBER(is_manager_new) AS is_manager -- returns 1 or 0
FROM employees;
-- Once legacy apps are updated, drop the old column
-- ALTER TABLE employees DROP COLUMN is_manager;
-- ALTER TABLE employees RENAME COLUMN is_manager_new TO is_manager;
Key Takeaways
- Use BOOLEAN for all new true/false columns – stop using NUMBER(1) or VARCHAR2 flag patterns in Oracle 23ai/26ai.
- Simplify your WHERE clauses – write
WHERE is_activeinstead ofWHERE is_active = 1. - PL/SQL Boolean functions now work in SQL – a major unification that eliminates wrapper functions and type conversion hacks.
- Implicit conversions are built in – BOOLEAN converts to/from NUMBER (1/0) and VARCHAR2 (‘TRUE’/’FALSE’) automatically where needed.
- Plan your migration – use ALTER TABLE, online redefinition, and backward-compatible views to refactor legacy flag columns incrementally.
