• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Using ‘New’ SQL Data Types in RPG

    March 17, 2004 Raymond Everhart

    As RPG programmers, we have become very comfortable with character, zoned, and packed decimal data types. Occasionally, when dealing with APIs or subprocedures, we’ve been forced to dabble with binary numbers or variable length strings. More recently some of us have started taking advantage of the strengths of the date, time, and timestamp data types supported in RPG IV. And just when we think we’ve got it all covered, we find out that DB2 supports even more data types.

    DB2 supports data types that are seldom used by iSeries programmers. However, since C or Java programmers may create tables (or files) on the iSeries, we need to know how to interact with these data types.

    The following tables list the data types that can be used in DB2 on the iSeries.

    Numeric Data Types Min Value Max Value Bytes of Storage Used
    Small Integer -32,768 32,767 2
    Integer -2,147,483,648 2,147,483,647 4
    Big Integer -9,223,372,036,854,775,808 9,223,372,036,854,775,807 8
    Decimal -1031 + 1 1031 – 1 Up to 16
    Numeric -1031 + 1 1031 – 1 Up to 31
    Float(Single Precision) 1.17549436 x 10-38 3.40282356 x 1038 4
    Float(Double Precision) 2.2250738585072014 × 10-308 1.7976931348623158 x 10308 8
    String Data Types Description Max Length
    Char Fixed Length Character Data 32,766
    VarChar Variable Length Character Data 32,740
    CLOB Character Large Object String 15,728,640
    Graphic Fixed Length Graphic String 16,383
    VarGraphic Variable Length Graphic String 16,370
    DBCLOB Double Byte Character Large Object String 7,864,320
    BLOB Binary Large Object String 15,728,640
    Date/Time Data Types Contents Limits Bytes of Storage Used
    Date 3 part value: Year, Month and Day

    If the date format *JUL, *MDY, *DMY, or *YMD is used, the year part of the value can only represent dates in the range 1940 through 2039. 4
    Time 3 part value: Hour, Minutes and Seconds 0 3
    TimeStamp 7 part value: Year, Month, Day; Hours, Minutes, Seconds, Microseconds

    0 10

    Now that we know just how much we don’t know, let’s look at how to define these data types in RPG and how to convert to and from these data types using SQL scalar functions.

    DEFINING SQL DATA TYPES IN RPG

    Let me start by saying that the SQL precompiler does a lot of the hard work for you. When you use embedded SQL to put data into your application, you must define “host variables” to contain the values selected in your SQL statement. When using native I/O, coding an F-spec adds the fields and their definitions into the program, during the compile process. Embedded SQL does not require an F-spec. Instead, host variables are defined in D-specs, like any other variable in RPG. Host variables can be defined as stand-alone fields, data structures, externally described data structures or multiple occurrence data structures.

    In the example below, a single host variable has been defined. When the SQL statement runs, the number of records in the QADBXREF file will be placed into the variable RecordCount. In this case, RecordCount is defined as a packed decimal value with a precision of 9,0.

    .....DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
         D RecordCount     S              9  0
    
         C/Exec SQL
         C+ Select Count(*) into :RecordCount from QADBXREF
         C/End-Exec
    

    Now let’s make a change. Notice that the RecordCount variable is now defined as a zoned decimal value with a precision of 7,0. This code will also work just fine.

    .....DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
         D RecordCount     S              7S 0
    
         C/Exec SQL
         C+ Select Count(*) into :RecordCount from QADBXREF
         C/End-Exec
    

    Now the RecordCount variable is defined as a four-byte Integer. This code will also work.

    .....DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
         D RecordCount     S              5I 0
    
         C/Exec SQL
         C+ Select Count(*) into :RecordCount from QADBXREF
         C/End-Exec
    

    The point that I am trying to make is that if the data types are not the same, the program will work to convert the value correctly, if possible. The data types do not have to be the same, but they do need to be compatible. If the value of one data type can be assigned to another without the use of a scalar function, the data types are compatible. For example, a small integer value can be assigned to a decimal variable, a character value can be assigned to a character large object, and a correctly formatted character value can be assigned to a date variable. Just like in RPG, you can add a zoned decimal to an integer and store the results in a packed decimal field. You don’t have to worry about the differences; RPG will handle all of the data type conversions necessary. So if a column in your table is defined as numeric, but you define it as an integer in RPG, the conversion will be handled automatically. The most important thing to watch for is that you keep data from being truncated as it moves from one data type to another.

    The source code listed below shows a sample RPG definition for each SQL data type. Care should be taken not to exceed the maximum length, as shown in the table above, or change the lengths of the integer or float data types. Large objects require the SQLTYPE keyword, which is processed by the SQL precompiler.

    .....DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
    
          * Numeric Definitions
         D SmallInteger    S              5I 0
         D SmallInteger    S              4B 0
         D Integer         S             10I 0 
         D Integer         S              9B 0
         D BigInteger      S             20I 0
         D Decimal         S             31P 9
         D Numeric         S             31S 9
         D Float_Single    S              4F 
         D Float_Double    S              8F
    
          * Character Definitions
         D Char            S          32766A
         D VarChar         S          32740A   Varying
    
          * Graphic Data Definitions
         D Graphic         S          16383G
         D VarGraphic      S          16370G   Varying
    
          * Large Object Definitions
         D CLOB            S                   SQLTYPE(CLOB:500)
         D DBCLOB          S                   SQLTYPE(DBCLOB:500)
         D BLOB            S                   SQLTYPE(BLOB:500)
    
          * Date/Time Definitions
         D Date            S               D
         D Time            S               T
         D TimeStamp       S               Z
    

    For performance reasons, it makes sense to avoid unnecessary data type conversions, but the system will convert compatible data types nonetheless.

    CHANGING BETWEEN DATA TYPES IN SQL

    It seems as if programmers spend a lot of their time changing data from one type to another. A value stored as a number is converted to a date, an invoice amount is converted to a character string, so it can be inserted into a body of text, and on and on. SQL has built-in functions to accomplish these tasks as well. These functions allow you to control the length, precision, and data type of your results. The rest of this article examines the use of scalar functions to convert between data types. However, another option is available within SQL. The CAST expression lets you perform the same data type conversions as individual scalar functions. Once you master the scalar functions, you can decide which you prefer.

    CONVERTING TO CHARACTER DATA

    The first method of converting data to the character data type is the CHAR() function. The results of the CHAR() function depend on the data type being converted.

    The CHAR() function will convert the following:

    Character data to character Char (character expression, length)
    Integer data to character Char (integer expression)
    Decimal data to character Char (decimal expression, decimal character)
    Float data to character Char (float expression, decimal character)
    Date/Time data to character Char (date time expression, format)

    The table below shows the resulting length of the Char() function based on the source data type.




    Source

    Source

    Data Type

    Comments

    Length of

    Result

    Character

    The result is a character string of the length specified
    in the second argument.  If the second
    argument is not specified, the resulting string is the same length as the
    source string.

     

    Small Integer

    Fixed length.

    Preceding minus sign if negative.

    Left justified.

    No leading zeros.

    Padded on the right with blanks

    6

    Integer

    11

    Big Integer

     

    20

    Decimal

    Variable Length

    Preceding minus sign if negative.

    Left justified.

    No leading zeros.

    If the value is positive, there will be one trailing
    blank.

    The decimal character can be a period or a comma and is
    specified on the second argument.

     

     

    Precision of source
    value

    + 2

    Float

    Fixed length.

    Preceding minus sign if negative.

    If the value is zero,
    the returned string is 0E0.

    The smallest number of
    digits/characters possible is

         used to
    represent the value.

    Padded on the right
    with blanks.

     

     

    24

    Date

    The format and separator are determined by the second
    argument of the function.  If no format
    is specified, the value of the DATFMT and
    DATSEP parameters is used.

     

    ISO, USA, EUR,or JIS date format

    10

    YMD, MDY, or DMY date
    format

    6

    Time

    The format and separator are determined by the second
    argument of the function.  If no format
    is specified, the value of the TIMFMT and
    TIMSEP parameters is used.
     

     

    8

    TimeStamp

    The second argument is not allowed when converting this
    data type.

    26

     

     

     

     

    The table below shows some samples of the CHAR() function.




    Source

    Source

    Data Type

    Source Data

    CHAR() statement

    Result

    Character

    Name = ‘Dr. Suess‘

    Char(Name,5)

    ‘Dr. S’

     

    Char(‘I like ‘ +
    Name,20)

    ‘I like Dr. Suessbbbb‘

    Small Integer

    Sm_Int = 45

    Char(Sm_Int)

    ’45bbbb’

    Integer

    Int = -654321

    Char(Int)

    ‘-654321bbbb’

    Big Integer

    Big_Int = 32468465654005

    Char(Big_Int-5)

    ‘32468465654000bbbbbb’

    Decimal

    Num1 = 36.68

    Char(Num1)

    ‘36.68b’

    Num2 = -1254.996

    Char(Num2,’,’)

    ‘-1254,996’

     

    Char(10000.00-99865)

    ‘135.00bbb’

    Float

    Double =
    -987.654321E-35

    Char(Double)

    ‘-9.8765432100000002E-33
    ‘

    Date

    InvDate = 2003-05-22

    Char(InvDate, USA)

    ’05/22/2003′

    Char(InvDate, YMD)

    ’03/05/22′

    Time

    ChgTime = 09.25.01

    Char(ChgTime,USA)

    ‘9:25 AMb‘

    TimeStamp

     

    Char(InvDate+ChgTime)

    ‘2003-05-22-09.25.01.000000’

     

    Another function for converting to character data is the DIGITS() function. The DIGITS() function works with integer and decimal data types only. The value returned is an absolute value that is right-justified with leading zeros and no decimal separator. This function works well when you are formatting a “flat file” for export or when you want to append a sequence number to a character value. There is no equivalent CAST expression for the DIGITS() function. The following table shows the length and sample uses of the DIGITS() function.




    Source

    Source

    Data Type

    Source Data

    DIGITS() statement

    Length

    Result

    Small Integer

    Sm_Int = 45

    Digits(Sm_Int)

    5

    ‘00045’

    Integer

    Int = -654321

    Digits(Int)

    10

    ‘0000654321’

    Big Integer

    Big_Int = 32468465654005

    Digits(Big_Int-5)

    19

    ‘0000032468465654000’

    Decimal

    Num1 = 36.68

    Digits(Num1)

    Precision

    of Source value

    ‘3668’

    Num2 = -1254.996

    Digits(Num2)

    ‘1254996’

     

    Digits(10000.00-99865)

    ‘0013500’

     

    CONVERTING TO DATE/TIME DATA TYPES

    The DATE() function returns a date from a value. The value supplied to the DATE() function can be represented in a number of ways. The value can be a timestamp, a date, a positive number, or a string. If the value supplied is a timestamp, the returned value is the date portion of the timestamp. If the supplied value is a date, then that date is returned. If the value supplied is a number, it must represent the number of days after January 1, 0001. If the value supplied is a string, it must be a valid date string or a seven-character numeric string in the form yyyynnn; where yyyy is the year and nnn is the number of days (1-366) since the beginning of the year.

    DATE() EXAMPLES




    Constants

    Constants

    Format

    Date() statement

    Result

    Chg_Date = ‘2004-11-25’

    Rec_Date = ‘2003-05-22-09.25.01.000000’

     

    Date

    Date(Chg_Date)

    2004-11-25

    TimeStamp

    Date(Rec_Date)

    2003-05-22

    Numeric

    Date(731885)

    2004-10-31

    USA

    Date(’12/05/2001′)

    2001-12-05

    ISO

    Date(‘2004-11-01’)

    2004-11-01

    EUR

    Date(‘22.09.1998’)

    1998-09-22

    yyyynnn

    Date(‘2000214’)

    2000-08-01

     

    The TIME() function returns a Time value from a value. The value supplied to the TIME() function can also be represented in a number of ways. The value can be a TimeStamp, Time, or string. If the value supplied is TimeStamp, the returned value is the time portion of TimeStamp. If the supplied value is a time, that time is returned. If the value supplied is a character string, that string must be a valid representation of a time value.

    TIME() Examples




    Constants

    Constants

    Format

    Time() statement

    Result

    Chg_Date = ‘2004-11-25’

    Chg_Time= ‘13.22.05’

    Rec_Date = ‘2003-05-22-09.25.01.000000’

     

    Time

    Time(Chg_Time)

    13.22.05

    TimeStamp

    Time(Rec_Date)

    9.25.01

    USA

    Time(’01:05 PM’)

    13.05.00

    ISO

    Time(‘18.11.59’)

    18.11.59

    EUR

    Time(‘18.11.58’)

    18.11.58

    JIS

    Time(’16:42:46′)

    16.42.46

     

    The TIMESTAMP() function returns a timestamp from a value. The TIMESTAMP function can accept one or two arguments. If only one argument is specified, it must be a timestamp or a 14-character representation of a timestamp. The format for the 14-character string is yyyyMMddhhmmss, where yyyy is for the year, MM is for the month, dd is for the day, hh is for the hour, mm is for the minute, and ss is for the number of seconds. If two arguments are specified, the first value must be a date or a character representation of a date value and the second value must be a date or a character representation of a time value.

    TIMESTAMP() Examples




    Constants

    Constants

    Format

    Date() statement

    Result

    Chg_Date = ‘2004-11-25’

    Chg_Time= ‘13.22.05’

    Rec_Date =

    ‘2003-05-22-09.25.01.000000’

    TimeStamp

    TimeStamp(Rec_Date)

    2003-05-22-09.25.01.000000

    Character

    TimeStamp(‘20040522135204’)

    2004-05-22-13.52.04.000000

     

    TimeStamp(Chg_Date,Chg_Time)

    2004-11-25-13.22.05.000000

     

    TimeStamp(’10/15/1975′,
    ’08:55:01′)

    1975-10-15-08.55.01.000000

     

    CONVERTING TO INTEGER DATA TYPES

    To convert to an Integer data type use one of the following expressions:

    • SmallInt()

    • Integer() or Int()

    • BigInt()

    The syntax for these functions is the same. There is only one argument for these functions. The argument can be a number, a numeric expression, or a character-string representation of an integer, decimal, or float data type. The table below shows some examples of these functions.




    Constants

    Constants

    Function

    Result

    Total = 456.254

    Count = 15

    SmallInt(1235.564)

    1235

    Int(Total/Count)

    30

    BigInt(‘89465411’)

    89465411

    Integer(‘45323.55’)

    45323

     

    CONVERTING TO NUMERIC DATA TYPES

    To convert data to a numeric format, use the following functions:

    • Decimal() or Dec()

    • Zoned()

    For these functions, the data type of the first argument determines the rest of the syntax. The first argument can be a number, a numeric expression, or a character-string representation of an integer, decimal, or float data type.

    If the first argument is numeric:

    • The second argument is an integer value for the desired precision for the result.

    • The third argument is an integer value for the desired scale for the result.

    If the first argument is a character string:

    • The second argument is an integer value for the desired precision for the result.

    • The third argument is an integer value for the desired scale for the result.

    • The fourth argument is the character that is to be used as the decimal separator in the first argument.

    The value of the precision argument is from 1 to 31. If no precision is specified, the precision is defaulted to the values listed below, based on the data type of the first argument.




    Data Type

    Data Type

    Default Precision

    Floating Point

    Decimal

    Numeric

    15

    Big Integer

    19

    Integer

    11

    Small Integer

    5

     

    The value of the scale argument is from zero to the precision specified in the second argument.

    The value of the separator argument is either a comma (,) or a period (.).

    The table below shows some examples of the ZONED() and DECIMAL() functions.




    Constants

    Constants

    Function

    Result

    Total = 456.254

    Count = 15

    Decimal(135,9,3)

    135.000

    Zoned(‘1254.33’,8,4)

    1254.0000

    Decimal(Total/Count,9,2)

    30.42

    Zoned(‘8912354,79′,9,2,’,’)

    8912354,79

     

    CONVERTING TO FLOAT DATA TYPES

    To convert data to a float data type, use the following functions:

    • Double() or Double_Precision()

    • Float()

    • Real()

    The syntax for these functions is the same. There is only one argument for these functions. The argument can be a number, a numeric expression, or a character-string representation of an integer, decimal, or float data type. The table below shows some examples of the functions.




    Constants

    Constants

    Function

    Result

    Total = 456.254

    Count = 15

    Real(1235.564)

    1.2355640000E+03

    Real(Total/Count)

    3.0416933333E+01

    Real(‘89465411’)

    8.9465411000E+07

    Real(‘45323.55’)

    4.5323000000E+04

    Real(‘9.879822E+04′)

    9.8798220000E+04

     

    YOU ARE IN CONTROL

    These functions allow you to have complete control over your data and data types. These functions can also be nested within other functions. When this approach is combined with the creation of a view, your data conversions can be defined one time for all programs or users. Another use for these functions is when you need to duplicate an existing formula coded within another language. By specifying the precision and scale of your operands, you can control the resulting value of a formula. These functions require frequent use before they become second nature to you. In the meantime, refer to your reference manuals frequently and don’t be afraid to experiment with new functions.

    Raymond Everhart has over 18 years of IT experience with IBM midrange computers. He was a consultant, programmer, and educator for an IBM premier business partner in Upstate New York for 10 years, before relocating to the Dallas/Ft. Worth area in 1998. Since then, Raymond has been helping local companies implement new technologies with his consulting, programming and mentoring services. E-mail: reverhart@itjungle.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Raz-Lee Security

    iSecurity Multi Factor Authentication (MFA) helps organizations meet compliance standards and improve the existing security environment on IBM i. It requires a user to verify his identity with two or more credentials.

    Key Features:

    • iSecurity provides Multi Factor Authentication as part of the user’s initial program
    • Works with every Authenticator App available in the Market.

    Contact us at https://www.razlee.com/isecurity-multi-factor-authentication/

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    DRV Technologies Expands Output Options with SpoolFlex 3.0 Power5 Debuts March 31, OS/400 V5R3 Coming in April

    Leave a Reply Cancel reply

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • IBM i Has a Future ‘If Kept Up To Date,’ IDC Says
  • When You Need Us, We Are Ready To Do Grunt Work
  • Generative AI: Coming to an ERP Near You
  • Four Hundred Monitor, March 22
  • IBM i PTF Guide, Volume 25, Number 12
  • Unattended IBM i Operations Continue Upward Climb
  • VS Code Is The Full Stack IDE For IBM i
  • Domino Runs on IBM i 7.5, But HCL Still Working on Power10
  • Four Hundred Monitor, March 6
  • IBM i PTF Guide, Volume 25, Number 11

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2023 IT Jungle