Oracle claims that 23c has 300+ new features and enhancements compared to 21c. This page summarizes the features that are of particular interest to me.
Because of the importance of Artificial Intelligence technology in this release, Oracle renamed 23c to 23ai.
BOOLEAN data type in SQL
Oracle 23c introduces the booleandatatype for SQL (after it having been in PL/SQL for quite some time).
Some textual values such as true, false, y, yes will be converted to a boolean value, any numerical value that is not 0 will be converted to true, 0 values to false.
create table tq84_bool_test (val varchar2(10), flg boolean);
insert into tq84_bool_test values ('true' , true );
insert into tq84_bool_test values ('false' , false);
insert into tq84_bool_test values ('null' , null );
insert into tq84_bool_test values ('t' ,'t' );
insert into tq84_bool_test values ('yes' ,'yes' );
insert into tq84_bool_test values ('true' ,'true');
insert into tq84_bool_test values ('f' ,'f' );
insert into tq84_bool_test values ('0' , 0 );
select val from tq84_bool_test where flg;
select val from tq84_bool_test where not flg;
The new datatype comes with the function to_boolean(…).
The introduction of the boolean data type is rather unexpected: Some 20 years ago, Tom Kyte asserted that a boolean datatype is not needed
since
flag char(1) check (flag in ( 'Y', 'N' ))
serves the same purpose, requires the same amount of space and does the same thing.
Oracle clients earlier than 23c will display true values as 1 and false values as 0:
create mle module tq84_js language javascript as
export function f(p1, p2) { return p1+p2; }
…
create function f (p1 number, p2 number) return number as mle module tq84_js signature f(number, number);
select f(20, 22) /* Ha: no more dual :-) */;
If the group_by_position_enabledinit parameter is set to true, it's also possible to group by a position number In order to group on a position number (rather than an expression alias):
alter session set group_by_position_enabled = true;
select
category_id,
sum(val)
from
t
group by
1;
the way an application consumes and represents data (i. e. JSON documents) and
the paradigm in which a relational database stores the data (i. e. rows).
The conversion is between these two worlds is triggered in/with GraphQL.
create or replace JSON DUALITY VIEW
from tq84_root_tab -- The name table sitting at the top of the hierarchy
as
tq84_rel_dual_test
@update @insert @delete
{
num : col_num, -- Mapping between JSON property names and table column names
txt : col_txt
children : tq84_child_tab { -- Nesting objects
…
}
}
Accessing duality views
A duality view can be accessed with
SQL
traditional HTTP/REST operations, i. e. GET, PUT and POST HTTP requests. (see concurrent reading/writing access below)
Simple Oracle Document API (SODA)
Oracle Database API for MongoDB
ORDS
Concurrent reading/writing access
REST GET and REST PUT are stateless operations. Thus, a writing operation might overwrite the modification of another writing request («mid-air collision» problem).
In order to avoid this problem, Oracle has adapted the concept of the ETag response and If-Match request HTTP header (see also the function sys_row_etag).
Advantages over ORM
Some advantages of duality views over Object Relational Mappings (ORMs) are
They're language independent
They're optimized by the database
Describing a duality view's schema
dbms_json_schema.describe('tq84_rel_dual_test')
$dbHost=…
$schemaName=rene
curl -X GET http://$dbHost/ords/$schemaName/metadata-catalog/tq84_rel_dual_test
The order clause of the month_year domains influences the sort order of order by so that it is sorted logically rather than by the by the displayed value:
select
rep_period,
corrections_to,
id
from
financial_report
order by
rep_period;
--
-- REP_PER CORRECTIONS_TO ID
-- ------- -------------- ----------
-- 02-2023 maya@xyz.ab 3
-- 03-2023 fred@xyz.ab 1
-- 06-2023 joey@xyz.ab 4
-- 08-2023 fred@xyz.ab 2
domain_display(…) applies the display rules when selecting values from a domain:
A session updates a record in this table and then queries the value (which does not seem to change, i.e. is still 100):
SES 1> update tq84_async set val = val + 10 where id = 42;
SES 1> select * from tq84_async where id = 42;
--
-- ID VAL
-- ---------- ----------
-- 42 100
Another session also updates val (while the first session has not commited the update). This session also sees the value of 100:
SES 2> update tq84_async set val = val + 1 where id = 42;
SES 2> select * from tq84_async where id = 42;
--
-- ID VAL
-- ---------- ----------
-- 42 100
The first session then commits its transaction. It now sees its modification:
SES 1> commit;
SES 1> select * from tq84_async where id = 42;
--
-- ID VAL
-- ---------- ----------
-- 42 110
The second session also sees the update of the first session but still not its own update:
SES 2> select * from tq84_async where id = 42;
--
-- ID VAL
-- ---------- ----------
-- 42 110
Only when the 2nd session commits its transaction, its modification becomes visible also:
SES 2> commit;
SES 2> select * from tq84_async where id = 42;
--
-- ID VAL
-- ---------- ----------
-- 42 111
After the commit in the second session, the first session commits also and then selects the updated record:
SES 1> commit;
SES 1> select * from tq84_tab;
ID VAL
--------- ---------
42 111
A table with a reservable column cannot be dropped (error message ORA-55764: Cannot DROP or MOVE tables with reservable columns). Thus, the column must be first set to not reservable:
alter table tq84_async modify val not reservable;
drop table tq84_async;
See also
See also Connor McDonald'stweet and the follow up on YouTube.
Improved error messages
A program of Oracle (that is not strictly related to 23c only) tries to improve error messages:
ORA21> select sum(val), gr_1, gr_2 from T group by gr_1;
ORA-00979: not a GROUP BY expression
ORA21> connect …@ORA23
ORA23> select sum(val), gr_1, gr_2 from T group by gr_1;
ORA-00979: "GR_2": must appear in the GROUP BY clause or
be used in an aggregate function
Some of the messages that seem to have changed include
ORA-00932 from ORA-00932: inconsistent datatypes: expected … got … to ORA-00932: expression is of data type …, which is incompatible with expected data type ….
ORA-01722 from invalid number to unable to convert string value containing … to a number.
ORA-30926 from unable to get a stable set of rows in the source tables to The operation attempted to update the same row (rowid: …) twice.
ORA-06509 from PL/SQL: ICD vector missing for this package to PL/SQL: Interface call failed between the PL/SQL package and a binary executable.
Information about all migrations from AQ classic queues to Transactional Event Queues (TxEventQs).
dba_unused_schema_privs
Schema privileges (without privilege grant paths) that are not used for the privilege analysis policies reported by the dbms_privilege_capture.generate_result procedure. Compare with dba_used_schema_privs
dba_unused_schema_privs_path
Compare with dba_used_schema_privs_path
dba_used_schema_privs
Schema privileges (without privilege grant paths) that are used for the privilege analysis policies reported by the dbms_privilege_capture.generate_result procedure. Compare with dba_unused_schema_privs_path
Globally distributed database Raft repliation: a consensus-based commit protocol, enabling declarative replication which does not need Golden Gate or Data Guard.
OJM allows HTTP and TCP access while other OS calls are disabled
On OCI: Oracle Database Zero Data Loss Autonomous Recovery Service (with which Oracle hopes to address the challenges of ransomware, outages and human errors)
On OCI: Oracle Full Stack Disaster Recovery Service (Configuration, monitoring and management of the disaster recovery process for the full stack of technologies, including middleware, databases, networks, storage)
Support for Unicode Ideographic Variation Sequences (IVS)
Docker image
There is a docker image for the free edition of Oracle 23c:
With this password, I could then connect to the instance from SQL Developer using the service names FREE and FREEPDB1 (see /opt/oracle/product/23c/dbhomeFree/network/admin/tnsnames.ora)
It should be noted that all changes to the database disappear when the docker container is stopped.