Как объединить строку с нулем в функции postgres с plpg sql? - PullRequest
0 голосов
/ 29 января 2020

Я хочу написать функцию, которая выбирает некоторые значения из atable и затем вставляет их в btable.

DECLARE
loRecord record;
loRTest record;
lsQueryExecute text;

BEGIN

SELECT INTO loRTest 
    1 as test1,
    0 as test2,
    NULL::int as test_fk1,
    NULL::timestamp as test_fk2,
    NOW() as teststamp,
    true as test_bool
FROM atable

raise notice 'result  % ', loRTest; 

/ * result (1,0 ,,, "2020-01-29 11: 28: 33.785621 + 01 ", t) * /

что-то делать со значениями и, наконец, вставлять их в другую таблицу:

lsQueryExecute = 
'insert into btable (test1, test2, test_fk1, test_fk2, teststamp, test_bool) 
VALUES(
''' || loRTest.test1 || ''',
''' || loRTest.test2 || ''',
''' || loRTest.test_fk1 || ''',
''' || loRTest.test_fk2 || ''',
''' || loRTest.teststamp || ''',
''' || loRTest.test_bool ||''')';

/* EXECUTE */
 raise notice 'query  % ', lsQueryExecute; 

/*  query  <NULL>  */

хорошо, конкатенация с || и null устанавливает всю строку равной null . Какой правильный (простой, приятный) способ объединения строк (postgres 10)?

Ответы [ 2 ]

3 голосов
/ 29 января 2020

Не объединяйте значения, используйте соответствующие заполнители

lsQueryExecute := 
  'insert into btable (test1, test2, test_fk1, test_fk2, teststamp, test_bool) 
   VALUES ($1, $2, $3, $4, $5, $6)';

execute lsQueryExecute 
  using loRTest.test1, loRTest.test2, loRTest.test_fk1, 
        loRTest.test_fk2, loRTest.teststamp, loRTest.test_bool;

Если вам нужно сгенерировать динамические c SQL, лучший способ сделать это - использовать функцию format().


Но почему для начала динамика c SQL? Вы можете сделать это с помощью одного оператора INSERT:

insert into btable
SELECT 1 as test1,
       0 as test2,
       NULL::int as test_fk1,
       NULL::timestamp as test_fk2,
       NOW() as teststamp,
       true as test_bool
FROM atable

Если вы не можете использовать INSERT ... SELECT, вам все еще не нужны динамические c SQL в PL / pg SQL l oop:

insert into btable (test1, test2, test_fk1, test_fk2, teststamp, test_bool) 
VALUES (loRTest.test1, loRTest.test2, loRTest.test_fk1, 
        loRTest.test_fk2, loRTest.teststamp, loRTest.test_bool);
2 голосов
/ 29 января 2020

Пожалуйста, избегайте использования Dynami c SQL из пользовательского ввода, чтобы предотвратить SQL инъекцию. НЕ ИСПОЛЬЗУЙТЕ НИЖЕ, ЕСЛИ ВХОДЫ НЕ ВЕРЮТ.

В PostgreSQL оператор || объединяет STRING, но с аргументом NULL результат равен NULL.

In PostgreSQL> = 9,1

Используйте функцию CONCAT / CONCAT_WS (с разделителем) вместо ||. Он будет игнорировать значения NULL.

SELECT CONCAT('foo ', NULL, 'bar'); возвращает foo bar.

Если вы хотите получить более натуральный результат, используйте CONCAT_WS. SELECT CONCAT_WS(' ', 'foo', NULL, 'bar'); возвращает foo bar. ( Обратите внимание на удаленный завершающий пробел )

В PostgreSQL <9.1: </h2> Вы можете объединить COALESCE с оператором || следующим образом: SELECT COALESCE('foo', '') || COALESCE(NULL, '') || COALESCE('bar', ''); возвращает foobar. Вы можете настроить пустое пространство в соответствии с вашими потребностями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...