Reputation: 11455
I am trying check if a value is null if so the select null else cast to numeric, but it throws an error. This is actually part of an insert statement
INSERT into someTable(name,created,power)
SELECT 'xyz',now(),
case when :power ='null' then NULL else cast(:power as numeric) end from abc
error that I get is
Error: ERROR: invalid input syntax for type numeric: "null"
:power is a variable that can be given any value using java code. If I give a value of null it give an error.
In code I get the following error from the java stack trace
org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to numeric
Upvotes: 4
Views: 43170
Reputation: 658907
SELECT CASE WHEN 'null' = 'null' THEN NULL ELSE cast('null' AS numeric) END
DO
$$
DECLARE
power text := 'null';
BEGIN
PERFORM CASE WHEN power = 'null' THEN null ELSE cast(power AS numeric) END;
END
$$
If you build a query string, the expression cast('null' AS numeric)
or simply 'null'::numeric
always raises an exception, even in an ELSE
block that is never executed, because it is invalid input syntax
and the exception is raised during the syntax check (like the error message implies), not during execution.
A CASE
statement like you display only makes sense with a parameter or variable not with literals. The second instance of the literal has no connection to the first instance whatsoever after the query string has been assembled.
For dynamic SQL like that, you need to check the value before you build the query string. Or you use a function or prepared statement and pass the value as parameter. That would work, too.
In your particular case you could check the value in the app and build a query string like this:
INSERT INTO tbl(name, abc_id, created, power)
SELECT 'xyz'
, abc_id
, now()
, <insert_value_of_power_or_NULL_here> -- automatically converted to numeric
FROM abc;
You may be interested in a different approach to INSERT
data from a file conditionally.
Use COPY
for files local to the server or psql's meta-command \copy
for files local to the client.
Upvotes: 11
Reputation: 71
I was trying to do something similar in order to update/insert some records where a numeric value can be null or not. You can validate a variable before you send it to the function or inside the function depending the value passed (For me using a variable is better than use CASE WHEN THEN ELSE END CASE every time you need to validate the value)
So to work with the NULL values using a regular comparison operand in order to find a record to update can be done by turning transform_null_equals to ON
I hope this help someone
CREATE OR REPLACE FUNCTION update_insert_transaction(vcodaccount integer, vcodaccountaux text,
vdescription text, vcodgroup integer)
RETURNS integer AS $$
DECLARE
n integer = 0;
vsql text = 'NULL';
BEGIN
IF vcodaccountaux <> '' THEN
vsql = vcodaccountaux;
END IF;
SET LOCAL transform_null_equals TO ON;
EXECUTE 'UPDATE account_import_conf SET (codaccount, codaccountaux, description, codgroup) =
('||vcodaccount||','||vsql||',trim('||quote_literal(vdescription)||'),'||vcodgroup||')
WHERE codaccount='||vcodaccount||' AND codaccountaux = '||vsql||' RETURNING * ';
GET DIAGNOSTICS n = ROW_COUNT;
IF n = 0 THEN
EXECUTE 'INSERT INTO account_import_conf (codaccount, codaccountaux, description, codgroup)
SELECT '||vcodaccount||','||vsql||' ,trim('||quote_literal(vdescription)||'),'||vcodgroup||';';
END IF;
RETURN n;
END;$$
LANGUAGE plpgsql;
Upvotes: 0
Reputation: 1305
if the field value is null, and you want in this case to map it to some value you can use coalesce(field_name, 'Some value')
or coalesce(field_name, 123)
.
For full documentation see here.
Upvotes: 9
Reputation: 7307
INSERT into someTable(name,created,power) SELECT 'xyz',now(),
case :power when 'null' then NULL else :power end::numeric from abc
Upvotes: 0
Reputation: 72676
You have to check with the IS operator, and not with the equal when you dealing with NULL :
INSERT into someTable(name,created,power)
SELECT 'xyz',now(),
case when :power IS null then NULL else cast(:power as numeric) end from abc
Upvotes: 1