Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java / JavaSE / J2EE

Working with a large number of columns in Oracle Database

4.60/5 (3 votes)
18 Apr 2012CPOL3 min read 22.4K   224  
In this article I want to give a solution to work with an Oracle database has a large number of Columns

Introduction  

Today the database is an important factor of an application. The Database becomes more complicated day after day.  In this article I want to give a solution to work with an Oracle database has a large number of Columns.

As Oracle Limitation Documentation, we will remember in oracle database, a table will have no more than 1000 columns.

Our solution is using a real example in our current project, It will store Iso8583 format to Oracle Database. Someone work in Financial Field will know Iso8583 format and purpose of it. But only see Iso8583 format as an array of 128 String Array value, and we will store 128 value of iso fields into a table contains 128 columns

Design and Implementation

Database design 

First of all, we will create an Oracle database has this type

<code><code>

SQL
create or replace
type ISOMESSAGE_ARRAY 
as table of varchar2(1000);

Because Oracle can only support table contains no more 1000 columns so we only create an array type of 1000 varchar2 elements

The second thing we will create a TBLISO contain 128 columns to store ISO8583 data. By running this code

SQL
CREATE TABLE "TBLISO" 
   (    "MSGIN_ID" NUMBER(10,0), 
    "MSGHEADER" VARCHAR2(100 BYTE), 
    "BITMAP" VARCHAR2(32 BYTE), 
    "F2_PAN" VARCHAR2(19 BYTE), 
    "F3_PROCESSING_CODE" VARCHAR2(6 BYTE), 
    "F4_AMOUNT_TRANS" VARCHAR2(12 BYTE), 
    "F5_AMOUNT_SETT" VARCHAR2(12 BYTE), 
    "F6_AMOUNT_CARDHOLDER_BILL" VARCHAR2(12 BYTE), 
    "F7_TRANSMISSION_DATETIME" VARCHAR2(10 BYTE), 
    "F8_AMOUNT_CARDHOLDER_BILL_FEE" VARCHAR2(8 BYTE), 
    "F9_CONVERSION_RATE_SETT" VARCHAR2(8 BYTE), 
    "F10_CONVERSION_RATE_CARDBILL" VARCHAR2(8 BYTE), 
    "F11_SYSTEM_TRACE" VARCHAR2(6 BYTE), 
    "F12_LOCAL_TIME" VARCHAR2(6 BYTE), 
    "F13_LOCAL_DATE" VARCHAR2(4 BYTE), 
    "F14_DATE_EXPIRATION" VARCHAR2(4 BYTE), 
    "F15_DATE_SETT" VARCHAR2(4 BYTE), 
    "F16_DATE_CONVERSION" VARCHAR2(4 BYTE), 
    "F17_DATE_CAPTURE" VARCHAR2(4 BYTE), 
    "F18_MERCHANT_TYPE" VARCHAR2(4 BYTE), 
    "F19_ACQ_INST_COUNTRY_CODE" VARCHAR2(3 BYTE), 
    "F20_PRIMARY_ACC_NUM_EXT" VARCHAR2(3 BYTE), 
    "F21_FORWD_INST_COUNTRY_CODE" VARCHAR2(3 BYTE), 
    "F22_POS_ENTRY_MODE" VARCHAR2(3 BYTE), 
    "F23_CARD_SEQ_NUM" VARCHAR2(3 BYTE), 
    "F24_NETW_INTER_IDENTIFY" VARCHAR2(3 BYTE), 
    "F25_POS_CONDITION_CODE" VARCHAR2(2 BYTE), 
    "F26_POS_PIN_CAPTURE_CODE" VARCHAR2(2 BYTE), 
    "F27_AUTHO_IDEN_RESP_LENGTH" VARCHAR2(1 BYTE), 
    "F28_AMOUNT_TRANS_FEE" VARCHAR2(9 BYTE), 
    "F29_AMOUNT_SETT_FEE" VARCHAR2(9 BYTE), 
    "F30_AMOUNT_TRANS_PROCESS_FEE" VARCHAR2(9 BYTE), 
    "F31_AMOUNT_SETT_PROCESS_FEE" VARCHAR2(9 BYTE), 
    "F32_ACQ_INST_IDEN_CODE" VARCHAR2(11 BYTE), 
    "F33_FORW_INST_IDEN_CODE" VARCHAR2(11 BYTE), 
    "F34_PAN_EXTEND" VARCHAR2(28 BYTE), 
    "F35_TRACK2" VARCHAR2(37 BYTE), 
    "F36_TRACK3" VARCHAR2(104 BYTE), 
    "F37_RETRIEVAL_REF_NUM" VARCHAR2(12 BYTE), 
    "F38_AUTHO_IDEN_RESP" VARCHAR2(20 BYTE), 
    "F39_RESP_CODE" VARCHAR2(2 BYTE), 
    "F40_SERV_RESTRICT_CODE" VARCHAR2(3 BYTE), 
    "F41_CARD_ACCEPT_TERM_IDEN" VARCHAR2(20 BYTE), 
    "F42_CARD_ACCEPT_IDEN_CODE" VARCHAR2(15 BYTE), 
    "F43_CARD_ACCCEPT_NAME" VARCHAR2(40 BYTE), 
    "F44_ADD_RESP_DATA" VARCHAR2(25 BYTE), 
    "F45_TRACK1" VARCHAR2(79 BYTE), 
    "F46_ADD_DATA_ISO" VARCHAR2(999 BYTE), 
    "F47_ADD_DATA_NATIONAL" VARCHAR2(999 BYTE), 
    "F48_ADD_DATA_PRIVATE" VARCHAR2(999 BYTE), 
    "F49_CURRENCY_CODE_TRANS" VARCHAR2(3 BYTE), 
    "F50_CURRENCY_CODE_SETT" VARCHAR2(3 BYTE), 
    "F51_CURRENCY_CODE_CARDHOLD" VARCHAR2(3 BYTE), 
    "F52_PIN_DATA" VARCHAR2(16 BYTE), 
    "F53_SECUR_RELATE_CONTROL_INFO" VARCHAR2(16 BYTE), 
    "F54_ADD_AMOUNT" VARCHAR2(120 BYTE), 
    "F55_ICC_SYS_RELATE_DATA" VARCHAR2(255 BYTE), 
    "F56_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F57_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F58_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F59_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F60_ADVICE_REASON_CODE" VARCHAR2(60 BYTE), 
    "F61_POS_DATA" VARCHAR2(26 BYTE), 
    "F62_INF_DATA" VARCHAR2(50 BYTE), 
    "F63_NETWORK_DATA" VARCHAR2(44 BYTE), 
    "F64_MAC" VARCHAR2(16 BYTE), 
    "F65_BITMAP_EXTEND" VARCHAR2(16 BYTE), 
    "F66_SETT_CODE" VARCHAR2(1 BYTE), 
    "F67_EXTEND_PAYMENT_CODE" VARCHAR2(2 BYTE), 
    "F68_RECEIV_INST_COUNTRY_CODE" VARCHAR2(3 BYTE), 
    "F69_SETT_INST_COUNTRY_CODE" VARCHAR2(3 BYTE), 
    "F70_NETW_MANG_INFO_CODE" VARCHAR2(3 BYTE), 
    "F71_MESSAGE_NUM" VARCHAR2(4 BYTE), 
    "F72_MESSAGE_NUM_LAST" VARCHAR2(4 BYTE), 
    "F73_DATE_ACTION" VARCHAR2(6 BYTE), 
    "F74_CREDIT_NUM" VARCHAR2(10 BYTE), 
    "F75_CREDIT_REVRS_NUM" VARCHAR2(10 BYTE), 
    "F76_DEBIT_NUM" VARCHAR2(10 BYTE), 
    "F77_DEBIT_REVRS_NUM" VARCHAR2(10 BYTE), 
    "F78_TRANSFER_NUM" VARCHAR2(10 BYTE), 
    "F79_TRANSFER_REVRS_NUM" VARCHAR2(10 BYTE), 
    "F80_INQUIRIES_NUM" VARCHAR2(10 BYTE), 
    "F81_AUTHO_NUM" VARCHAR2(10 BYTE), 
    "F82_CREDIT_PROCESS_FEE_AMOUNT" VARCHAR2(12 BYTE), 
    "F83_CREDIT_TRANS_FEE_AMOUNT" VARCHAR2(12 BYTE), 
    "F84_DEBIT_PROCESS_FEE_AMOUNT" VARCHAR2(12 BYTE), 
    "F85_DEBIT_TRANS_FEE_AMOUNT" VARCHAR2(12 BYTE), 
    "F86_CREDIT_AMOUNT" VARCHAR2(16 BYTE), 
    "F87_CREDIT_REVRS_AMOUNT" VARCHAR2(16 BYTE), 
    "F88_DEBIT_AMOUNT" VARCHAR2(16 BYTE), 
    "F89_DEBIT_REVRS_AMOUNT" VARCHAR2(16 BYTE), 
    "F90_ORIGI_DATA_ELEMNT" VARCHAR2(42 BYTE), 
    "F91_FILE_UPDATE_CODE" VARCHAR2(1 BYTE), 
    "F92_FILE_SECUR_CODE" VARCHAR2(2 BYTE), 
    "F93_RESP_INDICATOR" VARCHAR2(5 BYTE), 
    "F94_SERVICE_INDICATOR" VARCHAR2(7 BYTE), 
    "F95_REPLACEMENT_AMOUNT" VARCHAR2(42 BYTE), 
    "F96_MESAGE_SECUR_CODE" VARCHAR2(16 BYTE), 
    "F97_AMOUNT_NET_SETT" VARCHAR2(17 BYTE), 
    "F98_PAYEE" VARCHAR2(25 BYTE), 
    "F99_SETT_INST_IDEN_CODE" VARCHAR2(11 BYTE), 
    "F100_RECEIVE_INST_IDEN_CODE" VARCHAR2(11 BYTE), 
    "F101_FILE_NAME" VARCHAR2(17 BYTE), 
    "F102_ACCOUNT_IDEN_1" VARCHAR2(28 BYTE), 
    "F103_ACCOUNT_IDEN_2" VARCHAR2(28 BYTE), 
    "F104_TRANS_DESCP" VARCHAR2(100 BYTE), 
    "F105_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F106_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F107_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F108_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F109_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F110_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F111_RESERVED_ISO" VARCHAR2(999 BYTE), 
    "F112_PARCELAS_DATA" VARCHAR2(248 BYTE), 
    "F113_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F114_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F115_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F116_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F117_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F118_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F119_RESERVED_NATIONAL" VARCHAR2(999 BYTE), 
    "F120_RECORD_DATA" VARCHAR2(999 BYTE), 
    "F121_AUTHO_AGENT_IDEN_CODE" VARCHAR2(11 BYTE), 
    "F122_ADD_RECORD_DATA" VARCHAR2(100 BYTE), 
    "F123_RESERVED_FUTURE" VARCHAR2(999 BYTE), 
    "F124_RESERVED_FUTURE" VARCHAR2(999 BYTE), 
    "F125_RESERVED_FUTURE" VARCHAR2(999 BYTE), 
    "F126_RESERVED_PRIVATE" VARCHAR2(999 BYTE), 
    "F127_PRIVATE_DATA" VARCHAR2(50 BYTE), 
    "F128_MAC" VARCHAR2(16 BYTE)
   ) 

 We added MSGIN_ID column as primary key of table, will use a sequence to generate primary key each time new iso8583 data need to be inserted

Don’t forget to create a sequence for generating primary key 

SQL
CREATE SEQUENCE  "SEQ_ISO"  MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 101 CACHE 100 NOORDER  NOCYCLE ;

And the last thing we need is an store procedure to insert data to table. There are some ways to create this store procedure. The normal way we will create a store procedure has 128 input parameter and use it in insert statement. But this way will take a lot of time of developer to compose and debug if having errors. So I will use the simpler way to pass parameters to the store-procedure: A Array input parameter solution

Let is run this code to create package header in Oracle DB 

SQL
create or replace
package isopkg as 
  procedure insert_iso(in_isomsg IN isomessage_array);
end isopkg; 

<code>

Let is run this code to create package body in Oracle DB 

SQL
create or replace
package body isopkg as
  procedure insert_iso(in_isomsg IN isomessage_array) AS
  new_id_in_msg number(10,0);
  begin
       select seq_iso.nextval into new_id_in_msg from dual;
        INSERT INTO "TBLiso"
        VALUES
        (
        new_id_in_msg,
        '0000', --as Header
        in_isomsg(2),--Bitmap
        in_isomsg(3),--PAN
        in_isomsg(4),
        in_isomsg(5),
        in_isomsg(6),
        in_isomsg(7),
        in_isomsg(8),
        in_isomsg(9),
        in_isomsg(10),
        in_isomsg(11),
        in_isomsg(12),
        in_isomsg(13),
        in_isomsg(14),
        in_isomsg(15),
        in_isomsg(16),
        in_isomsg(17),
        in_isomsg(18),
        in_isomsg(19),
        in_isomsg(20),
        in_isomsg(21),
        in_isomsg(22),
        in_isomsg(23),
        in_isomsg(24),
        in_isomsg(25),
        in_isomsg(26),
        in_isomsg(27),
        in_isomsg(28),
        in_isomsg(29),
        in_isomsg(30),
        in_isomsg(31),
        in_isomsg(32),
        in_isomsg(33),
        in_isomsg(34),
        in_isomsg(35),
        in_isomsg(36),
        in_isomsg(37),
        in_isomsg(38),
        in_isomsg(39),
        in_isomsg(40),
        in_isomsg(41),
        in_isomsg(42),
        in_isomsg(43),
        in_isomsg(44),
        in_isomsg(45),
        in_isomsg(46),
        in_isomsg(47),
        in_isomsg(48),
        in_isomsg(49),
        in_isomsg(50),
        in_isomsg(51),
        in_isomsg(52),
        in_isomsg(53),
        in_isomsg(54),
        in_isomsg(55),
        in_isomsg(56),
        in_isomsg(57),
        in_isomsg(58),
        in_isomsg(59),
        in_isomsg(60),
        in_isomsg(61),
        in_isomsg(62),
        in_isomsg(63),
        in_isomsg(64),
        in_isomsg(65),
        in_isomsg(66),
        in_isomsg(67),
        in_isomsg(68),
        in_isomsg(69),
        in_isomsg(70),
        in_isomsg(71),
        in_isomsg(72),
        in_isomsg(73),
        in_isomsg(74),
        in_isomsg(75),
        in_isomsg(76),
        in_isomsg(77),
        in_isomsg(78),
        in_isomsg(79),
        in_isomsg(80),
        in_isomsg(81),
        in_isomsg(82),
        in_isomsg(83),
        in_isomsg(84),
        in_isomsg(85),
        in_isomsg(86),
        in_isomsg(87),
        in_isomsg(88),
        in_isomsg(89),
        in_isomsg(90),
        in_isomsg(91),
        in_isomsg(92),
        in_isomsg(93),
        in_isomsg(94),
        in_isomsg(95),
        in_isomsg(96),
        in_isomsg(97),
        in_isomsg(98),
        in_isomsg(99),
        in_isomsg(100),
        in_isomsg(101),
        in_isomsg(102),
        in_isomsg(103),
        in_isomsg(104),
        in_isomsg(105),
        in_isomsg(106),
        in_isomsg(107),
        in_isomsg(108),
        in_isomsg(109),
        in_isomsg(110),
        in_isomsg(111),
        in_isomsg(112),
        in_isomsg(113),
        in_isomsg(114),
        in_isomsg(115),
        in_isomsg(116),
        in_isomsg(117),
        in_isomsg(118),
        in_isomsg(119),
        in_isomsg(120),
        in_isomsg(121),
        in_isomsg(122),
        in_isomsg(123),
        in_isomsg(124),
        in_isomsg(125),
        in_isomsg(126),
        in_isomsg(127),
        in_isomsg(128),
        in_isomsg(129)
        );  
        
  end insert_iso;  

end isopkg;

Implementation

Above, we are create the database with large number columns in table TBLISO. This session we will create a Java Application to work this database

We will use Oracle Thin Driver to work with Oracle Database. Sample application will contain in this session or you can download it above.

We will have 2 configuration file located in cfg folder

Dbcdg.txt: contains database connection information

jdbc:oracle:thin:@[iphost]:[port]:[sid]
user
pass 

And iso8583data.txt store Iso 8583 data. Its structure will be shown as below

0: 420
1: F2B900018E80C4000000000004000000
2: 9876543210123456
3: 351000
4: 000000000000
7: 0418055231
9: 20000000
11: 300422
12: 130527
13: 0418
16: 0418
32: 998866
33: 704001
37: 000000224003
38: 012345
39: 05
41: 00001100        
49: 704
50: 840
54: 0000000000000000000000000000000000000000
102: 00000000000000000000

As I refer above, Iso8583 format has 128 data fields. Each row will set one value for a field. Above “: “ string is field index and behind it is Iso Field value. You can add/remove field from this file but always refer to ISO Format document to ensure Data is good to store to correspondence column in table

Refer http://en.wikipedia.org/wiki/ISO_8583 to make good data range for Iso Fields

Now we start “coding”. 

Using the code 

Create class FileReader in Java

Java
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package iso8583db;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author minhdbh
 */
public class FileReader {

    private String filePath;
    private String[] lineData;

    public FileReader() {
        filePath = "";
        lineData = new String[0];
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
        loadData();

    }

    public String[] getLineData() {
        return lineData;
    }
    
    /**
     * I find the samples code to read text file on the internet :)
     * 
     */
    private void loadData() {
        try {
            FileInputStream fstream = new FileInputStream(filePath);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            lineData=new String[getLines(new File(filePath))];
            int iLine=0;
            String iData="";
            while ((iData = br.readLine()) != null) {
                System.out.println(String.format("Line %s: %s", iLine,iData));
                lineData[iLine]= iData;
                iLine++;
            }
            in.close();
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }
    
    /**
     * Use only when file is iso8583data, it will return an array of 128 elements correspondence with Iso format
     * @return 
     */
    public String[] toIsoArray() {
        String[] isoValueArray = new String[129];
        for (int i = 0; i < 129; i++) {
            isoValueArray[i] = "";
        }
        if (lineData.length>0)
        {
            for(int iField=0;iField<lineData.length;iField++)
            {
                String isoField[]=lineData[iField].split(": ");
                isoValueArray[Integer.parseInt(isoField[0])]=isoField[1];
            }
        }
        return isoValueArray;
    }

    /**
     * Get total lines in a text file
     * This function I find on internet
     * @param aFile: pointer to text file
     * @return 
     */
    private int getLines(File aFile)  { 
        LineNumberReader reader = null;
        try {
            reader = new LineNumberReader(new java.io.FileReader(aFile));
            while ((reader.readLine()) != null);
            return reader.getLineNumber();
        } catch (Exception ex) {
            return -1;
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException ex) {
                    Logger.getLogger(FileReader.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}

Create class dbLib  

SQL
<span style="line-height: 115%; font-family: "Calibri","sans-serif"; font-size: 11pt;"></span>/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package iso8583db;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

/**
 *
 * @author minhdbh
 */
public class dbLib {
    public static boolean insertIsoMsg(Connection cnn, String[] datainput) 
    {
        CallableStatement proc = null;
        boolean flag = true;
        try{
            String temp = "{ call isopkg.insert_iso(?)}";
            proc = cnn.prepareCall(temp);
            ArrayDescriptor para2Des = new ArrayDescriptor("ISOMESSAGE_ARRAY", cnn);
            ARRAY para2 = new ARRAY(para2Des,cnn,datainput);
            proc.setArray(1,para2);
            proc.execute();
            System.out.println("Insert to DB successfully");
        }
        catch(Exception ex)
        {
            flag=false;
            System.out.println("Cannot insert to DB");
        }
        finally
        {
            if (proc != null){
                try {
                    proc.close();
                } catch (SQLException se) {


                }
            }
        }
        return flag;
    }    
}

And in main function we of project we will add this code

Java
public static void main(String[] args) {
        // TODO code application logic here
        FileReader dbCfg = new FileReader();
        dbCfg.setFilePath("cfg/dbcdg.txt");

        Connection conn=null;
        String driver = "oracle.jdbc.driver.OracleDriver";
        try {
            Class.forName(driver); // load Oracle driver
            conn = DriverManager.getConnection(dbCfg.getLineData()[0], dbCfg.getLineData()[1], dbCfg.getLineData()[2]);
        } catch (Exception ex) {
            Logger.getLogger(Iso8583DB.class.getName()).log(Level.SEVERE, null, ex);
        }
        while (true) {
            FileReader isoData = new FileReader();
            isoData.setFilePath("cfg/iso8583data.txt");
            
            dbLib.insertIsoMsg(conn, isoData.toIsoArray());

            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(Iso8583DB.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

I use a loop and Sleep method, when application is running we can edit data in file iso8583data to apply new change to database!


Conclusion 

This is a simple way to work with a larger number of columns in Oracle. It will make the code more brighten and easier to debug and develop. Hope it will be meaningful with you! 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)