Re: [pgbr-geral] Função com generate_series
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
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
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
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 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
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 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
> > 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
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
> > 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
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
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