Thursday, June 20, 2024

Oracle 23ai: Fetch Top-N Rows Per Group Queries

 

Overview:

  • Oracle 23ai introduces the use of partition by clause in fetch first clause to get top-N rows per group.
  • A query's syntax
          SELECT ........
          FROM    ........
          ORDER BY <group>, <sort>
          FETCH FIRST <M> <group>, <N> ROWS ONLY

           Where:
           - group: a column or expression that will be used to group rows.
           - M: specifies how many different groups you want to return.
           - sort: a column or expression that will be used to sort rows ASC|DESC.
           - N: specifies the first rows for each group returned.

   In this blog, I'll show two demos demonstrating the use of partition by in fetch first clause to get top-N rows per group.


- Prerequisites:
  • Oracle Database 23ai.

Demo #1

- Fetch the two highest paid employees for the first three departments.

   Where:
    - group: column departments.department_id.
    - M: 3.
    - sort: column employees.salary DESC.
    - N: 2.

SELECT department_id,department_name, salary, first_name, last_name
FROM employees join DEPARTMENTS USING (DEPARTMENT_ID)
ORDER BY department_id, salary DESC
FETCH FIRST
      3 PARTITION by department_id,
      2 ROWS ONLY;






















Demo #2

- Fetch the latest hired employee in each department. 

   Where:
    - group: column departments.department_id.
    - M: set to a large value. For example, 10000000.
    - sort: column employees.hire_date DESC.
    - N: 1.

SELECT DEPARTMENT_ID, HIRE_DATE, first_name, last_name
FROM employees 
ORDER BY DEPARTMENT_ID, HIRE_DATE DESC
FETCH FIRST
      999999999999 PARTITION by DEPARTMENT_ID,
      2 ROWS ONLY;






Wednesday, June 5, 2024

Oracle 23ai: Comparing and Sorting JSON Datatypes

 

- Overview:

  • Oracle first introduced the JSON datatype in Oracle database 21c.
  • Oracle Database 23ai introduces the option to compare and sort JSON datatypes.
    • It allows equality comparison and sorting of JSON values.
    • It is supported in WHERE, ORDER BY, and GROUP BY clauses.
    • It makes for more powerful SQL/JSON programs.
    • Avoids unexpected datatype conversion problems.
In this blog, I'll show different demos demonstrating JSON datatype comparing and sorting.

- Prerequisites:
  • Oracle Database 23ai.
  • SQL Developer.

Demo #1: Compare JSON Documents in Two Tables


1. Create two tables with a column, which has a JSON datatype. 

create table json_data1 (col1 json);
create table json_data2 (col2 json);

2. Insert JSON documents into both tables with a name object has name and address fields, and address field has street and city individual fields.
  
INSERT into json_data1 
values (' {"name":"Scott", "address": {"street":"123 Bay St", "City":"Toronto"} }');
INSERT into json_data2 
values (' {"name":"Adam", "address": {"City":"Toronto", "street":"123 Bay St"} }');

    - You notice that the city and street in above JSON documents are in a different order across the two different tables.

3. Join the two tables on address field.
    - Prior to 23ai, we would need to know the fields within the address to compare individual fields.
    - However in 23ai, this becomes much more easier, where we join two tables with address fields without pointing to the individual fields within the field address as shown below.

select * from json_data1 t1, json_data2 t2 where t1.col1.address = t2.col2.address;

Demo #2: JSON Type Comparison


1. Create a table with a column, which has a JSON datatype.

create table json_tab (col1 json);

2. Insert JSON documents with a name object has fname and lname fields.

insert into json_tab values ('{"name": {"fname":"Scott", "lname":"Tiger"} }');
insert into json_tab values ('{"name": {"fname":"Adam", "lname":"Smith"} }');
insert into json_tab values ('{"name": {"lname":"Tiger", "fname":"Scott"} }');


















3. Query the table by trying to match name object where fname/lname fields are in a different order. 
    - Notice that, the query will return the first 2 documents where fname/lname fields are in a different order and fname/lname fields are in the same order.

select * from json_tab t
where t.col1.name = json('{"lname":"Tiger", "fname":"Scott"}');



















Demo #3: Sorting Mixed JSON Type Values


1. Create a table with a column, which has a JSON datatype.

create table json_sort (col1 json);

2. Insert different documents with a variety of  array, numeric, and string values.

insert into json_sort values ('{"jdoc": {"a":"b", "c": 1} }'); --- object 
insert into json_sort values ('{"jdoc": {"a":"z", "c": 10} }'); --- object
insert into json_sort values ('{"jdoc": [100, 500, 1000] }'); --- Array
insert into json_sort values ('{"jdoc": 20 }'); --- numeric  
insert into json_sort values ('{"jdoc": 60 }'); --- numeric 
insert into json_sort values ('{"jdoc": "10" }'); --- string


























3. Query the rows using string ordering (using JSON_SERIALIZE function).

select t.col1.jdoc from json_sort t order by JSON_SERIALIZE(t.col1.jdoc);











































4. Query the rows in JSON type default order, which is number, string, object, array.

select t.col1.jdoc from json_sort t order by t.col1.jdoc;



Tuesday, June 4, 2024

Oracle 23ai: JSON Schema Support

 

- Overview:

  • Oracle first introduced the ability to display a JSON schema when they introduced the JSON Data in Oracle 12.2, but without the option to validate the structure of JSON document.
  • Oracle Database 23ai introduces a new feature called JSON Schema
  • A JSON Schema can validate the structure and contents of JSON documents in your database when defining a JSON column in our table.
  • A JSON Schema is a declarative language that allows us to annotate and validate JSON documents, which helps avoid errors in production that were missed in development.
  • A JSON schema specifies the allowed properties for JSON documents.
  • A JSON Schema validation is available also as a PL/SQL utility function.
In this blog, I'll demonstrate the use of the VALIDATE clause along with the JSON schema when defining a JSON column in our table.

- Prerequisites:
  • Oracle Database 23ai.

Demo #1: A simple validation using the IS JSON keywords


1. Create a table with a column, which has a JSON datatype with a check constraint. 
     A "IS JSON VALIDATE USING" clause will be used for check constraint validation. 
     
    create table json_tab (
    col1 json constraint json_tab_col1_isjson check (col1 is json validate using
     '{
       "type":"object",
       "minProperties":2
      }')
     );   










2. Insert JSON data into the table.
    - Insert invalid JSON data by inserting an array. This will raise ORA-40875 error.

       insert into json_tab values ('["a","b"]');














    - Insert valid JSON data.

       insert into json_tab values ('{"a":1,"b":2}');








Demo #2: A simple validation using the shorthand syntax without the constraint keyword


1. Create a table with a column, which has a JSON datatype without a check constraint.
    A "VALIDATE USING" clause will be used for JSON document validation. 
    The JSON document has two properties price (number) and name (string).

    create table json_tab2 (
    col1 json validate using
      '{
        "type":"object",
        "properties": {"price":{"type":"number"},
                               "name": {"type":"string"}
                              }
       }'
    );
















2. Insert JSON data into the table.
    - Insert invalid JSON data by inserting a JSON document with invalid price property value datatype. This will raise ORA-40875 error.

insert into json_tab2 values ('{"price":"ten", "name":"widget"}');   --- price property value is string















- Insert valid JSON data.

   insert into json_tab2 values ('{"price":10, "name":"widget"}');














Demo #3: A simple validation using SQL-Domain based JSON Validation Rules


1. Create SQL-Domain with a column, which has a JSON datatype without a check constraint.
    A "VALIDATE USING" clause will be used for JSON document validation. 
    The JSON document has two required properties width and height where both properties have a number datatype and minimum and maximum values. 

create domain json_size_domain as json validate using
 ' { "type": "object",
     "required": [ "width", "height" ],
     "properties": {
                    "width": { "type": "number", "minimum":20, "maximum": 62 },
                    "height": { "type": "number", "minimum":25, "maximum": 50 }
                    }
    } ';

2. Create a table with a column, which has a JSON datatype and uses the created domain.

create table json_tab3 (col1 json domain json_size_domain);















3. Insert JSON data into the table.
    - Insert invalid JSON data by inserting a JSON document where width property has invalid value (< minimum value). This will raise ORA-40875 error.

insert into json_tab3 values ('{"width":0, "height":49}'); --- width value < 20 (minimum value) 














- Insert valid JSON data.

insert into json_tab3 values ('{"width":30, "height":49}');

























Demo #4: Validate using the VALIDATE_REPORT utility Function


1. Call VALIDATE_REPORT utility function on an invalid JSON document. The function will report back "valid":"false" with the error message.
























2. Call VALIDATE_REPORT utility function on a valid JSON document. The function will report back "valid":"true" 



Oracle 23ai: Hybrid Read-Only Mode for Pluggable Databases

  - Overview: Oracle 23ai database introduces a new feature to open Pluggable database in  a new mode called hybrid read-only. Hybrid read-o...