postgres проверит, если ноль, затем приведен к числовому - PullRequest
2 голосов
/ 10 февраля 2012

Я пытаюсь проверить, является ли значение пустым, если это так, то выбранное значение null преобразуется в числовое, но выдает ошибку. На самом деле это часть оператора вставки

INSERT into someTable(name,created,power) 
SELECT 'xyz',now(),
case when :power ='null' then NULL else cast(:power as numeric) end from abc 

ошибка, которую я получаю

Error: ERROR: invalid input syntax for type numeric: "null"

: power - это переменная, которой может быть присвоено любое значение с использованием кода Java. Если я даю значение NULL, это выдает ошибку.

В коде я получаю следующую ошибку из трассировки стека Java

org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to numeric

Ответы [ 5 ]

7 голосов
/ 10 февраля 2012

Ошибка:

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;
$$

Пояснение:

Если вы строите строку запроса, выражение cast('null' AS numeric) или просто 'null'::numeric всегда вызывает исключение, даже в блоке ELSE, который никогда не выполняется, потому что это invalid input syntax и исключение возникает во время проверки синтаксиса (как следует из сообщения об ошибке), а не во время выполнения.

Оператор CASE, который вы выводите на экран, имеет смысл только с параметром или переменной, а не с литералами. Второй экземпляр литерала никак не связан с первым экземпляром после того, как строка запроса была собрана.

Для такого динамического SQL вам нужно проверить значение до того, как вы создадите строку запроса. Или вы используете функцию или подготовленный оператор и передаете значение как параметр . Это тоже сработало бы.


Еще совет после комментария:

В вашем конкретном случае вы можете проверить значение в приложении и построить строку запроса следующим образом:

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

Вас может заинтересовать другой подход к вставке данных из файла условно.
Используйте COPY для файлов локально для сервера или метакоманду psql \ copy для файлов локально для клиента .

5 голосов
/ 20 февраля 2013

, если значение поля равно нулю, и в этом случае вы хотите отобразить его в какое-либо значение, вы можете использовать coalesce(field_name, 'Some value') или coalesce(field_name, 123).
Для полной документации см. здесь .

1 голос
/ 10 февраля 2012

Вы должны проверить с оператором IS, а не с равным, когда вы имеете дело с 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 
0 голосов
/ 10 августа 2015

Я пытался сделать что-то подобное, чтобы обновить / вставить некоторые записи, в которых числовое значение может быть нулевым или нет.Вы можете проверить переменную перед тем, как отправить ее в функцию или в функцию, в зависимости от переданного значения (для меня лучше использовать переменную, чем использовать CASE WHEN THEN ELSE END CASE каждый раз, когда вам нужно проверить значение)

Таким образом, чтобы работать со значениями NULL, используя обычный операнд сравнения, чтобы найти запись для обновления, можно сделать, установив transform_null_equals в положение ON

Я надеюсь, что это поможет кому-то

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;
0 голосов
/ 10 февраля 2012
INSERT into someTable(name,created,power) SELECT 'xyz',now(),
   case :power when 'null' then NULL else :power end::numeric from abc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...