SQL null values in RPG

Hi Experts,

I have some SQLRPGLE problems with reading a tabel (with null capable fields)
The program reads a record in a DS , change 2 fields and write it to a remote (identical) table.

But I have to add a null "check field" per field
exec sql fetch next from cIMPH INTO
 :DS_REFERENCE       :ISNUL1,          
 :DS_CONTEXT         :ISNUL2,          

In this example it's not a problem, but I need to do this for a file with round 100 fields.
So I prefer to use the SQL

exec sql fetch next from cIMPH INTO :DS;

On top of that, if I use the null-check field, the original field contains a space or a zero.
the remote table expect null values.

How can I solve this?
LVL 17
Theo KouwenhovenApplication ConsultantAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Gary PattersonVP Technology / Senior Consultant Commented:
Create an array for the null indicators:

dcl-s NullInds int(5)  dim(100);  

then do the fetch like this:

fetch cIMPH into :bigDS :NullInds;

Then on the INSERT:

INSERT INTO remote-table-name
                     (column-name1, column-name-2, ....)
          VALUES (:host-var1:nullInds(1), :host-var2:nullInds(2), ...)

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Theo KouwenhovenApplication ConsultantAuthor Commented:
Hi Gary,

I figured that out allready, but then I need to make an insert statment with 100 fields and 100 values (+ nullind),
that will become unreadable and unmaintainable  

What if I read the file using RPG with ALWNULL(*USRCTL)

(until now I avoid using null capability, because of this problems)
Theo KouwenhovenApplication ConsultantAuthor Commented:
Hi Gary,

After some trial & error, its working (until now)

VALUES (:host-var1:nullInds(1), :host-var2:nullInds(2), ...) is not working, compile error on use of array index  :-(
But VALUES (:dataDS:nullInds) is functioning as long as dataDS is not qualified, so writeout per field is not required :-)
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

Gary PattersonVP Technology / Senior Consultant Commented:
Good solution.  You can also get around the array index issue by overlaying the NullInds array with a DS of named elements, then using the meaningful names in your SQL statement.  This is particularly useful if the SELECT DS and INSERT format aren't identical, and you are only dealing with a subset of columns.

        dcl-ds ids;
            meaningfulName1Null int(5);
            meaningfulName2Null int(5);
            meaningfulName3Null int(5);
            meaningfulName4Null int(5);
            meaningfulName5Null int(5);
            NullInds int(5) dim(5) pos(1);

Then in SQL:

VALUES (:meaningfulName1:meaningfulName1Null, :meaningfulName2:meaningfulName2Null, ...)

And as for writing maintainable SQL, use this format, with one variable/null indicator pair per source line:

Theo KouwenhovenApplication ConsultantAuthor Commented:
Hi Gary,

Now the next problem:
Nullind in SQL is working fine.
The nullind in RPG is working also (I assume)
FMYIMPH    IF   E           K DISK    ALIAS                    
DIMPH             DS                  LIKEREC(IMPH_00001)      
D                                     NULLIND(IMPHNULL)        
DIMPHNULL         DS                  LIKEREC(IMPH_00001:*NULL)

Open in new window

IMPHNULL is containing an serie of qualified, named indicator-fields, where *Off is notNull and *On is Null....

SQL expect an array of integer(5) fields with indication 0 or -1 as nullind.

I have to read the record from the local file (with RPG) and have to write it to a remote DB with SQL but the nullind fields are not compatible.
(not investigated yet) but I don't think that I can read with SQL from the local DB and write to an remote server in the same program?
Gary PattersonVP Technology / Senior Consultant Commented:
In the past, I've always segregated operations like this in separate programs.  If both systems are IBM I db2, you can access both the local and remote db in the same program.  Pre v7r1 you have to explicitly CONNECT to each system each time you switch target DBs, but you dont lose existing connections when you do that.  In v7r1, you can use 3 part naming and skip the CONNECT TO step.  Havent tested this with Ardgate running to a non IBM I remote db, though.
Gary PattersonVP Technology / Senior Consultant Commented:
I assume you are constructing SQL dynamically.  If so, you could just use a set of IF blocks to test each null indicator and append the special value NULL to your SQL INSERT string in place of a value when the null indicator is on.  This enables you to avoid the whole null indicator issue on the INSERT completely.
Theo KouwenhovenApplication ConsultantAuthor Commented:
Hi Gary,

"I assume you are constructing SQL dynamically."

Wrong assumption :-)
I will write the complete records 1:1 from the local table to the remote-DB.
Otherwise I have to dynamically generate the field names (up to 100 names) and the values.
Theo KouwenhovenApplication ConsultantAuthor Commented:
Found a workaround :-)

DIMPH             DS                  LIKEREC(IMPH_00001)      
D                                     NULLIND(iNull)         
DiNull            Ds                  LIKEREC(IMPH_00001:*Null)
DoNull            S              5I 0 dim(100)                 

     clear oNull;                       
     For idx = 1 to %len(iNull);      
       If %subst(iNull:idx:1) = '1';  
         oNull(idx) = -1;               

Open in new window

array oNull can be used on the SQL insert :-)
It's not very nice, but it will work.
Peter PriceIBM System I DeveloperCommented:
If you dont like the NULL VALUES, you coould actually try modifying your SQL select statement to include COALESCE. For example

Select Cast(COALESCE(b.Account_Name, a.Customer_Name, '*UNKNOWN) as Character(128)) as Resolved_Name from CUSTOMER_TABLE as a LEFT OUTER JOIN ACCOUNT_Table as b On a.CUST_Id = b.Cust_Id
Gary PattersonVP Technology / Senior Consultant Commented:
@P_S_PRICE:  Unfortunately, that's not even remotely related to this problem.  

If you'll review the entire thread, you'll see that the poster is reading from a null-capable table on one system, and writing to a null-capable table on another system, and needs to set the null indicator correctly (and if I recall correctly from another thread, the remote DB may not be IBM i DB2, so null indicators may require a different format).
Theo KouwenhovenApplication ConsultantAuthor Commented:
unfortunately, the remote DB doesn't accept the SQL400 way of presenting null-values (doesn't surprise me its microsoft :-)

So I dynamically assign the fields and values to write only not Null fields.  
The field default on the remote site will do the rest .
Theo KouwenhovenApplication ConsultantAuthor Commented:
Answer point me to the complete solution.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.