Showing posts with label sql. Show all posts
Showing posts with label sql. Show all posts

Wednesday, September 25, 2019

Creating a training set table for machine learning in Oracle Database

When building a machine learning model, you will require a learning / training set of data. To enable you to quickly create a set of training data you can make use of the SQL SAMPLE clause in a select statement. Using the SAMPLE clause you instruct the database to select from a random sample of data from the table, rather than from the entire table. This provides a very simple way of getting the random collection of records you require for training your model.

Situation
You do have a large (or small) table of data in your database, in our case we use an Oracle Autonomous Data Warehouse and intend to use a part of this as training data while you want to use the remaining part for testing your model.


Assume we have a table named louwersj.loans which we want to use for both our training data as well as our test data. A simple way of splitting it in a 70/30 fashion is to use the below commands:

Step 1:
Check the total number of records in the table:

SELECT
    COUNT(1)
FROM
    louwersj.loans;

In our case this will give us the result of 614 as we have 614 records in our dataset

Step 2:
Take a 70% of the total and use this to create a table, this is where we will use the sample clause in the SQL statement to ensure we get a random 70% of the records. By issuing the below command the table loans_traindata will be exactly the same as the original table loans with only a random subset of the original table.

CREATE TABLE louwersj.loans_traindata
    AS
        SELECT
            *
        FROM
            louwersj.loans SAMPLE ( 70 ) SEED ( 1 )


To validate if this gives us what we wanted we can do another count to see if we indeed get a training set which contains 70% of the original table, the below command will return 455.

SELECT
    COUNT(1)
FROM
    louwersj.loans_traindata

Step 3:
Next to the train data we need to have some test data to validate the working of our machine learning model after we have trained it. For this we can use the remaining 30% of the data from the original table. With the following command we create a new table which will contain exactly that:

CREATE TABLE louwersj.loans_testdata
    AS
        SELECT
            *
        FROM
            louwersj.loans
        MINUS
        SELECT
            *
        FROM
            louwersj.loans_traindata

Conclusion
Using the SAMPLE clause as part of a CREATE TABLE AS statement in the Oracle Database helps you to speed up creating a good training set and test for your machine learning model. No needing to extract data from the database and re-insert the data, you can do all within the database without any actual moving of the data. 

Monday, September 21, 2015

Oracle Enterprise Manager query table space sizes

Oracle Enterprise Manager provides you the ideal solution to manage a large number of targets. All information about the targets, for example Oracle databases, is stored in the Oracle Enterprise Manager Repository database. What makes it interesting is that you can query the database with SQL and get information out of it quickly, showing you exactly what you need.

In the below example we do query the total size of the Oracle database tablesize per database. The query provides a list of all databases that are registered as a target in OEM in combination with the name of the server it is running on and the total size of the table space.

SELECT
      HOST_NAME,
      TARGET_NAME,
      round(SUM(TABLESPACE_SIZE)/1024/1024,0) AS "DB_TABLESPACE_USED"
FROM 
    MGMT$DB_TABLESPACES
GROUP BY
        target_name,
        host_name
ORDER BY 
        host_name, 
        target_name

The code is also available on github where you can find a larger collection of scripts. This scripting repository will be updated continuously so everyone is able to make use of the scripts.

Saturday, July 26, 2014

Query Big Data with SQL

Data management used to be “easy” within enterprises, in most common cases data lived was stored in files on a file system or it was stored in a relational database. With some small exceptions this was where you where able to find data. With the explosion of data we see today and with the innovation around the question how to handle the data explosion we see a lot more options coming into play. The rise of NoSQL databases and the rise of HDFS based Hadoop solutions places data in a lot more places then only the two mentioned.
Having the option to store data where it is most likely adding the most value to the company is from an architectural point of view a great addition. By having the option for example to not choice for a relational database however store data in a NoSQL database or HDFS file system is giving architects a lot more flexibility when creating an enterprise wide strategy. However, it is also causing a new problem, when you try to combine data this might become much harder. When you store all your data in a relations database you can easily query all the data with a single SQL statement. When parts of your data reside in a relational database, parts in a NoSQL database and parts in a HDFS cluster the answer to this question might become a bit harder and a lot of additional coding might be required to get a single overview.
Oracle announced “Oracle Big Data SQL” which is an “addition” to the SQL language which enables you to query data not only in the Oracle Database however also query, in the same select statement, data that resides in other places. Other places being Hadoop HDFS clusters and NoSQL databases. By extending the data dictionary of the Oracle database and allowing it to store information of data that is stored in NoSQL or Hadoop HDFS clusters Oracle can now make use of those sources in combination with the data stored in the database itself.

The Oracle Big Data SQL way of working will allow you to create single queries in your familiar SQL language however execute them on other platforms. The Oracle Big Data SQL implementation will take care of the translation to other languages while developers can stick to SQL as they are used to.


Oracle Big Data SQL is available with Oracle Database 12C in combination with theOracle Exadata Engineered system and the Oracle Big Data appliance engineered system. The use of Oracle Engineered systems make sense as you are able to use infiniband connections between the two systems to eliminate the network bottleneck. Also the entire design of pushing parts of a query to another system is in line with how Exadata works. In the Exadata machine the workload (or number crunching) is done for a large part not on the compute nodes but rather on the storage nodes. This ensures that more CPU cycles are available for other tasks and sorting, filtering and other things are done where they are supposed to be done, on the storage layer.

A similar strategy is what you see in the implementation of Oracle Big Data SQL. When a query (or part of a query) is pushed to the Oracle Big Data Appliance only the answer is send back and not a full set of data. This means that (again) the CPU’s of the database instance are not loaded with tasks that can be done somewhere else (on the Big Data Appliance).
The option to use Oracle Big Data SQL has a number of advantages to our customers, both on a technical as well as architectural and integration level. We can now lower the load on database instance CPU’s and are not forced to manual create connections between relations databases and NoSQL and Hadoop HDFS solutions. While on the other hand helps customers get rapid return on investment. Some Capgemini statements can be found on the Oracle website in a post by Peter Jeffcock and Brad Tewksbury from Oracle after the Oracle Key partner briefing on Oracle Big Data SQL.

Monday, November 25, 2013

MYSQL using numbers in VARCHAR fields

Recently someone asked me to help out with some coding parts for a startup they where beginning. Some of the things they needed help with where infrastructure related and some where more in data management and some query modeling and optimization on an already existing datamodel done in a MySQL database.

This gave me some options to start exploring again some things in MySQL which is not my standard database to develop in and use as I am more focusing on Oracle databases. Part of the fun was trying to find out why some queries where not working as expected, main reason for this was that the person who originally designed the datamodel had a love for the VARCHAR datatype.

In the database we do have a table named ovsocial_inst which holds an ID column named inst_m_id. For some reason the original datamodel developer created the column as a VARCHAR even though it is only holding numbers. Now some funny effects do happen when you try to sort.

When you execute the following query:

SELECT 
      inst_m_id
FROM 
    ovsocial_inst
ORDER BY 
        inst_m_id

you will get a result something like:

inst_m_id
1
10
2
3
4
5
6
7
8
9
This is somehow a little strange as long as you do not realize that the values of inst_m_id are treated as text. When you consider it to be text everything makes sense and the query is doing exactly what you ask it to do. However, we do not want it to behave in this manner, we do want it to treat the numbers as numbers even though they are stored in a VARCHAR column. To do so in a sort we can use the following query which converts the VARCHAR into an unsigned.

SELECT 
      inst_m_id
FROM 
    ovsocial_inst
ORDER BY
        convert(inst_m_id,unsigned) ASC

Now you will get a result as you expect;

inst_m_id
1
2
3
4
5
6
7
8
9
10

Now imagine another scenario. we know that the table ovsocial_inst will be relative small so to assign a new ID to a record we would like to query the table for the max inst_m_id + 1 and we would like to use that value to insert a new record. When you do not consider the fact that the values are written to the table in a VARCHAR manner this process will work until you have 10 records in your table. Reason for this is that if you have 9 records in your table the highest value (the latest in the sort) is 9. This means that the new ID is 10 (9+1). When we hit 10 records something strange will happen. when we hit 10 records the highest value or at least the latest in the sort will be 9. This results in a new ID of 9+1 instead of 10+1.

When your ID field inst_m_id would have been a proper column for holding numbers you would use a query like the one below;

SELECT 
      (max(inst_m_id)+1) as new_id
FROM 
    ovsocial_inst

however, the above will give the issue as soon as you hit more then 10 records. To prevent this you will need to construct your query like the one below;

SELECT 
      max(convert(inst_m_id,unsigned))+1 as new_id
FROM 
    ovsocial_inst

In this way you will ensure that it keeps working even if you hit the 10 marker.

Wednesday, February 27, 2013

Oracle SQL in Eclipse

The Eclipse project started as a project for developing a development platform for Java code. Even though it is still focused arround Java a lot of additions have been build around Eclipse. Eclipse is as the project like to explain; "a community for individuals and organizations who wish to collaborate on commercially-friendly open source software. Its projects are focused on building an open development platform comprised of extensible frameworks, tools and runtimes for building, deploying and managing software across the lifecycle. "

You can find plugins for large number of languages and for a large number of development frameworks that can be enabled within Eclipse. One of the companies investing in the development of Eclipse plugins is Oracle and as Oracle is a database company they also made sure some code was donated to make Eclipse a SQL development environment. This however is somewhat unknown as Oracle mostly promotes the Oracle SQL Developer solution. However, when you only need to work on SQL code occasionally and do most of your development work in Eclipse this can be very handy. Or,... if you just like Eclipse more then you like Oracle SQL Developer.

To start using the Oracle database plugin for Eclipse you will to undertake the following steps.

Step 1:
Start Eclipse and go to "Windows" - "Open Perspective" - "Other"




Step 2:
Selecting the option from step 1 will provide you with the screen as show below. Here you can select the perspective for database development.



Step 3:
The action performed in step 2 will open a new side menu on the left side of Eclipse and will show as the "Data Source Explorer".  At the Database connections menu right-click and select New.



Step 4:
Eclipse is providing a lot of database connection types. If you have installed the Eclipse Oracle additions you will also have the option for an Oracle database. Out of the box a lot of other database connection types are also provide as you can see in the below screenshot.



Step 5:
When you have selected the Oracle database option you will be provided with the below menu where you will have to enter de connection details for this specific database connection.


When you have successfully completed the actions in step 5 and have clicked finish you should now have a working connection and the options to start developing PL/SQL code and start executing commands against your Oracle database. Below is a screenshot showing your Eclipse Oracle SQL worksheet.

Tuesday, January 15, 2013

Oracle Database login audit

In some cases you are required as an Oracle database administrator to provide audit information on the usage of your database. This can include providing information on who logged on to the database both successful and unsuccessful. Also in some cases you might be required to help users to find out why they are unable to connect to your database. In those cases it is good to know that Oracle is creating an audit trail for all login attempts both successful and unsuccessful. You can query this audit trail via DBA_AUDIT_SESSION.

when you query DBA_AUDIT_SESSION you will note that you can view all moments a session is doing a LOGON or LOGOFF action. This can be seen in the action_name column. In most cases you are not that interested however in all connections that where successful, commonly the unsuccessful attempts are much more of interest to you.

Every unsuccessful attempt has a return code which is not equal to 0. the return code 0 is a successful attempt to create a connection. If you wan to query all unsuccessful ones the query below might be of interest to you. This is also providing you a not more information then only the returncode, it is telling you the meaning of the code. Next to this it is showing you the username used, the username of the person who is attempting to connect on his local workstation, the name of the local workstation used to try and establish a connection and a timestamp (of the database server)

SELECT 
      username, 
      os_username, 
      userhost, 
      extended_timestamp,
      decode( returncode
            , 00911, 'Invalid Character'
            , 00988, 'Missing or invalid password(s).'
            , 01004, 'Logon denied.'
            , 01005, 'Null Password'
            , 01017, 'Invalid username/password.'
            , 01031, 'No Privilege'
            , 01045, 'User string lacks CREATE SESSION privilege; logon denied.'
            , 01918, 'No Such UserID'
            , 01920, 'No Such Role'
            , 09911, 'Incorrect user password.'
            , 28000, 'The account is locked.'
            , 28001, 'Your password has expired.'
            , 28002, 'Your account will expire soon; change your password now.'
            , 28003, 'The password is not complex enough.'
            , 28007, 'Password cannot be reused.'
            , 28008, 'Invalid old password.'
            , 28009, 'Connection to sys should be as sysdba or sysoper.'
            , 28011, 'Your account will expire soon; change your password now.'
            , 28221, 'The original password was not supplied.') as returncode
FROM 
    SYS.DBA_AUDIT_SESSION 
WHERE 
     returncode != 0 
ORDER BY 
        extended_timestamp desc

Friday, January 11, 2013

Oracle SQL EAN-13 check digit

When working with products in your company it is of importance that in your database you have the ability to uniquely identify a product by a product ID. A lot of companies do maintain a product ID specially used within that company. The products ID's are used in warehousing, sales, purchasing and finance. Meaning, the ID is used for a wide range of actions in your systems and  business processes. What you see is that a lot of companies do maintain their own product ID however link them to the standard product numbering system EAN. Reason for this is that EAN numbers are used across companies to identify a product uniquely.

An EAN-13 barcode (originally European Article Number, but now renamed International Article Number even though the abbreviation EAN has been retained) is a 13 digit (12 data and 1 check) barcoding standard which is a superset of the original 12-digit Universal Product Code (UPC) system developed in the United States. The EAN-13 barcode is defined by the standards organization GS1.

The EAN-13 barcodes are used worldwide for marking products often sold at retail point of sale. The numbers encoded in EAN-13 bar codes are product identification numbers, which are also called Japanese Article Number (JAN) in Japan. All the numbers encoded in UPC and EAN barcodes are known as Global Trade Item Numbers (GTIN), and they can be encoded in other GS1 barcodes.

The less commonly used EAN-8 barcodes are used also for marking retail goods; however, they are usually reserved for smaller items, for example confectionery.

2-digit (EAN 2) and 5-digit (EAN 5) supplemental barcodes may be added for a total of 14 or 17 data digits. These are generally used for periodicals (to indicate the current year's issue number), or books and weighed products like food (to indicate the manufacturer suggested retail price or MSRP), respectively.

Making sure that the EAN number you entered is a correct EAN number is vital to ensure that your database will only hold valid EAN numbers and no mistakes are made during the process of entering the number. The EAN numbering holds a mechanism to check if the number is valid. A EAN-13 number consists out of 12 data and 1 check digits. You can use the check digit to verify that the number entered is a valid EAN-13 number by using the check-digit algorithm.

To do the check you have to do a "matrix" calculation on the data digits from the EAN-13 number which are the first 12 digits. In this example we take the EAN-13 number for a MacBook Air which is 0885909592449.

Every position in the EAN-13 number has a weight associated with it, either a 1 or a 3. You will have to multiply every value of the position with the weight of the position and sum all the results up to one value.


In our case this is the final value 111. Take the nearest (upper) multiple of 10 that is equal or higher than the sum, the sum is in our case 111, meaning the nearest (upper) multiple of 10 is 120. Substract the sum from the nearest (upper) multiple of 10 and this should be equal to your check digit which in our case is 9. 120 - 111 = 9. This means your EAN-13 number you have entered is a valid EAN-13 number.

Now that we understand this logic there might be the need to incorporate this into your database so you can use it as a check. Thanks to Asif Momen and the discussion on forums.oracle.com you can use the function below to do so:

CREATE OR REPLACE
  FUNCTION ean_13(
      P_Str IN VARCHAR2)
    RETURN VARCHAR2
  IS
    l_Sum      NUMBER;
    l_Multiple NUMBER;
  BEGIN
    FOR I IN 1..12
    LOOP
      IF mod(i,2)   = 0 THEN
        l_Multiple := 3;
      ELSE
        l_Multiple := 1;
      END IF;
      l_Sum := NVL(l_Sum, 0) + SUBSTR(P_Str, i, 1) * l_Multiple;
    END LOOP;
    IF 10 - Mod(l_Sum, 10) = SUBSTR(P_Str, 13) THEN
      RETURN('TRUE');
    ELSE
      RETURN('FALSE');
    END IF;
  END;

Wednesday, January 09, 2013

Oracle SQL automatic ID generation

When developing an application at one point you most likely will come to the subject of providing ID's. When you store a record in the database you most likely will like to have an ID for this record so you can uniquely identify it and make relations to records in other tables based upon this ID.

When creating the design for your application and associated database model you can select 2 locations to generate the ID used for a specific record. One option is to have your application query the next number in a sequence in the database and use this the second is to have the database populate this when you enter the record. Depending on some criteria you can select both options however I am personally in factor of having your database handle this. As in most cases an ID is directly influencing your data model integrity I do favour having this done here however in some cases there is a good reason to deviate from this.

Considering that you will use the database to populate your ID's for you, a coupe of things are needed: first we need the table where we will store the data, secondly we need a sequence to give you the next number and we need a trigger on the database table. The trigger will be used to query the next number from the sequence and use this number during the insert in the table. When you are using Oracle SQL Developer you can use the "Column Sequences" option to have this all done for you. When using this option a trigger and a sequence will be created and associated with the column you want to populate with a ID. This is shown in the example below:

Looking at the code generated you will notice that a trigger and a sequence are generated. In the case of the example above we have a new trigger named AUTO_ID_EXAMPLE_0_TRG
 and a sequence named AUTO_ID_EXAMPLE_0_SEQ

Code for the trigger:
create or replace
TRIGGER AUTO_ID_EXAMPLE_0_TRG BEFORE INSERT ON AUTO_ID_EXAMPLE_0 
FOR EACH ROW 
BEGIN
  BEGIN
    IF :NEW.EXAMPLE_ID IS NULL THEN
      SELECT AUTO_ID_EXAMPLE_0_SEQ.NEXTVAL INTO :NEW.EXAMPLE_ID FROM DUAL;
    END IF;
  END COLUMN_SEQUENCES;
END;

Code for the sequence:
CREATE SEQUENCE "LOUWERSJ"."AUTO_ID_EXAMPLE_0_SEQ" 
MINVALUE 1 MAXVALUE 9999999999999999999999999999 
INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ;

Now we can test to see if there is indeed an automatic ID generated when we insert records into the table. We insert the following records as a test, do note we only insert data in the example_text column and not in the example_id column.
insert into auto_id_example_0 (example_text) VALUES ('TEST1');
insert into auto_id_example_0 (example_text) VALUES ('TEST2');
insert into auto_id_example_0 (example_text) VALUES ('TEST3');

When we query the table we do get the following result:
SELECT * FROM auto_id_example_0;

EXAMPLE_ID           EXAMPLE_TEXT       
-------------------- --------------------
1                    TEST1                
2                    TEST2                
3                    TEST3    

having a meaningless number as an ID can be very good and is commonly used as a database internal reference however when we are building an application where the number is used as a reference towards humans commonly the number is more meaningful and/or it is changed to be more human friendly. For example, if you check order numbers or ticket numbers it is commonly seen that you have some padding on the left side. Meaning, you will not see the number 1024 for example, you will see more likely on your order the number 00001024 or even more meaning where you have for example ORD_UTR_00001024 where for example ORD is showing we are talking about an order and UTR is showing that the order is generated in a shop with the code UTR.. An automatically generated ID can be anything and is not limited to a number, you can code all meaning you like in the trigger.

As an example for the 00001024 example we could construct the following trigger instead;
create or replace
TRIGGER AUTO_ID_EXAMPLE_0_TRG BEFORE INSERT ON AUTO_ID_EXAMPLE_0 
FOR EACH ROW 
BEGIN
  BEGIN
    IF :NEW.EXAMPLE_ID IS NULL THEN
      SELECT LPAD(AUTO_ID_EXAMPLE_0_SEQ.NEXTVAL,8,0) INTO :NEW.EXAMPLE_ID FROM DUAL;
    END IF;
  END COLUMN_SEQUENCES;
END;

Within the trigger we do use the LPAD function from Oracle SQL to left-pad the number generated by the sequence with a 0 until we reach a length of 8 characters. If we now insert a new record the next example_id will be something like 00000004 (or 00001024).

Now we have the situation where we would like to give some more meaning to the number and we would like to have something like ORD_UTR_00001024. In the below example we have added some additions to the trigger. A subquery is introduced to query the UTR part and we have added ORD_ in front. In the below example the subquery is not making any sense because it will always return UTR however you can introduce your own business logic to it.
create or replace
TRIGGER AUTO_ID_EXAMPLE_0_TRG BEFORE INSERT ON AUTO_ID_EXAMPLE_0 
FOR EACH ROW 
BEGIN
  BEGIN
    IF :NEW.EXAMPLE_ID IS NULL THEN
      SELECT 'ORD_'
            ||
            (SELECT LOCATION_CODE FROM AUTO_ID_LOCATION WHERE LOCATION_CODE = 'UTR')
            ||'_'
            || lpad(AUTO_ID_EXAMPLE_0_SEQ.NEXTVAL,8,0)
      INTO :NEW.EXAMPLE_ID 
      FROM dual;
    END IF;
  END COLUMN_SEQUENCES;
END;

By using a more sophisticated trigger you can ensure that your automatically generated number by the sequence is more meaningful then only a number. As you will notice when developing applications it is quite a common request from business owners that ID's like order numbers or ticket numbers are not simply numbers however have some more meaning. When looking for a way to build this you can opt to build this into you application side however as you can see there are a lot of options in the database and to my personal believe this is the place where this should be done by default with the exception if there is a very good reason not to do this.

Thursday, January 03, 2013

Oracle SQL check constrain

When developing an application developers do check if the input provided by the user is valid and can be stored in a database. This is a good practice as you want to make sure the data that is entering your database is consistent and correct. Data consistency can make or brake your application and having inconsistent data in your dataset will come back at you at some point in time. Also checking if only valid data is entered in your database is part of a deep application boundary validation security approach which I discussed in a previous post where the insert statement in your database is the last part of a chain of security checks.

In large projects you commonly have application developers and you will have developers architects who will be responsible for the datamodel. You can leave the validation that the correct data is entered in your database with the application developers however it is good practice to also have a check on your database level. Making sure such a check is in place is the responsibility of a data-model architect. For this we can make use of Oracle database check constrains. A check constrain will check at the moment the insert is done into a table if the data in the insert statement is in line with the check.

It might look a little overdone to have a dual check, one in the application and one in the database however it can ensure that all applications are entering consistent data and ensure that a application developer is bound to follow the rules set by the data-model architect. Secondly it will help when you will have multiple applications all entering data into a single database to ensure they all play by the same rules.

As an example we have a table for international sourcing of products which we call INT_PROD_SOURCE.  For this we have stated that the source_country code always need to be in uppercase characters. The application is in principle responsible of ensuring this however we also have enabled a check on database level. As you can see we have a constraint on source_country and we do a check on the same.

CREATE TABLE INT_PROD_SOURCE
(
  prod_id numeric(10),
  sup_id numeric(10),
  source_country varchar2(4),
  CONSTRAINT source_country
  CHECK (source_country = upper(source_country))
);


The constrain and check can be defined at creation time of the table. There are a lot of things you can enter in such a check for example you can use a IN check as shown below this ensures that only records can be entered that will have a source_country code that is NL, DE or BE;

CHECK (source_country IN ('NL', 'DE', 'BE'));

One things is not permited, which is a shame, and that is a sub-query. This is really a shame however with some good programming you can find your way around this.

Monday, November 26, 2012

Exponential function in SQL

In mathematics, the exponential function is the function ex, where e is the number (approximately 2.718281828) such that the function ex is its own derivative. The exponential function is used to model a relationship in which a constant change in the independent variable gives the same proportional change (i.e. percentage increase or decrease) in the dependent variable. The function is often written as exp(x), especially when it is impractical to write the independent variable as a superscript. The exponential function is widely used in physics, chemistry and mathematics.

When working with mathematical equations in Oracle you will come into contact with this exponential function at one point in time. Using it is quite simple, you can use it by calling the exp function in a way shown below;

SELECT 
      exp(1) AS exp_result 
FROM dual;


EXP_RESULT
----------
2.71828182845904523536028747135266249776 

The above example also shows the precision of exp as it is implemented in the Oracle database.


Sunday, November 25, 2012

Rounding numbers in Oracle SQL

When working with numbers in an Oracle database you will have to round the numbers at some point in time. When you are creating SQL code it is good to know that you have primarily 3 options for rounding numbers in Oracle SQL. The 3 main options you have at your use are round, floor and ceil. All have there own use and should be used in the correct way in your code.

The ceil option wil give you the smallest integer greater or equal to the given number. Meaning; the ceil option will round the number upwards to a whole number. for example 1.4 will become 2 however 1.5 or 1.6 will also become 2.

select ceil(1.4) from dual;

CEIL(1.4)
---------
        2 


select ceil(1.5) from dual;

CEIL(1.5)
---------
        2 


The floor option will do exactly the opposite and will round down in the same way as ceil is doing downwards. Below you can see a rounding example using floor.

select floor(1.4) from dual;

FLOOR(1.4)
----------
         1 


select floor(1.5) from dual;

FLOOR(1.5)
----------
         1 


Both floor and ceil are very convenient options when you have to round a number to a integer however in many cases rounding to an integer is not what you would like. For "true" rounding you can make use of the SQL round function in an Oracle database.

When no additional information is given the round function will round a number to a integer like result. For example if we round 1.4432123421 it provide a return set of 1.

select round(1.4432123421) from dual;

ROUND(1.4432123421)
-------------------
                  1 

However, giving some options will make sense in most cases, below are some examples of rounding;

select round(1.4432123421,1) from dual;

ROUND(1.4432123421,1)
---------------------
                  1.4 


select round(1.4432123421,2) from dual;

ROUND(1.4432123421,2)
---------------------
                 1.44


select round(1.4432123421,3) from dual;


ROUND(1.4432123421,3)
---------------------
                1.443 

Friday, November 23, 2012

Oracle generate XML from SQL

XML is used in numerous applications and application designs because of all the good and all the bad reasons. If you are using XML correctly or incorrectly in your application design is out of scope of this blogpost. Whatever the reason, in some cases you need to generate a XML file from the result set of your database SQL query. There are several ways of doing this and most of them involve some custom coding. The Oracle database is however also equipped with a simple solution to return your result set in a XML format. If you are in need to have it returned in a XML format you can make use of the  DBMS_XMLGEN.GETXML options that the database provides you.

When you use DBMS_XMLGEN.GETXML in the most basic way your XML will be returned as a CLOB object. As a example we have a simple query on a table named testtable as shown below

SELECT 
      tst.name,
      tst.location 
FROM 
    testtable tst
WHERE 
    tst.location NOT LIKE ('Amsterdam')

This provides the result as shown below as can be expected from a simple SQL select statement:

NAME                 LOCATION                                         
-------------------- --------------------------------------------------
Johan                Utrecht                                            
Krista               Utrecht                                            
Johan                De Meern                                           
Martin               De Meern 


However what we wanted to do is to have the resultset returned as CLOB object which holds a XML structure with the return set. To be able to do so we have to make use of DBMS_XMLGEN.GETXML. This is done in the below example. Do make note of the escape character for '. If you do not use it in this case you will run into an error.

SELECT DBMS_XMLGEN.GETXML
('
  SELECT 
        tst.name,
        tst.location 
  FROM 
      testtable tst
  WHERE 
      tst.location NOT LIKE (''Amsterdam'')
  ')
FROM 
    dual;


This query will return you a CLOB object which holds the following XML structure:

<?xml version="1.0"?>
<ROWSET>
<ROW>
<NAME>Johan</NAME>
<LOCATION>Utrecht</LOCATION>
</ROW>
<ROW>
<NAME>Krista</NAME>
<LOCATION>Utrecht</LOCATION>
</ROW>
<ROW>
<NAME>Johan</NAME>
<LOCATION>De Meern</LOCATION>
</ROW>
<ROW>
<NAME>Martin</NAME>
<LOCATION>De Meern</LOCATION>
</ROW>
</ROWSET>

This is the most simple and most easy way to do this. You can however make it more usable and more designed for your application and use the CLOB object somewhere else in your code or store it in a table... this however is the first step in building XML directly in your database.

Wednesday, November 14, 2012

MONTHS_BETWEEN function SQL

Companies like to work with schedules, think for example about equipment that needs to be checked every month. When you have a database where you track the dates when the equipment was checked you could write a query to figure out if a equipment part is due to be checked again or is overdue. When writing such a query you could use simple date calculations and trick some things to see the difference between one date and another date (for example sysdate) however there is a much more easy way to do this in an Oracle database using Oracle SQL when you make use of the MONTHS_BETWEEN function which is available.

The MONTHS_BETWEEN function shows the returns the number of months between one date and another date. For example if we have a table called service_log and we store the date of a service in the column service_date we could do something like the query below;

  SELECT
        MONTHS_BETWEEN(sysdate, service_date) as difference
  FROM 
      service_log

This will show the months between the current date (sysdate) and the last service date as shown below;

  DIFFERENCE
  ----------
  4.05244063620071684587813620071684587814 
  3 
  2.05244063620071684587813620071684587814 
  1.98792450716845878136200716845878136201 
  0.9556664426523297491039426523297491039427

When combining this with a round function you will be able to quickly build a report to show you if a equipment part is serviced on a monthly basis or not. An example using the round function is shown below;

  SELECT
        ROUND(MONTHS_BETWEEN(sysdate, service_date),2) as difference
  FROM 
      service_log

Sunday, November 11, 2012

Inverse trigonometric functions in SQL

Databases are primarily used to store and retrieve data by applications and occasionally by users who directly query the database. When actions, outside the domain of storing and retrieving data are needed a lot of people, who do lack SQL development knowledge will go to the application layer of a stack to build in calculation and logic functions. In some cases this makes sense however in some other cased it would make sense to build some of the logic and some of the calculations into the database side of the application stack.

To be able to make full use of the application side of the stack it is needed to understand what is available to a developer from within the Oracle database by default. For example it is not known to all Oracle SQL (PL/SQL) developers that all mathematical inverse trigonometric functions are directly available for use within the SQL language.

In mathematics, the inverse trigonometric functions (occasionally called cyclometric functions) are the inverse functions of the trigonometric functions with suitably restricted domains.

The notations sin−1, cos−1, tan−1, etc. are often used for arcsin, arccos, arctan, etc., but this convention logically conflicts with the common semantics for expressions like sin2(x), which refer to numeric power rather than function composition, and therefore may result in confusion between multiplicative inverse and compositional inverse.

In computer programming languages the functions arcsin, arccos, arctan, are usually called asin, acos, atan. Many programming languages also provide the two-argument atan2 function, which computes the arctangent of y / x given y and x, but with a range of (−Ï€, Ï€].

Within the Oracle database we have the functions ACOS, ASIN, ATAN and ATAN2 available as in many other programming languages. All are very straight forward in use. Below you can find the examples:

ACOS
As an example for the Oracle SQL ACOS function you can execute the below;
  
  SELECT 
        acos(.3) 
  FROM 
      dual;

This will give you the following result;
  1.2661036727794991112593187304122222822

Which is quite a precise number and might not be needed in all cases so you can apply a round to if for example from 3 which can be done by executing it in the following manner;
  
  SELECT 
        round(acos(.3),4) 
  FROM 
      dual;

This will provide you with the following outcome (rounding can be done to any number you like simply by using the ROUND function in combination with the ACOS function;
  1.2661

ASIN
As  an example to use the Oracle SQL ASIN function you can execute the below;
  
  SELECT 
        asin(.3) 
  FROM 
      dual;

This will give you the following result;
  0.3046926540153975079720029612275291599

ATAN
As an example to use the Oracle SQL ATAN function you can execute the below;
   
  SELECT 
        atan(.3) 
  FROM 
      dual;

This will give you the following result;
  0.2914567944778670919956046214328911935013

ATAN2
As an example to use the Oracle SQL ATAN2 function you can execute the below;
  
  SELECT 
        atan2(.4,.5) 
  FROM 
      dual;

This will give you the following result;
  0.674740942223552663056520973609813615077

All above mentioned functions are by default precise to 30 decimal digits (unless you use the ROUND function as showed in the ACOS example).

Saturday, November 10, 2012

Oracle absolute value function

Anyone who will be doing more than only simple select statements in the database and will start working on equations in the database will come along some mathematical functions every now and then. The need for a function to retrieve the absolute value of a number is more then just making sure it is a positive number.

In mathematics, the absolute value (or modulus) | a | of a real number a is the non-negative value of a without regard to its sign. Namely, | a | = a for a positive a, | a | = −a for a negative a, and | 0 | = 0. For example, the absolute value of 3 is 3, and the absolute value of −3 is also 3. The absolute value of a number may be thought of as its distance from zero.

Generalizations of the absolute value for real numbers occur in a wide variety of mathematical settings. For example an absolute value is also defined for the complex numbers, the quaternions, ordered rings, fields and vector spaces. The absolute value is closely related to the notions of magnitude, distance, and norm in various mathematical and physical contexts.

When you want to have the absolute value from a number (or any other type that can be converted to a numeric type) you can use the abs SQL function in the Oracle database.

for example;

SELECT ABS(-20) "absovalue" FROM DUAL;

 absovalue
----------
        20

Oracle SQL current_timestamp function

In many (database) applications it is important to keep some sort of logging on all kinds of actions taken. For example when was a record created or when was a record changed. When we are talking about a system which mainly interact with human users this can in most cases be done by stating a date and time which is precise up to the second. However in some cases, in many cases systems where you see a lot of machine to machine communication this is not accurate enough.

In a lot of cases where Oracle SQL developers implement a timestamp option in the application they make use of the systdate function from within the Oracle database which returns the current time and date based upon the operating system clock of the operating system the Oracle database is running on.

There is however a more precise way of getting the exact date and time which is using the current_timestamp function from the datbase.

You can extend the current_timestamp with a precision parameter. If you do not provide a precision parameter the default will be 6.

For example if you do;

select
  current_timestamp(1)
from
    dual;

you wil get
10-NOV-12 02.20.30.600000000 PM US/PACIFIC

and if you do;

select
  current_timestamp(3)
from
    dual;

you wil get
10-NOV-12 02.20.30.615000000 PM US/PACIFIC

As you can see the provided precision in influencing the the number of milliseconds that is used in your timestamp. Depending on the nature of your application and the accuracy that is needed for the timestamping this can be very important and worth looking into.

Sunday, May 27, 2012

Finding objects in Oracle via user_objects

When working with Oracle databases in within a large company with multiple customers (departments or external customers) you will also be faced with the situation that not all databases are alike. Some databases will have a strict datamodel and a strict documentation policy. From those databases you will know exactly what is in the datamodel and you will be able to find all documentation of it. This is normally the case with all production databases and the associated D(evelopment), T(est) and A(cceptance) environments. However when it comes to the "play" environments and the environments used for research and development you are not always that lucky. Specially when you are looking into a database which is used by multiple developers to work on small coding projects and using it to learn new tricks of the trade.

In those cases it is not uncommon that you have to reverse engineer some parts of the code and from time to time find lost objects. Someone stating something like "yes I have stored that in a table a year ago and called in something like HELP" is not uncommon. In those cases you will have to start looking for the object and to do so your best friend is the USER_OBJECT table in the Oracle database.

The USER_OBJECT table holds information on all the objects available tot the users. This will help you finding the table you are looking for. Some people like to directly use CAT and do something like;

SELECT
      *
FROM
    CAT
WHERE
     TABLE_NAME LIKE 'HELP'
This however will only give you the table name (HELP) and the table_type (TABLE). Secondly you will have limited options to search. You can imagine that the person stating that the table name was HELP might have some mistaken as it is more than a year ago he created it. It might very well be that the table name is USERHELP and it might also very well be that a lot of objects have the "HELP" in their name. I do personally think that using USER_OBJECTS gives you just that extra power above CAT to find the correct object quickly.

Below you see a describe of the USER_OBJECTS table:
Name           Null Type          
-------------- ---- ------------- 
OBJECT_NAME         VARCHAR2(128) 
SUBOBJECT_NAME      VARCHAR2(30)  
OBJECT_ID           NUMBER        
DATA_OBJECT_ID      NUMBER        
OBJECT_TYPE         VARCHAR2(19)  
CREATED             DATE          
LAST_DDL_TIME       DATE          
TIMESTAMP           VARCHAR2(19)  
STATUS              VARCHAR2(7)   
TEMPORARY           VARCHAR2(1)   
GENERATED           VARCHAR2(1)   
SECONDARY           VARCHAR2(1)   
NAMESPACE           NUMBER        
EDITION_NAME        VARCHAR2(30)  
it might be wise to give the USER_OBJECTS table a good look and play arround with it some more to understand it correctly. For example it will be able to show you all the objects and it is not limited to tables only for example.
you can find out what kind of objects are used within the database by executing the below query. This will give you a list of used user_objects.

SELECT 
      DISTINCT(object_type)
FROM 
    user_objects 
ORDER BY 
        object_type
back to question of the "HELP" table. You know for example that you are looking for a table so you can filter on object_type to only show you the table objects. Secondly you know that it most likely has "HELP" in the name so you can filter for all objects having "HELP" as part of the object_name and secondly you know it is created 11 or more months ago so you can use this as a filer on the created date field. As you can see, it gives you just a little more options then using the CAT option in your Oracle database.

Thursday, December 29, 2011

Oracle eBS change username

Amar Padhi is running a showing a nice explanation on how to change the username of a user in Oracle eBS. I encountered this option due to the fact that I was looking into some requests from a customer which involves the mass change of a userbase in Oracle eBS. This particular customer is in need to change a large set of its usernames to be able to be compliant with internal rules and regulations concerning usernames.

The initial idea was to create new accounts and end-date the old accounts in Oracle eBS. However, it turns out that you can rename them by making use of the change_user_name function which can be found in the fnd_user_pkg package in the database.

The example Amar is using on his weblog is the example below:
begin
  fnd_user_pkg.change_user_name(
                               x_old_user_name => 'AMARKP', 
                               x_new_user_name => 'AMAR.PADHI'
                              );

  commit;
end;
/
Without much effort you could create a script to mass update all the users that are in need of an update. You do most likely would like to add some reporting, logging and notification to this script to make it robust however the use of fnd_user_pkg.change_user_name will play a central role.

Thursday, September 09, 2010

Oracle EBS mass create users

When using Oracle e-Business suite in a production environment you most likely will have besides a production instance some other instances. For example you might have an instance for developers and a Oracle eBS instance for your support organization. In most cases developers and possibly people from the support organization do not have an account on eBS.

In those cases you would like to have those accounts generated every time a instance is refreshed from a production instance. You can decide to have your developers do this manually as they most likely will have a high level of database access however it is more convenient to incorporate the generation of accounts into your cloning scripting.

The below script can be used to do this. It can also be used to generate for example user accounts on a production environment in case you need to do a mass creation of users. It is however advisable to change the script a bit if you intend to use it for this purpose. For cloning it is very useful.


/*********************************************************************************/
/*    after_clone_user_create_ebs.sql                                            */
/*                                                                               */
/*    PL/SQL script to create mass users for Oracle EBS non production instances */
/*    after a refresh from production. Developers and such can be added by this  */
/*    script.This code is tested on Oracle EBS 11.5.10.2 systems                 */
/*                                                                               */
/*    Copyright (C) 2010  Johan Louwers                                          */
/*                                                                               */
/*    This program is free software: you can redistribute it and/or modify       */
/*    it under the terms of the GNU General Public License as published by       */
/*    the Free Software Foundation, either version 3 of the License              */
/*                                                                               */
/*    This program is distributed in the hope that it will be useful,            */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of             */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              */
/*    GNU General Public License for more details.                               */
/*                                                                               */
/*    You should have received a copy of the GNU General Public License          */
/*    along with this program.  If not, see http://www.gnu.org/licenses.         */
/*                                                                               */
/*    CONTRIBUTIONS                                                              */
/*    JLO          Johan.Louwers{at}capgemini.com                                */
/*                                                                               */
/*                                                                               */
/*    VERISON    DATE         DEVELOPER   DESC                                   */
/*    1.0        28-AUG-2010  JLO         Initial creation                       */
/*    1.1        29-AUG-2010  JLO         Added logging to the output.           */
/*                                                                               */
/*                                                                               */
/*********************************************************************************/

Set serveroutput ON;

DECLARE
/*--------------------------------------------*/
/* declare all the variables used in the      */
/* script.                                    */
/*                                            */
/*                                            */
/*--------------------------------------------*/
createdUser varchar2(200);
TYPE t_users IS VARRAY(60) OF VARCHAR2(20);
TYPE t_resp IS VARRAY(60) OF VARCHAR2(50);   


/*--------------------------------------------*/
/* State the usernames which have to be       */
/* created by the program. If the name is     */
/* already in the system it will not be       */
/* created again.                             */
/*--------------------------------------------*/
t_list_users t_users := t_users('SOMEUSERNAME'
,'ANOTHERUSERNAME'
,'SOMEUSER'
);


/*--------------------------------------------*/
/* list the resps that will be added to each  */
/* new user. The values are based upon the    */
/* value of RESPONSIBILITY_KEY as stated in   */
/* FND_RESPONSIBILITY. If the KEY is not      */
/* valid a error will be thrown               */
/*--------------------------------------------*/                                      
t_list_resp t_resp := t_resp('SYSTEM_ADMINISTRATOR'
,'APPLICATION_DEVELOPER'
);    


/*--------------------------------------------*/
/* cursor c_user_exists will be used to check */
/* if the user is already in the system. This */
/* is to prevent a error from happening by    */
/* entering a user for the second time which  */
/* is not allowed by fnd_user_pkg.CreateUser  */
/*--------------------------------------------*/ 
CURSOR c_user_exists (p_username IN VARCHAR2) IS
SELECT 
COUNT (us.user_name) AS usercounter
FROM 
apps.fnd_user us
WHERE 
us.user_name = (p_username);
r_user_exists c_user_exists%rowtype; 


/*--------------------------------------------*/
/* cursor c_resp_details will be query all    */ 
/* details for a resp needed when adding it to*/
/* a new user.                                */
/*                                            */  
/*--------------------------------------------*/
CURSOR c_resp_details (p_respkey IN VARCHAR2) IS
SELECT   
fav.application_short_name
,fav.application_name
,frv.responsibility_key
,frv.responsibility_name
FROM 
fnd_application_vl fav
,fnd_responsibility_vl frv
WHERE 
frv.application_id = fav.application_id
AND frv.responsibility_key = (p_respkey);
r_resp_details c_resp_details%rowtype; 




BEGIN
FOR i IN t_list_users.FIRST .. t_list_users.LAST
LOOP

DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('+ Checking for user '||t_list_users(i));

/*--------------------------------------------*/
/* Check if the user is already in the system */ 
/* if this is the case we will not create we  */
/* will only print a warning to the screen    */
/*                                            */  
/*--------------------------------------------*/
open c_user_exists(t_list_users(i));
fetch c_user_exists into r_user_exists;

IF r_user_exists.usercounter > 0
THEN
DBMS_OUTPUT.PUT_LINE(' - User '||t_list_users(i)||' was found, we will not create it. ');

/*--------------------------------------------*/
/* If the user in not the system we will have */ 
/* to create the user and print this to the   */
/* output. Creation will be done by using the */
/* standard fnd_user_pkg.CreateUser option    */  
/*--------------------------------------------*/
ELSE
DBMS_OUTPUT.PUT_LINE(' - User '||t_list_users(i)||' was NOT found, we will create it again');

createdUser := t_list_users(i);

fnd_user_pkg.CreateUser(x_user_name            => t_list_users(i)
,x_owner                => 'CUST'
,x_unencrypted_password => 'welcome'
,x_description => 'External Consultant'
);

/*--------------------------------------------*/
/* For all new users we will add all the resps*/ 
/* which have been stated in t_list_resp. To  */
/* be able to get all the details needed by   */
/* fnd_user_pkg.AddResp we will query it via  */
/* cursor c_resp_details.                     */
/*--------------------------------------------*/       
FOR i IN t_list_resp.FIRST .. t_list_resp.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(' - Adding to user '||createdUser||' the resp '||t_list_resp(i)||'.');
open c_resp_details(t_list_resp(i));
fetch c_resp_details into r_resp_details;

fnd_user_pkg.AddResp(username       => createdUser
,resp_app       => r_resp_details.application_short_name
,resp_key       => t_list_resp(i)
,security_group => 'STANDARD'
,description    => r_resp_details.responsibility_name
,start_date     => SYSDATE
,end_date       => NULL
);
close c_resp_details;
END LOOP;
END IF;
close c_user_exists;     


END LOOP;  

END;

COMMIT;

Saturday, May 01, 2010

Oracle SQL prevent unique constrain violated error

When creating a database model in your Oracle database (or any other database) you will have to creation relations. When you do things correct (in my opinion) you will base those relations on primary and foreign keys and by using those building unique constraints. Or simply put, binding tables on values. If you want to build a one to many relation you will have to make sure that you hold a column with a unique value, this will be your primary key which can not be null. Making sure that the value in this column is unique is done by the Oracle database, if you try to insert a value which is not unique the database will throw a unique constrain violated error. So you will need to provide some mechanism to ensure you only insert unique values.

So, the database will prevent you from inserting a non unique value and will throw a error message, to prevent your code from entering a couple of options possible. For example one can query the highest value + 1. The downside from this is that you need to query the table before you can do a insert which results in computation which is not needed and which can be intense on large tables. a better way is to make use of a database sequence which will provide you the next value. When using a sequence you can do the insert in a couple of ways.

You can get the next value from the sequence like:
SELECT 
sequencename.nextval 
FROM 
dual;

you could use this as a sub-query in your insert statement or get it in your pl/sql code as a variable and use this variable in your insert statement. All options are valid and can be used in your code however an other option is available which I prefer. This option has to be considered the moment you create the table and will make use of a trigger and sequence. The trigger will fire when you insert a record into the table without the unique value. The unique value will be requested by the trigger and inserted into the table.

Before creating the table you will have to define a sequence. In the example below we first create a sequence named johan.WEBLOG_EXAMPLE_0_SEQ

CREATE SEQUENCE "JOHAN"."WEBLOG_EXAMPLE_0_SEQ"
MINVALUE 1 
MAXVALUE 9999999999999999999999999999 
INCREMENT BY 1 
START WITH 1 
CACHE 20 
NOORDER 
NOCYCLE ;
This sequence will provide us a unique number every time we do a request for a nextval like we did in the first example and in the example below where it is done manual:
SELECT 
johan.WEBLOG_EXAMPLE_0_SEQ.nextval 
FROM 
dual;
Now we have created a sequence we will create the table in which we will place a trigger which uses the sequence johan.WEBLOG_EXAMPLE_0_SEQ. We name the table WEBLOG_EXAMPLE_0
CREATE TABLE "JOHAN"."WEBLOG_EXAMPLE_0"
(
"ID_COLUMN"     NUMBER NOT NULL ENABLE,
"DATA_COLUMN_0" VARCHAR2(120 BYTE),
"DATA_COLUMN_1" VARCHAR2(120 BYTE),
CONSTRAINT "WEBLOG_EXAMPLE_0_PK" PRIMARY KEY ("ID_COLUMN") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" ENABLE
)
SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE
(
INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "USERS" ;
CREATE OR REPLACE TRIGGER "JOHAN"."WEBLOG_EXAMPLE_0_TRG" BEFORE
INSERT ON JOHAN.WEBLOG_EXAMPLE_0 FOR EACH ROW BEGIN <<COLUMN_SEQUENCES>> BEGIN IF :NEW.ID_COLUMN IS NULL THEN
SELECT WEBLOG_EXAMPLE_0_SEQ.NEXTVAL INTO :NEW.ID_COLUMN FROM DUAL;
END IF;
END COLUMN_SEQUENCES;
END;
/
ALTER TRIGGER "JOHAN"."WEBLOG_EXAMPLE_0_TRG" ENABLE;
In the example above you can see that we create the table and also create a before trigger named WEBLOG_EXAMPLE_0_TRG. This will make sure that before the record is inserted it will be checked if a value for the unique column "ID_COLUMN" is given. If this value is NULL it will request a nextval from the sequence and place this in the "ID_COLUMN". after this is done the record is inserted. This is one the most secure ways of making sure you will try to insert a unique value in your "ID_COLUMN". In the example below we will see this:
INSERT INTO JOHAN.WEBLOG_EXAMPLE_0 
(DATA_COLUMN_0, 
DATA_COLUMN_1) 
VALUES ('blabla', 
'more blabla');
when we do a select on the table we will notice that the trigger is working and that the "ID_COLUMN" column now has a value of 1, the following will get a value of 2 etc etc etc.