'CASE statement in Netezza

I am new to Netezza so may be I am not able to figure out the issue.

I have a scenario to implement in informatica with Netezza as the database. As few functions are not available/supported by informatica, so decided to make some netezza views and use them in informatica.

The scenario is as below :

INDEX_BDV = Convert "SST_LDA_TEA2PLUSBUCKET.INDEX" from CHAR to SMALLINT
/!\ If conversion fails, do not reject the records but put a NULL as default value /!\

I am trying to build a view. I tried building test query for conversion to smallint as below:

SELECT CASE WHEN CAST('99999' AS NUMERIC(18,0)) >= -32678 AND
                 CAST('99999' AS NUMERIC(18,0)) <= 32767
            THEN CAST('99999' AS smallint)
            ELSE NULL END

But everytime it fails with the error msg as below :

*ERROR [HY000] ERROR:  pg_atoi: error reading "99999": Numerical result out of range */

I tried some other alternative as below :

SELECT CASE WHEN CAST('99999' AS NUMERIC(18,0)) >= -32678 AND
                 CAST('99999' AS NUMERIC(18,0)) <= 32767
            THEN 'A'
            ELSE NULL END

The result is NULL. but for the above case it doesn't return NULL, rather it returns an exception.



Solution 1:[1]

Your query work properly, the problem isn't in the query. Show us another code. You can use simpler form of query.

SELECT CASE WHEN CAST('99999' AS NUMERIC(18,0)) between -32678 AND 32767
            THEN CAST('99999' AS smallint)
            ELSE NULL 
       END

Solution 2:[2]

You first query is failing because the system cannot CAST 99999 as a SMALLINT, which only covers ranges -32678 from 32767. The CAST of a literal will be evaluated at compilation time and will never make it to runtime in order to evaluate the CASE logic. This is probably what is confusing you here.

SELECT CASE WHEN CAST('99999' AS NUMERIC(18,0)) >= -32678 AND
                 CAST('99999' AS NUMERIC(18,0)) <= 32767
            THEN CAST('99999' AS smallint)
            ELSE NULL END

If you test this against data in an actual table it will perform as you expect.

TESTDB.ADMIN(ADMIN)=> create table smallint_test (col1 varchar(10));
CREATE TABLE
TESTDB.ADMIN(ADMIN)=> insert into smallint_test values ('99999');
INSERT 0 1
TESTDB.ADMIN(ADMIN)=> insert into smallint_test values ('1');
INSERT 0 1
TESTDB.ADMIN(ADMIN)=> SELECT COL1,
   CASE
      WHEN CAST(COL1 AS NUMERIC(18,0)) >= -32678
      AND CAST(COL1 AS  NUMERIC(18,0)) <= 32767
      THEN CAST(COL1 AS SMALLINT)
      ELSE NULL
   END
FROM SMALLINT_TEST;

 COL1  | CASE
-------+------
 1     |    1
 99999 |
(2 rows)

Based on your additional comments, I think the answer from @Niederee to this question can help you out.

Using the TRANSLATE function as he describes, you could do this:

SELECT INDEX,
   CASE
      WHEN
         TRANSLATE(INDEX,'0123456789','') IN ('','.','-','-.')
      THEN
         CASE
            WHEN INDEX BETWEEN -32678 AND 32767
            THEN INDEX::SMALLINT
            ELSE NULL
         END
      ELSE NULL
   END THE_NUMBER
FROM TPB;

 INDEX | THE_NUMBER
-------+------------
 1     |          1
 99999 |
 p     |
 p99   |
(4 rows)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Community