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" 



OCW 2024: What to Expect Around Oracle 23ai

  I’m so excited to share that I’ll be attending Oracle CloudWorld 2024 this year!. I’m thrilled as It will be my first OCW event to attend ...