Monday, October 30, 2023

Oracle OCI Product Tours Page

 Oracle has a new (?) Oracle Cloud Infrastructure (OCI) Product Tours page: https://www.oracle.com/cloud/product-tours/ 

 


At the moment the Analytics section seems to be very active: https://www.oracle.com/cloud/product-tours/#analytics


I like the links to the YouTube videos.

See if you find anything interesting there.


If you are here, this is a reminder of the Analytics Live Demos page:  https://www.oracle.com/business-analytics/data-visualization/demos/ where you can run a live demo (see arrow), download useful elements (Examples, Extensions, Geo Layers and Rest Connectors), add your ideas in Idea Lab and see Videos.


Tuesday, October 24, 2023

Oracle (with or without APEX) - adding insert and update time and user to table

 We had an APEX project where  we wanted to add auto-generated key, and save both date/time and user that made the insert and last update.In Oracle, the basic idea is to use a trigger and (for the key) a sequence. 

I was sure I will find lots of examples, but didn't find one that seemed like perfect fit for me. So I got some help from my colleague Matan Poran, who has a rare combination of both great professionality and  personality. 

Lets start with this link: https://www.insum.ca/feuertip-41-tips-for-triggers/  

I will have here code for the following:

  • Adding the 4 "create/update time/user" columns to table.
  • Adding trigger that deals only with those 4 columns with Apex users.
  • Creating a sequence.
  • Adding trigger that deals with those 4 columns with Apex users and inserting the sequence based auto-generated key.

Modify "Your_Table" by adding 4 "create/update time/user" columns

alter table "YOUR_TABLE" add (
"CREATE_DATE" DATE,
"CREATED_BY" VARCHAR2(128),
"UPDATE_DATE" DATE,
"UPDATED_BY" VARCHAR2(128)     );

 

Adding trigger that deals only with those 4 columns with Apex users

create or replace TRIGGER "Your_Trigger_Name"  
before
insert or update on "YOUR_TABLE
" --
for each row
begin
    if inserting then
            :new.CREATE_DATE:=SYSDATE;
            :new.CREATED_BY:=nvl(sys_context('APEX$SESSION','APP_USER'),user);
     end if;
     if UPDATING then
        :new.UPDATE_DATE := SYSDATE;
        :new.UPDATED_BY := nvl(sys_context('APEX$SESSION','APP_USER'),user);
    end if;
end;
/

If you are not in an APEX case you can use your user definition. For example in Oracle SQL:

 create or replace TRIGGER "Your_Trigger_Name"  
before
insert or update on "YOUR_TABLE" --
for each row
begin
    if inserting then
            :new.CREATE_DATE:=SYSDATE;
            :new.CREATED_BY:=trim(upper(user));
     end if;
     if UPDATING then
        :new.UPDATE_DATE := SYSDATE;
        :new.UPDATED_BY := trim(upper(user));
    end if;
end;
/


 
 We can complicate it a bit. For example setting value for CREATED_BY only if the user wasn't updated manually:

 create or replace TRIGGER "Your_Trigger_Name"  
before
insert or update on "YOUR_TABLE" --
for each row
begin
    if inserting then
            :new.CREATE_DATE:=SYSDATE;
            if :new.CREATED_BY is null then :new.CREATED_BY:=trim(upper(user)); end if;
     end if;
     if UPDATING then
        :new.UPDATE_DATE := SYSDATE;
        :new.UPDATED_BY := trim(upper(user));
    end if;
end;
/
 

 

    Yes, this code works for multiple updates.

**    Please note that trigger names are case sensitive!

 

 

The following enhances the above code to include Auto-generated primary key based on sequence.

 

Creating a sequence

If you are in APEX you can create a sequence by using right click in sequences in Object Browser.

anyway the basic sequence code for creating the sequence named YOUR_TABLE_SEQ is:

create sequence "YOUR_TABLE_SEQ"
start with 1
increment by 1
cache 20
nocycle;


Adding trigger that deals with those 4 columns with Apex users and inserting the sequence based auto-generated key

Assuming there is a column KEY_COL used as primary key and you want the sequence to update it. I will use the previous sequence. 

All is needed is one extra row:

create or replace TRIGGER "Your_Trigger_Name"  
before
insert or update on "YOUR_TABLE
" --
for each row
begin
    if inserting then 

            if :new.KEY_COL is null then :new.KEY_COL:=YOUR_TABLE_SEQ.nextval; end if;
            :new.CREATE_DATE:=SYSDATE;
            :new.CREATED_BY:=nvl(sys_context('APEX$SESSION','APP_USER'),user);
     end if;
     if UPDATING then
        :new.UPDATE_DATE := SYSDATE;
        :new.UPDATED_BY := nvl(sys_context('APEX$SESSION','APP_USER'),user);
    end if;
end;

P.S.

Please note that sometime the sequence based key can be a security issue when used in URL (then, if security not hardened enough, user can try the next value in the URL). In APEX this is solved by using "Session State Protection", so generated link will also include a checksum. See more about it in the following Blog: https://hartenfeller.dev/blog/apex-security-sequences-risk

(In few words: Enable Session State Protection in shared components under security, on page level setting - security: for Page Access protection, set "Arguments Must Have Checksum".)


Monday, October 9, 2023

Oracle Analytics and AI services usefull links

 Oracle Cloud Analytics and AI services. 

Links to product page, Documentation page, API, CLI & Python SDK.

Few extras for some products, when relevant.

OCI Product Product Link Documentation API CLI Python SDK Extra
General link link link link link link
AI Services - Anomaly Detection link link link link link
AI Services - Digital Assistant link link link link SDKs for Mobile
AI Services - Document Understanding link link link link link
AI Services - Forecasting link




AI Services - Language  link link link link link
AI Services - Vision link *
AI Services -  Speech link
Analytics Cloud (OAC) link link link link link !
Generative AI link link link


Machine Learning in Oracle Database link link link link link **
OCI Data Labeling link link link link link ***
OCI Data Science Link link link link ****
OCI Data Science - ML pipelines link (pipelines) link
Fusion Analytics link link


























*     AI Services - Vision



**   Machine Learning in Oracle Database OML4Py API




***  OCI Data Labeling Data Labeling Management API Data Labeling Service Dataplane
**** OCI Data Science ADS SDK ADS SDK CLI CONDA odsc CLI

!    OAC creating instances APIs              link

 

 

 

 

Monday, August 14, 2023

Hackathon Posts - Oracle APEX - Low Code App Platform

Few posts planned for use in expected Hackathons.

Oracle APEX (formerly known as Oracle Application Express) is a very popular Low Code App Platform by Oracle. It is used for developing and deploying cloud, mobile, and desktop applications. The platform offers a web-based integrated development environment (IDE) with a range of features including wizards, drag-and-drop layout, and property editors to simplify the process of building applications and pages.

APEX is a fully-supported no-cost feature of the Oracle Database and can be installed anywhere Oracle Database runs. APEX is also offered on Oracle's Cloud across various services including Autonomous Database Cloud Services and the stand-alone fully managed APEX Application Development service.

 

How to start?

If you have an existing Autonomous Database, you can access the Database Actions - View all database actions and select APEX.




If you don't, you can create an Autonomous database for APEX workload type.


How to learn?

There are lots of great tutorials in Oracle LiveLabs (the site itself is created with APEX):

For starter consider one of the following (first 2 available also on LiveLabs sandbox):

 

For Specific issues there are lots of blogs for the topics and also the following tutorials on LiveLabs: 


There several specific cases examples such as 
 

  

You can also check this Videos page here there many specific tips there.

 

This is the documentation page - https://docs.oracle.com/en/database/oracle/apex/index.html

 

For local installations this is the installation guide.


Friday, August 11, 2023

Oracle Spatial - loading geographic data - Line

 Following the previous post - Oracle Spatial - SQL based Geographic data - Intro, few examples of loading lines of geographical data. Line is usually used when we have routes.

I will cover here:

  • Manual creation
  • Loading GeoJSON

Simple example - Manual Creation of line based on few points

Step 1 & Step 2: Lets assume we have 3 geographic data points that creates a line. 

I will create a table with few descriptions and the line:

create table Line0 as
select  
100 as code,
'Morning Walk' as descript,
SDO_GEOMETRY(
                 2002,                                         -- 2002 - two dimensional line
                 4326,                                         -- our usual coordinate system for lon/lat
                 NULL, -- ONLY for points
                 SDO_ELEM_INFO_ARRAY(1, 2, 1),    --line
                 SDO_ORDINATE_ARRAY(    -- lon/lat values
                    34.809512,    32.099221, 
                    34.810434,    32.099269,
                    34.810434,    32.099999
                 )
            ) as geometry
from dual;

Check it works fine:


And create the spatial index:

Step 3: Before creating a spatial index, we must insert a row of spatial metadata.

INSERT INTO USER_SDO_GEOM_METADATA VALUES (
  'Line0',  -- table name
  'GEOMETRY',    -- geometry column name
  SDO_DIM_ARRAY(
    SDO_DIM_ELEMENT('X', -180, 180, 0.005),
    SDO_DIM_ELEMENT('Y', -90, 90, 0.005)),
   4326           -- indicates longitude/latitude coordinates (
coordinate system)
 );

Step 4: Create a spatial Index for performance

CREATE INDEX Line0_SIDX ON
      Line0 (
          GEOMETRY
      )
          INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2;


Line GeoJSON based example

GeoJSON (see at https://geojson.org/) is a standard in the industry. 

GeoJson structure from LiveLabs workshop

Naturally, GeoJSON is still a JSON file. Oracle has now many JSON oriented options. There is an Autonomous JSON Database in Oracle cloud or simple drag and drop UI in "regular" Autonomous Database for JSON files loading. Yet, we have basic JSON support even in earlier versions such as 12c.

 In the Spatial Data LiveLab here (Lab 3) we have an example of loading data from files ans setting region tables in Autonomous Database. I will do a simple manual version of that process, that is less trivial that what is done in the Autonomous example of the Tornado Path file.

So our JSON file has the following structure:


 We want to load a JSON file into the database.

The JSON file is located in some storage that is mapped in the DB to a Directory. Access to directory required by spatial user to load JSON File. If needed system user / Admin should run something like:

GRANT read on DIRECTORY TEMP_DIR to user_name;
 

I will create a table named Line_GEOJSON that contains a single clob column named CLOB_JSON:

 Load the file tornado_paths.geojson

declare
    b bfile := bfilename('TEST_DIR','tornado_paths.geojson');
    c clob;
  l_dest_offset   integer := 1;
  l_src_offset    integer := 1;
  l_bfile_csid    number  := 0;
  l_lang_context  integer := 0;
  l_warning       integer := 0;
  begin
    dbms_lob.open(b);
    dbms_lob.createtemporary(c,true);
    dbms_lob.loadclobfromfile (
    dest_lob      => c,
    src_bfile     => b,
    amount        => dbms_lob.getlength(b),
    dest_offset   => l_dest_offset,
    src_offset    => l_src_offset,
    bfile_csid    => l_bfile_csid ,
    lang_context  => l_lang_context,
    warning       => l_warning);
    insert into Line_GEOJSON values (c);
    commit;
    dbms_lob.fileclose(b);
    dbms_lob.freetemporary(c);
  end;
  /

Next I can create table Line1 based on the JSON file data structure:

Create table Line1 as
select j.*
    from    Line_geojson,
            json_table(CLOB_JSON, '$.features[*]'  
                columns (
                    type    varchar2(128) path '$.type',                   
                    geometry SDO_GEOMETRY PATH '$.geometry',
                    YR NUMBER path '$.properties.YR',
                    LOSS NUMBER path '$.properties.LOSS',
                    L_Key NUMBER path '$.properties.KEY'
            )) j;

And check the result:

Finally create the spatial index:

Step 3: Before creating a spatial index, we must insert a row of spatial metadata.

INSERT INTO USER_SDO_GEOM_METADATA VALUES (
  'Line1',  -- table name
  'GEOMETRY',    -- geometry column name
  SDO_DIM_ARRAY(
    SDO_DIM_ELEMENT('X', -180, 180, 0.005),
    SDO_DIM_ELEMENT('Y', -90, 90, 0.005)),
   4326           -- indicates longitude/latitude coordinates (
coordinate system)
 );

Step 4: Create a spatial Index for performance

CREATE INDEX Line1_SIDX ON
      Line1 (
          GEOMETRY
      )
          INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2;

 

Lets check the length of each tornado path using the SDO_GEOM.SDO_LENGTH function:

 select
    L_Key,
    YR,
    SDO_GEOM.SDO_LENGTH(geometry,0.005, 'unit=KM') Length
from Line1;