Question

I am using in insert statement to convert BDE table (source) to a Firebird table (destination) using IB Datapump. So the INSERT statement is fed by source table values via parameters. One of the source field parameters is alphanum (SOURCECHAR10 char(10), holds mostly integers and needs to be converted to integer in the (integer type) destination column NEWINTFLD. If SOURCECHAR10 is not numeric, I want to assign 0 to NEWINTFLD.

I use IIF and SIMILAR to to test whether the string is numeric, and assign 0 if not numeric as follows:

INSERT INTO "DEST_TABLE" (......,  "NEWINTFLD",.....)          
VALUES(..., IIF( :"SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*', :"SOURCECHAR10", 0),..)

For every non numeric string however, I still get conversion errors (DSQL error code = -303).

I tested with only constants in the IIF result fields like SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*', 1, 0) and that works fine so somehow the :SOURCECHAR10 in the true result field of the IIF generates the error. Any ideas how to get around this?

Was it helpful?

Solution

When your query is executed, the parser will notice that second use of :"SOURCECHAR10" is used in a place where an integer is expected. Therefor it will always convert the contents of :SOURCECHAR10 into an integer for that position, even though it is not used if the string is non-integer.

In reality Firebird does not use :"SOURCECHAR10" as parameters, but your connection library will convert it to two separate parameter placeholders ? and the type of the second placeholder will be INTEGER. So the conversion happens before the actual query is executed.

The solution is probably (I didn't test it, might contain syntax errors) to use something like (NOTE: see second example for correct solution):

CASE 
   WHEN :"SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*' 
      THEN CAST(:"SOURCECHAR10" AS INTEGER) 
   ELSE 0 
END

This doesn't work as this is interpreted as a cast of the parameter itself, see CAST() item 'Casting input fields'

If this does not work, you could also attempt to add an explicit cast to VARCHAR around :"SOURCECHAR10" to make sure the parameter is correctly identified as being VARCHAR:

CASE 
   WHEN :"SOURCECHAR10" SIMILAR TO '[[:DIGIT:]]*' 
      THEN CAST(CAST(:"SOURCECHAR10" AS VARCHAR(10) AS INTEGER) 
   ELSE 0 
END

Here the inner cast is applied to the parameter itself, the outer cast is applied when the CASE expression is evaluated to true

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top