Skip to content
Advertisement

WHILE / LOOP inside CASE expression SQL – ORACLE

I am testing a select statement containing a CASE expression and I need to add a WHILE / LOOP inside one of the WHEN conditions.

The logic from this statement will eventually be included inside a PL/SQL script but I want to know it´s working 100% before I include it in the procedural.

The logic serves to query a zip/postal code inside an XML package found in a clob column.

INTENDED ACTION:

if ZIP > 5 digits then remove everything after 5th char.

if ZIP < 5 digits then add ‘0’ until the length reaches 5 char.

else do nothing.

WHAT IS NEEDED:

The logic that adds a ‘0’ using contact() function needs to reiterate until the new zip reaches a length of 5 char. As it is, the query only adds up to one ‘0’, but this needs to repeat as many times as required for total char length to = ‘5’. My attempts at adding a LOOP or a WHILE all result in incorrect formating according to Oracle SQL.

QUERY:

SELECT ORDER_NUMBER, 
EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip') as "ZIPS_INV",
LENGTH(EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip')) as "ZIPS_LEN",
CASE
/* add digits to zip WHILE/LOOP NEEDED HERE */
  WHEN LENGTH(EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip')) < 5 
    THEN concat(EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip'), '0')
/* subtract digits to zip */
  WHEN LENGTH(EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip')) > 5 
    THEN substr(EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip'), 1, 5)    
  ELSE 
    'correct format'
END as "FIXED_ZIP"
FROM quarantine;

Advertisement

Answer

You can do both operations at once with RPAD(): this functions either pads the string, truncates it or leaves it untouched as per the target length.

So:

RPAD(
    EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip'),
    5,
    '0'
) 

In your query:

SELECT
    t.*,
    LENGTH(zips_inv) zip_len,
    RPAD(zip_inv, 5, '0') fixed_zip
    CASE WHEN LENGTH(zips_inv) = 5
        THEN 'correct format'
        ELSE 'wrong format' 
    END zip_status
FROM (
    SELECT 
        order_number, 
        EXTRACTVALUE(xmltype(PACKAGE), '/Package/fCustomerVO/invoiceAddress/zip') zips_inv
    FROM quarantine
) t

I find that a subquery is useful here to avoid repeating the same lengthy expression multiple times. Also, separating the zip value from its status (correct or not) makes more sense to me.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement