PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Dividir determinada string e preparar a instrução case


Configuração limpa:
CREATE TABLE tbl (
  given_date date
, set_name varchar
);

Use um termo singular como nome de coluna para um único value.
O tipo de dados é obviamente date e não um timestamp .

Para transformar seus parâmetros de texto em uma tabela útil:
SELECT unnest(string_to_array('2001-01-01to2001-01-05,2001-01-10to2001-01-15', ',')) AS date_range
     , unnest(string_to_array('s1,s2', ',')) AS set_name;

"Desaninhamento paralelo" é útil, mas tem suas ressalvas. Postgres 9.4 adiciona uma solução limpa, Postgres 10 eventualmente higienizado o comportamento deste. Ver abaixo.

Execução dinâmica

Declaração preparada


As declarações preparadas são visíveis apenas para a sessão de criação e morrem com ela. Por documentação:

As instruções preparadas duram apenas pela duração da sessão atual do banco de dados.

PREPARE uma vez por sessão :
PREPARE upd_tbl AS
UPDATE tbl t
SET    set_name = s.set_name
FROM  (
   SELECT unnest(string_to_array($1, ',')) AS date_range
        , unnest(string_to_array($2, ',')) AS set_name
   ) s
WHERE t.given_date BETWEEN split_part(date_range, 'to', 1)::date
                       AND split_part(date_range, 'to', 2)::date;

Ou use ferramentas fornecidas pelo seu cliente para preparar a declaração.
Execute n vezes com parâmetros arbitrários:
EXECUTE upd_tbl('2001-01-01to2001-01-05,2001-01-10to2001-01-15', 's1,s4');

Função do lado do servidor


As funções são persistentes e visíveis para todos sessões.

CREATE FUNCTION uma vez :
CREATE OR REPLACE FUNCTION f_upd_tbl(_date_ranges text, _names text)
  RETURNS void AS
$func$
UPDATE tbl t
SET    set_name = s.set_name
FROM  (
   SELECT unnest(string_to_array($1, ',')) AS date_range
        , unnest(string_to_array($2, ',')) AS set_name
   ) s
WHERE  t.given_date BETWEEN split_part(date_range, 'to', 1)::date
                        AND split_part(date_range, 'to', 2)::date
$func$  LANGUAGE sql;

Ligue n vezes:
SELECT f_upd_tbl('2001-01-01to2001-01-05,2001-01-20to2001-01-25', 's2,s5');

Fiddle SQL

Design superior


Use parâmetros de matriz (ainda podem ser fornecidos como literais de string), um daterange type (ambos da página 9.3) e o novo paralelo unnest() (pág. 9.4 ).
CREATE OR REPLACE FUNCTION f_upd_tbl(_dr daterange[], _n text[])
  RETURNS void AS
$func$
UPDATE tbl t
SET    set_name = s.set_name
FROM   unnest($1, $2) s(date_range, set_name)
WHERE  t.given_date <@ s.date_range
$func$  LANGUAGE sql;

<@ sendo o operador "elemento está contido por".

Ligar:
SELECT f_upd_tbl('{"[2001-01-01,2001-01-05]"
                  ,"[2001-01-20,2001-01-25]"}', '{s2,s5}');

Detalhes:
  • Desaninhar vários arrays em paralelo