Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Guimarães Faria Corcete DUTRA , Leandro
2016-10-19 11:19 GMT-02:00 Izaque Maciel :
>
> Chave artificial.
> É somente uma identificação de número controle interno, não é como um cpf ou
> rg.
> Não entendo bem, mas garantindo a unicidade do campo em questão, no caso o
> "id", já resolve. Obrigado por alertarem.

Enquanto não der outros problemas, tudo bem; mas sem uma chave
natural, você provavelmente nalgum momento terá a mesma informação
várias vezes registrada, só com ids diferentes.  Deve ser um dos
problemas mais comuns em bases de dados hoje.


-- 
skype:leandro.gfc.dutra?chat  Yahoo!: ymsgr:sendIM?lgcdutra
+55 (61) 3546 7191  gTalk: xmpp:leand...@jabber.org
+55 (61) 9302 2691ICQ/AIM: aim:GoIM?screenname=61287803
BRAZIL GMT−3  MSN: msnim:chat?contact=lean...@dutra.fastmail.fm
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Izaque Maciel
Em 19 de outubro de 2016 10:52, Guimarães Faria Corcete DUTRA, Leandro <
l...@dutras.org> escreveu:

> Não foi o que você perguntou, mas alertando para um problema potencial:
>
>
> Essa tabela tem chave natural, ou só artificial?  Porque a artificial
> não garante unicidade, e se for só ela dará problema mais cedo ou mais
> tarde.
>
>
> --
> skype:leandro.gfc.dutra?chat  Yahoo!: ymsgr:sendIM?lgcdutra
> +55 (61) 3546 7191  gTalk: xmpp:leand...@jabber.org
> +55 (61) 9302 2691ICQ/AIM: aim:GoIM?screenname=61287803
> BRAZIL GMT−3  MSN: msnim:chat?contact=lean...@dutra.fastmail.fm
> ___
> pgbr-geral mailing list
> pgbr-geral@listas.postgresql.org.br
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>

Chave artificial.
É somente uma identificação de número controle interno, não é como um cpf
ou rg.
Não entendo bem, mas garantindo a unicidade do campo em questão, no caso o
"id", já resolve. Obrigado por alertarem.
Passarei a utilizar sempre o sequence, já que ele garante que mais de uma
sessão não utilize o mesmo número.
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Guimarães Faria Corcete DUTRA , Leandro
Não foi o que você perguntou, mas alertando para um problema potencial:


2016-10-18 15:19 GMT-02:00 Izaque Maciel :
>
> select date
> from generate_series(new.dtinicial::timestamp,
>   new.dtfinal, '1 day') date
> where extract(dow from date) not in (0,6)
>   LOOP
> INSERT INTO tarefa_itens (id, id_tarefaag, data_horafin,
>  data_horaexec, executada)
> VALUES ((select coalesce((max(ti.id) + 1), 1)
> chave from tarefa_itens ti),
>   new.id,
>   null,
> rec.date   -- Aqui
>   'N');

Essa tabela tem chave natural, ou só artificial?  Porque a artificial
não garante unicidade, e se for só ela dará problema mais cedo ou mais
tarde.


-- 
skype:leandro.gfc.dutra?chat  Yahoo!: ymsgr:sendIM?lgcdutra
+55 (61) 3546 7191  gTalk: xmpp:leand...@jabber.org
+55 (61) 9302 2691ICQ/AIM: aim:GoIM?screenname=61287803
BRAZIL GMT−3  MSN: msnim:chat?contact=lean...@dutra.fastmail.fm
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Izaque Maciel
Em 19 de outubro de 2016 09:58, Matheus de Oliveira <
matioli.math...@gmail.com> escreveu:

>
> 2016-10-19 9:41 GMT-02:00 Izaque Maciel :
>
>> encontrei também uma maneira de atualizá-las, em alguns casos de rollback.
>
>
> Essa afirmação me deixa um tanto preocupado, você não está falando de
> executar um SETVAL após um ROLLBACK, né?
>
>
> --
> Matheus de Oliveira
>
>
>
> ___
> pgbr-geral mailing list
> pgbr-geral@listas.postgresql.org.br
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>


Não é isso, é porque um sistema antigo que dei manutenção era muito
complicado tratar os "ids",
tinha que dar lock na tabela em questão para tentar garantir que o valor do
id fosse o único, utilizando o max(id) + 1,
e este id é utilizado como numeração de controle pelos usuários do sistema.
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Matheus de Oliveira
2016-10-19 9:41 GMT-02:00 Izaque Maciel :

> encontrei também uma maneira de atualizá-las, em alguns casos de rollback.


Essa afirmação me deixa um tanto preocupado, você não está falando de
executar um SETVAL após um ROLLBACK, né?


-- 
Matheus de Oliveira
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Izaque Maciel
Que ótimo, resolve alguns problemas, estudei um pouco sobre as sequences, e
encontrei também uma maneira de atualizá-las, em alguns casos de rollback.
Muito obrigado pessoal!

Em 19 de outubro de 2016 09:17, Matheus de Oliveira <
matioli.math...@gmail.com> escreveu:

>
> 2016-10-19 8:45 GMT-02:00 Izaque Maciel :
>
>> Obrigado Mateus, farei os ajustes. Só mais uma dúvida, utilizando a
>> sequence mencionada acima ou o nextval explícito, nunca ocorrerá problemas
>> de concorrência?
>
>
> Não, porque o PostgreSQL garante que apenas uma sessão recupere o mesmo
> valor na sequence.
>
> Um efeito causado pela sequence, entretanto, é que em caso de ROLLBACK da
> transação o valor da sequence não volta, podendo deixar buracos na
> sequência. O que em geral não é um problema, porque o que sequence garante
> é só a geração de valores únicos.
>
> Atenciosamente,
> --
> Matheus de Oliveira
>
>
>
> ___
> pgbr-geral mailing list
> pgbr-geral@listas.postgresql.org.br
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Matheus de Oliveira
2016-10-19 8:45 GMT-02:00 Izaque Maciel :

> Obrigado Mateus, farei os ajustes. Só mais uma dúvida, utilizando a
> sequence mencionada acima ou o nextval explícito, nunca ocorrerá problemas
> de concorrência?


Não, porque o PostgreSQL garante que apenas uma sessão recupere o mesmo
valor na sequence.

Um efeito causado pela sequence, entretanto, é que em caso de ROLLBACK da
transação o valor da sequence não volta, podendo deixar buracos na
sequência. O que em geral não é um problema, porque o que sequence garante
é só a geração de valores únicos.

Atenciosamente,
-- 
Matheus de Oliveira
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Izaque Maciel
>
> Além do que o Euler já comentou, eu tenho mais duas recomendações.
>
> 1. Essa é bem grave, usar `select coalesce(max(id)+1),1) ...` é uma
> prática comum, mas pode ter consequências indesejáveis devido à problemas
> de concorrência. Interessante que comentei sobre isso esses dia no último
> PGDay Campinas [1]. Caso duas sessões tentem executar esse código ao mesmo
> tempo, ambas vão recuperar o mesmo ID, tentando assim inserir o mesmo
> valor. A solução nesse caso é simplesmente usar uma SEQUENCE, para isso
> basta definir a coluna ID como SERIAL ou BIGSERIAL e simplesmente não usar
> essa coluna no INSERT, deixando o PostgreSQL gerar o ID automaticamente (ou
> então use DEFAULT ou nextval explícito).
>
> 2. Essa não é um problema, é mais uma pequena otimização. Eu também não
> usaria LOOP, simplesmente faria INSERT ... SELECT.
>
> O resultado seria mais ou menos assim:
>
> INSERT INTO tarefa_itens (
> id_tarefaag, data_horafin, data_horaexec, executada
> )
> SELECT
> NEW.id, null, g.dt, 'N'
> FROM
> generate_series(new.dtinicial::timestamp, new.dtfinal, '1 day')
> AS g(dt)
> WHERE
> EXTRACT(DOW FROM g.dt) NOT IN (0,6);
>
> Se quiser fazer o equivalente ao SERIAL na coluna que já existe, basta
> executar:
>
> BEGIN;
> CREATE SEQUENCE tarefa_itens_id_seq;
> ALTER TABLE tarefa_itens ALTER id SET DEFAULT
> nextval('tarefa_itens_id_seq');
> ALTER SEQUENCE tarefa_itens_id_seq OWNED BY tarefa_itens.id;
> SELECT setval('tarefa_itens_id_seq', max(id)) FROM tarefa_itens;
> COMMIT;
>
> [1] http://www.slideshare.net/matheus_de_oliveira/o-que-voc-
> acha-que-sabe-sobre-banco-de-dados
>
> Atenciosamente,
> --
> Matheus de Oliveira
>
>
>
Obrigado Mateus, farei os ajustes. Só mais uma dúvida, utilizando a
sequence mencionada acima ou o nextval explícito, nunca ocorrerá problemas
de concorrência?
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-19 Por tôpico Matheus de Oliveira
On Tue, Oct 18, 2016 at 3:19 PM, Izaque Maciel 
wrote:

>   FOR rec IN
> select date
> from generate_series(new.dtinicial::timestamp,
>   new.dtfinal, '1 day') date
> where extract(dow from date) not in (0,6)
>   LOOP
> INSERT INTO tarefa_itens (id, id_tarefaag, data_horafin,
>  data_horaexec, executada)
> VALUES ((select coalesce((max(ti.id) + 1), 1)
> chave from tarefa_itens ti),
>   new.id,
>   null,
> rec.date   -- Aqui
>   'N');
>
>   END LOOP;
>

Além do que o Euler já comentou, eu tenho mais duas recomendações.

1. Essa é bem grave, usar `select coalesce(max(id)+1),1) ...` é uma prática
comum, mas pode ter consequências indesejáveis devido à problemas de
concorrência. Interessante que comentei sobre isso esses dia no último
PGDay Campinas [1]. Caso duas sessões tentem executar esse código ao mesmo
tempo, ambas vão recuperar o mesmo ID, tentando assim inserir o mesmo
valor. A solução nesse caso é simplesmente usar uma SEQUENCE, para isso
basta definir a coluna ID como SERIAL ou BIGSERIAL e simplesmente não usar
essa coluna no INSERT, deixando o PostgreSQL gerar o ID automaticamente (ou
então use DEFAULT ou nextval explícito).

2. Essa não é um problema, é mais uma pequena otimização. Eu também não
usaria LOOP, simplesmente faria INSERT ... SELECT.

O resultado seria mais ou menos assim:

INSERT INTO tarefa_itens (
id_tarefaag, data_horafin, data_horaexec, executada
)
SELECT
NEW.id, null, g.dt, 'N'
FROM
generate_series(new.dtinicial::timestamp, new.dtfinal, '1 day') AS
g(dt)
WHERE
EXTRACT(DOW FROM g.dt) NOT IN (0,6);

Se quiser fazer o equivalente ao SERIAL na coluna que já existe, basta
executar:

BEGIN;
CREATE SEQUENCE tarefa_itens_id_seq;
ALTER TABLE tarefa_itens ALTER id SET DEFAULT
nextval('tarefa_itens_id_seq');
ALTER SEQUENCE tarefa_itens_id_seq OWNED BY tarefa_itens.id;
SELECT setval('tarefa_itens_id_seq', max(id)) FROM tarefa_itens;
COMMIT;

[1]
http://www.slideshare.net/matheus_de_oliveira/o-que-voc-acha-que-sabe-sobre-banco-de-dados

Atenciosamente,
-- 
Matheus de Oliveira
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-18 Por tôpico Izaque Maciel
>
> Você está misturando um tipo (date) com nome de uma variável [1]. Isso
> está confundindo o parser. Ou você usa um outro nome para variável no
> record ou ajusta o parâmetro de configuração plpgsql.variable_conflict
> (eu prefiro a primeira opção).
>
> Apesar de "date" não ser uma palavra reservada no postgres [2], ela é
> reservada no padrão SQL. Evite um nome de coluna com essa palavra-chave.
>
>
> [1]
> https://www.postgresql.org/docs/9.6/static/plpgsql-
> implementation.html#PLPGSQL-VAR-SUBST
> [2] https://www.postgresql.org/docs/9.6/static/sql-keywords-appendix.html
>
>
> --
>Euler Taveira   Timbira - http://www.timbira.com.br/
>PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento
>
>
Ok Euler, vou verificar, obrigado pela ajuda.
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Re: [pgbr-geral] Função com generate_series

2016-10-18 Por tôpico Euler Taveira
On 18-10-2016 14:19, Izaque Maciel wrote:
> Estou tentando um insert que pega os valores do novo registro da tabela
> tarefa (After Insert) e gera os valores da tabela tarefa_itens. Com a
> função generate_series dentro do for loop armazeno num tipo Record, mas
> no momento da execução recebo um erro de que o schema rec não existe. O
> que estou fazendo de errado?
> 
> ERROR:  schema "rec" does not exist
> LINE 7: rec.date
> 
Você está misturando um tipo (date) com nome de uma variável [1]. Isso
está confundindo o parser. Ou você usa um outro nome para variável no
record ou ajusta o parâmetro de configuração plpgsql.variable_conflict
(eu prefiro a primeira opção).

Apesar de "date" não ser uma palavra reservada no postgres [2], ela é
reservada no padrão SQL. Evite um nome de coluna com essa palavra-chave.


[1]
https://www.postgresql.org/docs/9.6/static/plpgsql-implementation.html#PLPGSQL-VAR-SUBST
[2] https://www.postgresql.org/docs/9.6/static/sql-keywords-appendix.html


-- 
   Euler Taveira   Timbira - http://www.timbira.com.br/
   PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

[pgbr-geral] Função com generate_series

2016-10-18 Por tôpico Izaque Maciel
Boa tarde pessoal,

se possível, por favor me auxiliem nesta função:

CREATE OR REPLACE FUNCTION public.tarefa_agendada_ai (
)
RETURNS trigger AS
$body$
DECLARE
  rec record;
BEGIN
  FOR rec IN
select date
from generate_series(new.dtinicial::timestamp,
  new.dtfinal, '1 day') date
where extract(dow from date) not in (0,6)
  LOOP
INSERT INTO tarefa_itens (id, id_tarefaag, data_horafin,
 data_horaexec, executada)
VALUES ((select coalesce((max(ti.id) + 1), 1)
chave from tarefa_itens ti),
  new.id,
  null,
rec.date   -- Aqui
  'N');

  END LOOP;
  return new;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;


Estou tentando um insert que pega os valores do novo registro da tabela
tarefa (After Insert) e gera os valores da tabela tarefa_itens. Com a
função generate_series dentro do for loop armazeno num tipo Record, mas no
momento da execução recebo um erro de que o schema rec não existe. O que
estou fazendo de errado?

ERROR:  schema "rec" does not exist
LINE 7: rec.date
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral