Pages

Tuesday, June 16, 2015

How to update certain node values from set of node values in XML type table column value in sql

Hi folks,

I have recently got task to create a SQL procedure which could update 2 specific node values of an xml column value in a table. Original column has 7 to 10 node value sets depending on the user type (in my scenario, it's employee type and student type). I'm writing this article is to put all the needed steps to one place because it will make easier for someone to find it in here rather than going through number of pages and links for each and every part.

The xml column value is some what like this,

<attributes>
  <attribute>
    <code>EMPID</code>
    <type>System.Int32</type>
    <value>0477348</value>
  </attribute>
  <attribute>
    <code>EMPEID</code>
    <type>System.Int32</type>
    <value>19245866</value>
  </attribute>
  <attribute>
    <code>EMPBADGEID</code>
    <type>System.Int32</type>
    <value>15354</value>
  </attribute>
  <attribute>
    <code>EMPCF</code>
    <type>CMB</type>
    <value>1</value>
  </attribute>
  <attribute>
    <code>ENTITY</code>
    <type>CMB</type>
    <value>4</value>
  </attribute>
  <attribute>
    <code>JOBTITLE</code>
    <type>System.String</type>
    <value>Executive Director</value>
  </attribute>
  <attribute>
    <code>DEPARTMENT</code>
    <type>CMB</type>
    <value>Transportation Parking &amp; Traffic</value>
  </attribute>
  <attribute>
    <code>DEPARTMENTLOCATOIN</code>
    <type>CMB</type>
    <value>29</value>
  </attribute>
  <attribute>
    <code>MOBILENO</code>
    <type>System.String</type>
    <value>9097300644</value>
  </attribute>
</attributes>

I have to update above green colored values with the given two values according to the given userid. The approach i used is inserting the <code> value, <type> value and <value> value to a temporary table and then update the relevant columns with the given values and then replace the original table value with the updated values in the temporary table. 

First step is to insert the node values to separate columns in a temporary table and i found how to do it via web. 

DECLARE @tempTable TABLE (
id int identity(1,1) not null,
code VARCHAR(500),
type VARCHAR(500),
value VARCHAR(500))

Since the table column is xml, I had to convert it to a varchar value.

DECLARE @xml XML
SELECT @xml= CAST(userAttributes AS VARCHAR(MAX)) FROM op_tb_trn_user WHERE userid = @userid

Then insert it to a temporary table.

INSERT INTO @tempTable
SELECT  
  Tbl.Col.value('code[1]', 'varchar(500)'),  
  Tbl.Col.value('type[1]', 'varchar(500)'),  
  Tbl.Col.value('value[1]', 'varchar(500)')
FROM   @xml.nodes('attributes/attribute') Tbl(Col)

Run a select statement on your temporary table and the output will be something like this,

id code                  type         value
1 EMPID              System.Int32 0477348
2 EMPEID             System.Int32 19245866
3 EMPBADGEID         System.Int32   15354
4 EMPCF              CMB              1
5 ENTITY             CMB              4
6 JOBTITLE           System.String Executive Director
7 DEPARTMENT         CMB              Transportation Parking & Traffic
8 DEPARTMENTLOCATOIN CMB              29
9 MOBILENO           System.String 9097300644

Then you should update the relevant column with the given values.
In my scenario,

UPDATE @tempTable SET value = @newvalue1 WHERE code = 'EMPID'
UPDATE @tempTable SET value = @newvalue2 WHERE code = 'EMPEID'

According to my scenario, i have declared set of variables to hold the values in my temporary table and then create a dynamic sql command with those variables.

DECLARE @type VARCHAR(100)
DECLARE @value VARCHAR(100)
DECLARE @type1 VARCHAR(100)
DECLARE @value1 VARCHAR(100)
DECLARE @type2 VARCHAR(100)
DECLARE @value2 VARCHAR(100)........

SET @empstring = '<attributes><attribute><code>EMPID</code><type>'+@type+'</type><value>'+@value+'</value></attribute><attribute><code>EMPEID</code><type>'+@type1+'</type><value>'+@value1+'</value></attribute><attribute><code>EMPBADGEID</code><type>'+@type2+'</type><value>'+@value2+'</value></attribute><attribute><code>EMPCF</code><type>'+@type3+'</type><value>'+@value3+'</value></attribute><attribute><code>ENTITY</code><type>'+@type4+'</type><value>'+@value4+'</value></attribute><attribute><code>JOBTITLE</code><type>'+@type5+'</type><value>'+@value5+'</value></attribute><attribute><code>DEPARTMENT</code><type>'+@type6+'</type><value>'+@value6+'</value></attribute><attribute><code>DEPARTMENTLOCATOIN</code><type>'+@type7+'</type><value>'+@value7+'</value></attribute><attribute><code>MOBILENO</code><type>'+@type8+'</type><value>'+@value8+'</value></attribute></attributes>'

Then i got another problem while i'm trying to update the original table column values with xml converted value of my dynamic sql because the dynamic sql command has '&' in somewhere in it. '&' is causing problem only because it's an special character in xml. Therefore we have to treat him separately. We have to replace '&' with '&amp;' and then only we can convert this in to xml.

SELECT @initialpart = SUBSTRING(@empstring,1,CHARINDEX('&',@empstring) -1)
SET @initialpart = @initialpart+'&amp;'
SELECT @final = SUBSTRING(@empstring,CHARINDEX('&',@empstring) + 1,len(@empstring))
SET @finalempstring = @initialpart+@final


Then you can update the original value like,

UPDATE op_tb_trn_user SET userAttributes = CAST(@finalempstring AS XML) WHERE userid = @userid

You can proceed with the update statement without the '&' convention statements if there is no '&' in your dynamic command.

Happy coding... :)

Monday, May 18, 2015

How to add additional conditions within a where condition depending on the value got in a where condition

Hi folks,

                            I have recently got a task to add additional condition to a particular query. This additional condition should be validate if a particular condition got true. Let's illustrate this as below,

SELECT col1, col2, col3...
FROM table1
WHERE col3 = 'val 1' OR col3 = 'val 2'
AND ........................

Lets say we have to add and additional condition if col3 = val 1. If col3 = val 2 then we dont have to check for this additional condition (lets say for col4). 
This is how we can simply do this.

SELECT col1, col2, col3...
FROM table1
WHERE ((col3 = 'val 1' AND col4 = 'val 3') OR col3 = 'val 2')
AND ........................ 

In the above query, it will check for col4 = 'val 3' when col3 = val 1. If col3 = 'val 2' the additional check will be neglected and the rest is same.

Wednesday, July 9, 2014

ORA-01791 not a SELECTed expression

Hi fellas,

ORA-01791 not a SELECTed expression is kind of an untraceable error when i had came across in a first place. Oracle form which has a LOV (List of Values) pops up an error "ORACLE ERROR : Unable to read from List of Values" when click on the LOV button or press CTRL+L key combination. 


I haven't come across the exact reason for this but this has something to do with the database changes (Not like package changes or table structure changes but due to db version changes or rack changes) since the relevant query runs fine in all the existing 10g and 11g databases except a particular database which had a major change few dates back.


The relevant query is something like,


SELECT DISTINCT receipt_no, r_amount
FROM receipts
WHERE status = 'Y'
AND paycate_code = 'BL'
AND cust_keyvalue like DECODE(:customer_keyvalue,NULL,'%',:customer_keyvalue)
ORDER BY creation_date DESC;

Problem occurred because of the combination of the DISTINCT keyword with the ORDER BY keyword. To resolve this,


  • Remove the DISTINCT keyword if there is a trigger available in relevant to eliminate entering duplicate data in to the table.
  • Select all the columns which are using for ORDER BY clause along with the needed columns (In this scenario, you don't have to remove the DISTINCT keyword).
The query will be like,

SELECT receipt_no, r_amount
FROM receipts
WHERE status = 'Y'
AND paycate_code = 'BL'
AND cust_keyvalue like DECODE(:customer_keyvalue,NULL,'%',:customer_keyvalue)
ORDER BY creation_date DESC;

or

SELECT DISTINCT receipt_no, r_amount, creation_date
FROM receipts
WHERE status = 'Y'
AND paycate_code = 'BL'
AND cust_keyvalue like DECODE(:customer_keyvalue,NULL,'%',:customer_keyvalue)
ORDER BY creation_date DESC;

Happy coding...:)

Monday, February 17, 2014

How to handle "100501 Non-Oracle exception" in a simple way

Hi fellas,

                       I have comacross 100501 Non-Oracle exception in one of my oracle form yesterday. 100501 is the error code of FORM_TRIGGER_FAILURE. In my form, after firing some validation, this non oracle exception message poped up and then gone after click on the ok button on the message box. This message didn't do any harm my form's functionality but do kind of a harm in QC (quality controlling) phase.

                       the previous developer who modified the form i'm working now used RAISE FORM_TRIGGER_FAILURE in exception handling area. The original code is,

EXCEPTION
    WHEN OTHERS THEN
        set_application_property(CURSOR_STYLE, 'DEFAULT');
        alert_message(110,SQLERRM);
        ROLLBACK;
        RAISE FORM_TRIGGER_FAILURE;

The relevant exception in my scenario is a FORM_TRIGGER_FAILURE. Therefore the relevant error code is displaying via alert_message. In a scenario like this simply you can comment the relevant code which is responsible of displaying error messages or you could simple write a small coding part like below to handle that scenario separately.

EXCEPTION 
    WHEN FORM_TRIGGER_FAILURE THEN
        set_application_property(CURSOR_STYLE, 'DEFAULT'); 
        ROLLBACK;
        RAISE FORM_TRIGGER_FAILURE;

    WHEN OTHERS THEN 

        set_application_property(CURSOR_STYLE, 'DEFAULT'); 
        alert_message(110,SQLERRM);
        ROLLBACK;
        RAISE FORM_TRIGGER_FAILURE;

Most valuable code is,
WHEN FORM_TRIGGER_FAILURE THEN
RAISE FORM_TRIGGER_FAILURE;

Wednesday, December 4, 2013

How to validate previous record's properties when user tries to enter new record in to the same data block without entering and saving the previous record and it's properties(data for child blocks)

Hi fellas,

This is just for new guys to oracle.

                                           I got an oracle form which has 6 data blocks based on 6 separate tables and form has 3 tabs. From first data block to last block, there is a connection between the particular block and it's previous block. Its like second block has a relation with first block, third block has a relation with second block, fourth block has a relation with third block and like wise. Since all these blocks based on database tables when tab pages changes changes will be inserted into the relevant tables.
                                           
                                           The form i had has data enter process like below.

First block has the master record. This is only one record per one round.
Second block is tabular one and can have multiple records per round. Record can be a item which should have serial numbers or may be a item which shouldn't have serial numbers. Third block based on this concept.
If the second block has serialized item then the third block should have relevant serial numbers accordingly.
Since the data blocks based on tables when tab pages changed relevant input data will get inserted in to tables.
The problem i had was when user create the first record on the second block, user used serialized item and  without entering relevant serial numbers in to third block, he tries to add a second record in to the second block. I have restrict the user in this scenario and navigate him / her to enter serial numbers when tries to enter the  second record in the second block without entering serial numbers for the first record.
                                     all the input data will get inserted in to the tables when tab pages changed but wont get committed until press the save button in the end of the process. Therefore i couldn't check for the serial numbers from the database table. What i did for this situation was i maintain a variable to hold the value of :system.cursor_value. When ever user tries to create a new record in the second block ( :system.cursor_value null because user tries to create a new record. ) i navigate to the previous record, checked whether the previous record is a serialized item and if so i checked the third block's values. If the third block doesn't have any data then i just redirect the user to the third block and forced him / her to enter the serial numbers. If the previous record has the relevant serial numbers in the third block or the previous record is a non serialized item then navigate to the second block and create a new record by using create_record built in.
I just put my code here and you can get the idea by going through that. Leave the additional conditions here  which are unique to my form and it's functionality. Just concentrate on the codings in red color...


DECLARE

    
    ml_new_cursor_rec NUMBER;   
    ml_value VARCHAR2(50);
    
BEGIN
    
    ml_new_cursor_rec := :system.cursor_record;
    ml_value := :system.cursor_value;
    
    IF ml_value IS NULL THEN 
        previous_record;
    
        IF FU_SERIAL_NO_ITEM THEN
        
            IF :stl_adjust_qty != 0 AND :stl_adjust_qty IS NOT NULL AND :SVS_SERIAL_NO IS NULL THEN
                err_msg(3620,2);
            
                set_tab_page_property('ADJUSTED_DETAILS',enabled,property_true);
                set_tab_page_property('APPROVEL_INFORMATION',enabled,property_true);
            
                IF NVL(:ic_stk_take_lines.stl_adjust_qty,0) > 0 THEN 
                    :IC_STK_VARIANCE_LINES.SVL_VARIANCE_TYPE := 'R';
                ELSIF NVL(:ic_stk_take_lines.stl_adjust_qty,0) < 0 THEN
                    :IC_STK_VARIANCE_LINES.SVL_VARIANCE_TYPE := 'I';
                END IF;
            
                :ic_stk_variances.stv_date            := sysdate; 
                :ic_stk_variance_lines.svl_item_code  := :ic_stk_take_lines.stl_item_code;
                :ic_stk_variance_lines.fc_item_desc   := :ic_stk_take_lines.fc_item_desc;
                :ic_stk_variance_lines.svl_adjust_qty := NVL(:ic_stk_take_lines.stl_adjust_qty,0);
                :ic_stk_variance_lines.svl_rack_no    := :ic_stk_take_lines.stl_rack_no;
                :ic_stk_variance_lines.svl_bin_no     := :ic_stk_take_lines.stl_bin_no;
                        
                :FC_SUPPESS_VALIDATE_FLAG := 'Y';
                SELECT SYSDATE INTO :IC_STK_VARIANCES.STV_DATE FROM DUAL; 
                go_item('ic_stk_variance_serials.svs_serial_no');
                first_record;
        
                IF :ic_stk_variance_serials.svs_serial_no IS NULL THEN
     
                    LOOP
        
                        EXIT WHEN :ic_stk_variance_serials.svs_serial_no IS NULL;
            
                        DELETE FROM ic_stk_variance_serials
                        WHERE svs_voucher_no = :ic_stk_variances.stv_voucher_no
                        AND svs_item_code  = :ic_stk_take_lines.stl_item_code
                        AND svs_serial_no  = :ic_stk_variance_serials.svs_serial_no;
                 
                        EXIT WHEN :system.last_record = 'TRUE'; 
                 
                        next_record;
                 
                    END LOOP;
            
                ELSE  
                    go_block('IC_STK_TAKE_LINES');  
                    create_record;  
        
                END IF;  
        
            ELSE
                go_block('IC_STK_TAKE_LINES');  
                create_record;  
        
            END IF;
        
        ELSE
            go_block('IC_STK_TAKE_LINES');  
            create_record;
        
        END IF;
        
    END IF;
    
END;

Happy coding.....:)

Sunday, June 16, 2013

How to get a selected part of a string separate from the back end of the given string in oracle forms

Hi fellas,

Last week i got a task to write a sql statement to select a particular part of a string from given string. The part of the string i need to get separate is in the back end of the original string. Actually given string is path where valuable text document stored in the server. File name is included in this path from the back end. To process the file they need to read the full path from the database and get the file name separated from the original path string.
Actual string is like this,
                       Main_Folder\folder_1\Folder_2\textfile.txt

Every folder is separated by '\' sign and number of folders in string can be different by time to time.Apart from that, the length of the file name can be very. Therefore we cannot predict the length of the original file path and length of the file name as well.My task is to read the original string from back end and cut the string when first '\' sign meets.

To read the string from the back, I had to reverse the given string. We can use REVERSE key word for this. But normally 10g oracle forms doesn't support all the key words in sql. Therefore forms doesn't support for REVERSE as well. Forms doesn't recognize REVERSE as a key word.Therefore we have to use UTL package along with the reverse key word (only for forms).

Lets imagine the original string is like "Main_Folder\folder_1\Folder_2\Sub_folder\TextFile.txt"
First of all I had to reverse the original string and then i can read it until I can find the first '\' sign. Relevant statement is,
  SELECT UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW
  ('Main_Folder\folder_1\Folder_2\Sub_folder\TextFile.txt'))) FROM DUAL;

Output will be "txt.eliFtxeT\redlof_buS\2_redloF\1_redlof\redloF_niaM"

Then I had to read the string till I can find the position of the first '\' sign. Relevant statement is,
SELECT INSTR(UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW
  ('Main_Folder\folder_1\Folder_2\Sub_folder\TextFile.txt'))),'\')-1 FROM DUAL;

Output will be "12".


Therefore now I know that i have to substring the given string from 12th position to get only the file name separated. The relevant statement is,
SELECT SUBSTR((SELECT UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW
  ('Main_Folder\folder_1\Folder_2\Sub_folder\TextFile.txt'))) FROM DUAL,0,(SELECT INSTR(UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW
  ('Main_Folder\folder_1\Folder_2\Sub_folder\TextFile.txt'))) ,'\')-1 FROM DUAL)) FROM DUAL;

Output will be "txt.eliFtxeT".


Now I had to reverse the separated file name to get the original file name. For this process I had to use REVERSE statement again for the above mentioned output.

For the whole process, relevant statement is like below.

SELECT UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW((SELECT SUBSTR((SELECT UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW
  ('Main_Folder\folder_1\Folder_2\Sub_folder\TextFile.txt'))) FROM DUAL,0,(SELECT INSTR(UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW
  ('Main_Folder\folder_1\Folder_2\Sub_folder\TextFile.txt'))) ,'\')-1 FROM DUAL)) FROM DUAL)))) FROM DUAL;

When we use this in the form, all the SELECT key words and FROM DUAL key words should be left.

Final output of the above mentioned statement will be,
"TextFile.txt".

I used INSTR to calculate the position of the first '\' sing in the reversed string and we must reduce 1 from that position number to get only the file name.

Monday, January 14, 2013

Use SSL in ASP.NET MVC3 Applcation

Hi fellas,

                                 SSL stands for Secure Socket Layer. Normally we use SSL in our web applications. We use it to secure the message transmission on the internet. This will secure the information we transmit via the URL. Different MVC applications use different methods to apply SSL to web application. In this section you will see how to use SSL with your ASP.NET MVC web application.

First of all we have to add related programming codes to the Web.config file of our web application. You can select the form to add this and if you want you can use this for several forms in your application. Bellow is the related XML code you should use in the Web.config file,

<forms loginUrl="~/Account/LogOn" timeout="2880" requireSSL="true"/>

In above XML code requireSSL="true" is the cording part which will take care of SSL. You can add any  related URL to the loginUrl according to your requirement. In above example it's loginUrl="~/Account/LogOn". 

After define Web.config file we have to modify the properties of our application project. to do this right click on the project and select properties.



In project properties select web tab and in that web tab  the Server properties scroll down to the Servers.


In that properties select Use Local IIS Web Server radio button. After that select Use IIS Express checkbox and Overide applicationroot URL checkbox.

Then go the project properties by double clicking on the project and you will get a window like bellow.


In the properties window set SSL Enable as True. After that copy the given URL in SSL URL and paste it on project URl and field under Overide application root URL checkbox like bellow,


Paste the copied URL like bellow,

After modify the web tab in project properties save the changes and the clean the project, Rebuild and run the project. Now your URL will include the https (SSL).

Wednesday, January 9, 2013

FRM-30457: Warning: Maximum Length ignored for character-datatype subordinate mirror itme

Hi fellas,

Sometimes we used Copy Value From Item property and Synchronize With Item property in oracle forms to connect separate items in same form. 

Just imagine we have two items named ITEM1 and ITEm2 and we need to use number of properties like Data Type, Maximum Length, Required property ,  Highest Allowed Value,..etc... of ITEM1 on ITEM2. In these kind of scenario, we can use Copy Value From Item property and Synchronize With Item property to apply them. 
For apply this you have to keep both items in the same data type

FRM-30457: Warning: Maximum Length ignored for character-datatype subordinate mirror item will appear if you assign a value for Maximum Length property in child item (in this example it's ITEM2. ITEM1 is the master item.). 
If we assign a value to Copy Value From Item property to some item, we cant assign a value to the Maximum Length property of that item because it refers the master item and will take those properties from that master item. Therefore we have to keep Maximum Length property as 0 for child item.

FRM-30443: Warning: Highest Value Allowed ignored for subordinate mirror item
and
FRM-30444: Warning: Lowest Value Allowed ignored for subordinate mirror item
will be appear if you assign values for Lowest Allowed Value and Highest Allowed Value properties of the child item. You should keep those properties (Lowest Allowed Value / Highest Allowed Value) empty for child item to avoid those above warnings. 

Monday, December 17, 2012

Synonyms in PL/SQL

Hi falks,

In pl/sql synonym refers to schema objects which are created by a particular user to access an objects which  didn't belongs to him.Sometimes we have to join certain modules of a product to retrieve data for business purposes. Normally the particular user has to create the synonym for the related object according to the data requirement. The owner of the object should give grants for this user. 

Owner can create synonyms and give grants to other users who are using different schema s.

User cannot create a synonym for different schema other than his own schema from different schema other than his own schema.

Example statement of creating synonym from different schema for a certain table. Just imagine that your schema is ABC and other schema which include the table you want is DEF and table is employees. Statement is,

      CREATE OR REPLACE PUBLIC SYNONYM synemployees FOR ABC.employees;

User don't have to give any kind of grants to the synonym for his schema. It will assign all the grants automatically when synonym is creates.
But user can give grants to other users (schemas) while creating the synonym.

Thursday, December 6, 2012

Anagram words in text file and file write and replace text through java

Hi all,

Before few days I was having an assignment which need to apply Anagram to the words in a given text file through java. No way of using predefined methods or algorithms for this. Therefore I created simple java program to do this. This might also help you to understand about anagram and some techniques of applying anagram through java.

This is the source code.....

Just imagine that the existing file name is "test"

import java.io.*;
import java.util.StringTokenizer;
 

public class FileRead {

    static String sentence [];
    static String temp [];
    static int i = 0;
    static String first="";

 public static void Read() {

  try{

  // Read the existing text file

  FileInputStream fstream = new FileInputStream("test.txt");
  DataInputStream in = new DataInputStream(fstream);
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  

  String strLine;
 

  while ((strLine = br.readLine()) != null) {

     StringTokenizer stk = new StringTokenizer(strLine);
     sentence = new String[stk.countTokens()];
    temp = new String[sentence.length];
    while(stk.hasMoreTokens()) {
    sentence[i] = stk.nextToken();
    i++;

  }

  for(int x=0;x<sentence.length;x++){

if(x==0){
temp[x]= sentence[(sentence.length-1)];
}
else{
temp[x]= sentence[x-1];

}

  }
  for(int x=0;x<temp.length;x++){
     first=first+temp[x]+" ";

  }
  // Print original sentence
  System.out.println (strLine);
  System.out.println ("\n");
  System.out.println ("Apply anagram for the above sentence.");
  //Print Anagramed sentence.
  System.out.print (first+"\n");

  first="";

You can write this new phrase by using Filewritter and Bufferwritter as below mentioned. I'm using new text file to write new phrase......


// Write Anagramed sentence to new text file
File file =new File("test1.txt");
    //if file doesnt exists, then create it
    if(!file.exists()){
    file.createNewFile();
    }
    FileWriter fileWritter = new FileWriter(file.getName(),false);
    BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
    bufferWritter.write(first);


The statement "FileWriter fileWritter = new FileWriter(file.getName(),false);" includes "false" in the end of the statement. We can use true instead of using false. The different of these two is , we can write new word or phrase right after the existing word or phrase in the text file by using "true". When we use "false" it will replace the existing word or phrase by given word or phrase.