Ir para conteúdo
Fórum Script Brasil

Ronivaldo Lopes

Membros
  • Total de itens

    39
  • Registro em

  • Última visita

Sobre Ronivaldo Lopes

  • Data de Nascimento Setembro 22

Contatos

  • MSN
    (95)981141842

Perfil

  • Gender
    Male
  • Location
    Boa Vista - RR
  • Interests
    SQL Server, Postgresql, Delphi e Lazarus.

Últimos Visitantes

697 visualizações

Ronivaldo Lopes's Achievements

0

Reputação

  1. Bom dia, uso uma única trigger genérica e uma única tabela para gravar o log de todas as tabelas a serem monitoradas. Todos os campos das tabelas são gravados no campo dados1 do tipo jsonb. No exemplo1, todas as tabelas tem como chave o campo id, e para comandos update, somente os campos que foram atualizados são gravados nos campos dados1 e dados2, depois e antes da atualização, respectivamente. Você pode simplificar e fazer o comando do insert funcionar para o update (exemplo2), nesse caso pode excluir o campo dados2 da tabela _generic_log. Caso deseje gravar os dados antes da alteração, e as tabela possuírem os campos chaves com nomes diferentes, já que se trata de um banco antigo, para cada tabela repetir o comando, substituindo a palavra key pelo nome da campo chave da tabela (exemplo3). Na ultima parte, tem a rotina que associa todas as tabelas do banco para gravar na tabela _generic_log, com exceção as tabelas que estão as linha do IF, nesse caso a própria tabela _generic_log, pois entrará em loop ao incluir seu próprio log. Feito isso, a tabela _generic_log terá as informações necessárias para você monitorar todas as ações dos usuários. -- ******************** drop table if exists public._generic_log; create table public._generic_log ( id serial not null primary key, tabela varchar(50) not null, usuario varchar(50) not null default current_setting('app.user_name'), ip_address varchar(15) not null default current_setting('app.ip_address'), mac_address varchar(17) not null default current_setting('app.mac_address'), data_hora int8 not null default to_char(now(), 'yyyymmddHH24missms')::int8, operacao char not null check (operacao in ('I', 'U', 'D')), dados1 jsonb not null, dados2 jsonb null ); create index _generic_log_ind on public._generic_log using brin ( tabela ); -- *************************************************** exemplo1 drop function if exists public.check_generic_log(); create or replace function public.check_generic_log() returns trigger as $$ begin if tg_op = 'INSERT' then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ) from jsonb_each( to_jsonb( new ) ) n; elseif tg_op = 'DELETE' then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( o.key, o.value ) from jsonb_each( to_jsonb( old ) ) o; else -- update insert into _generic_log (tabela, operacao, dados1, dados2 ) select * from ( select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ) as dados1, jsonb_object_agg( o.key, o.value ) as dados2 from jsonb_each( to_jsonb( new ) ) n join jsonb_each( to_jsonb( old ) ) o on n.key = o.key where n.key in ('id','n.key') or (coalesce(n.value, o.value) is distinct from coalesce(o.value, n.value) and n.key <> 'data_hora_log')) a where dados1 <> dados2; end if; return null; end; $$ language plpgsql;] -- **************************** exemplo2 drop function if exists public.check_generic_log(); create or replace function public.check_generic_log() returns trigger as $$ begin if (tg_op = 'INSERT') or (tg_op = 'UPDATE') then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ) from jsonb_each( to_jsonb( new ) ) n; elseif tg_op = 'DELETE' then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( o.key, o.value ) from jsonb_each( to_jsonb( old ) ) o; end if; return null; end; $$ language plpgsql; -- **************************** exemplo3 drop function if exists public.check_generic_log(); create or replace function public.check_generic_log() returns trigger as $$ begin if (tg_op = 'INSERT') or (tg_op = 'UPDATE') then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ) from jsonb_each( to_jsonb( new ) ) n; elseif tg_op = 'DELETE' then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( o.key, o.value ) from jsonb_each( to_jsonb( old ) ) o; else -- update if tg_table_name = 'bancos' then insert into _generic_log (tabela, operacao, dados1, dados2 ) select * from ( select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ) as dados1, jsonb_object_agg( o.key, o.value ) as dados2 from jsonb_each( to_jsonb( new ) ) n join jsonb_each( to_jsonb( old ) ) o on n.cdbanco = o.cdbanco where n.key in ('cdbanco','n.key') or (coalesce(n.value, o.value) is distinct from coalesce(o.value, n.value) and n.key <> 'data_hora_log')) a where dados1 <> dados2; elseif tg_table_name = 'agencias' then insert into _generic_log (tabela, operacao, dados1, dados2 ) select * from ( select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ) as dados1, jsonb_object_agg( o.key, o.value ) as dados2 from jsonb_each( to_jsonb( new ) ) n join jsonb_each( to_jsonb( old ) ) o on n.cdagencia = o.cdagencia where n.key in ('cdagencia','n.key') or (coalesce(n.value, o.value) is distinct from coalesce(o.value, n.value) and n.key <> 'data_hora_log')) a where dados1 <> dados2; end if; end if; return null; end; $$ language plpgsql; -- *************************************************** -- *************************************************** -- -- Executa a trigger generica para todas as tabela do banco de dados -- do $$ declare _tabela varchar(100); declare _obj record; begin for _obj in select schemaname as schema, relname as tabela from pg_stat_user_tables where substring(relname for 1 from 1) <> '_' order by relname loop _tabela := _obj.schema || '.' || _obj.tabela; execute format('drop trigger if exists log_generic on %s;', _tabela ); execute format('drop trigger if exists log_generic_update on %s;', _tabela ); if not _obj.tabela = any (values ('_generic_log','_tabela1...','_tabela2...')) then -- insert or delete execute format('create trigger log_generic after insert or delete on %s for each row execute function public.check_generic_log();', _tabela ); -- update --> somente se houve alteração ==> for each row WHEN (old.* is distinct from new.*) execute format('create trigger log_generic_update after update on %s for each row when (old.* is distinct from new.*) execute function public.check_generic_log();', _tabela ); end if; end loop; end; $$
  2. Bom dia, na clausula including você pode especificar o que copiar (defaults, constraints, indexes, all), o que não acontece com o "create table tab_a as select * from tab_b". do $$ begin execute 'create table tbl_01_' || to_char(now(), 'yyyymmddHH24missms') || ' (like tbl_01 including all)'; end; $$ ou do $$ begin execute format('create table tbl_01_%s (like tbl_01 including all)', to_char(now(), 'yyyymmddHH24missms')); end; $$
  3. Bom dia, na tabela de Cad_Clients, cada cliente possui 1 Ctrl, na tabela de Cad_Colors, o Ctrl pode ter mais uma cor, resumindo a cliente pode ter mais de uma cor. select a.*, b.Color from Cad_Clients a left join Cad_Colors b on a.Ctrl = b.Ctrl where b.Ctrl is not null order by a.idPerson 100 -> Red 103 -> Yellow 104 -> Blue e Purple 105 -> Green e Red resultado da query idperson person ctrl color 1 John 100 Red 4 Emily 103 Yellow 5 William 104 Blue 5 William 104 Purple 6 Olivia 105 Red 6 Olivia 105 Green 7 James 100 Red 10 Sophia 103 Yellow 11 Samuel 104 Purple 11 Samuel 104 Blue 12 Ava 105 Red 12 Ava 105 Green 13 Joseph 100 Red
  4. Boa tarde, quando eu trabalhava com SQL Server, eu usava a função Convert, o ultimo parâmetro, nesse caso o 111, é o formato yyyy/mm/dd, sendo que existem outros formatos. Qtde de registros por data select Convert(Char(10), data, 111) as data, sum(1) as qtde from tabela group by Convert(Char(10), data, 111) order by Convert(Char(10), data, 111) Somente datas select distinct Convert(Char(10), data, 111) from tabela Não tenho o SQL Server pata testar
  5. Faça o teste sem a primeira e a ultima barra, você pode utilizar o excel para abrir a ser importado, exclua as colunas em branco antes da primeira barra e depois da ultima barra, e gere novamente o arquivo sem essas duas barras.
  6. Bom dia, não tenho o SQL Server instalado para testar, mas a primeira e a ultima barra não devem existir no arquivo a ser importado, a barra está sendo utilizada como delimitador dos campos, ou seja, use somente entre os campos. Utilize o assistente de exportação e gere um arquivo para verificar como fica o resultado.
  7. Bom dia, você tem que executar com 'select * from funcao()' e não com 'select funcao()'. Sua função retorna uma tabela, você pode selecionar somente os campos necessários e não todos os campos ( * ). SELECT * from relacional.lista_pedido_site_status_data('Gold', NULL,NULL,NULL);
  8. Bom dia, há alguns anos deixei de usar o SQL Server e não tenho como testar. O operador "IN" é utilizado para verificar uma lista de expressões, e o erro pode ser que o parâmetro seja uma STRING, se for o caso, você pode utilizar a condição abaixo. where case when trim(@parametro) = '' then true else charindex(uf, @parametro) > 0 end
  9. Boa noite, -- Criar a tabela e incluir os registros drop table if exists tabela; create table tabela (funcao char(3), dtinicial date, dtfinal date); insert into tabela (funcao, dtinicial, dtfinal) values ('DI1','01/01/2023','31/03/2023'), ('VP1','10/01/2023','20/01/2023'),('VP2','10/02/2023','20/03/2023'),('DI2','01/04/2023','10/04/2023'); with d00 as ( select funcao, dtinicial as data, 1 as tipo, row_number() over ( order by dtinicial, funcao ) as row from tabela union all select funcao, dtfinal, 2, row_number() over ( order by dtinicial, funcao ) as row from tabela ), d01 as ( select *, row_number() over ( order by data, funcao ) as row1 from d00 ), d02 as ( select funcao, data, tipo, 1 as comando from d01 -- * union all select null, b.data-1, 2, 2 from d01 a, d01 b where a.row <> b.row and a.row1+1 = b.row1 and b.data > a.data+1 and b.tipo = 1 -- ** union all select null, a.data+1, 1, 3 from d01 a, d01 b where a.row <> b.row and a.row1 = b.row1-1 and b.data > a.data+1 and a.tipo = 2 ), -- *** d03 as ( select *, row_number() over ( order by data ) as row from d02 ), d04 as ( select a.funcao, a.data as dtinicial, b.data as dtfinal from d03 a, d03 b where a.row+1 = b.row and a.tipo = 1 order by a.data, a.funcao) select distinct coalesce(a.funcao, b.funcao), a.dtinicial, a.dtfinal from d04 a left join tabela b on a.dtinicial between b.dtinicial and b.dtfinal and a.dtfinal between b.dtinicial and b.dtfinal order by a.dtinicial, coalesce(a.funcao, b.funcao);
  10. Pode usar window functions select * from tabela where id_t in ( select first_value(id_t) over (partition by id_setor, dt_ent) from tabela );
  11. Boa tarde, considerando que o campo id_t seja o id da tabela e que seja sequencial e deternine a ordem que os registros são incluídos. No select da clausula where você filtra o período select * from tabela where id_t in (select min(id_t) from tabela where dt_ent between :dtInicial and :dt_final group by id_setor, dt_ent)
  12. Boa noite, uso uma trigger genérica para gravar o log de todas as tabelas, uso o tipo de dados jsonb para gravar os campos, e para o arquivo de índice, uso o índice do tipo brin que ocupa pouco espaço no disco, principalmente para tabelas com muitos registros. Todas as tabelas tem com chave o campo id, e para comandos update, são gravados somente são os campos que foram atualizados, antes e depois de atualizados, nos campos dados1 e dados2. create table _generic_log ( tabela text not null, usuario text not null default current_setting('app.user_name'), ip_address text not null default current_setting('app.ip_address'), mac_address text not null default current_setting('app.mac_address'), data_hora timestamp not null default now(), operacao char not null check (operacao in ('I', 'U', 'D')), dados1 jsonb not null, dados2 jsonb null ); create index _generic_log_ind on _generic_log using brin (tabela); create or replace function check_generic_log() returns trigger as $$ begin if tg_op = 'INSERT' then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ) from jsonb_each( to_jsonb( new ) ) n; elseif tg_op = 'DELETE' then insert into _generic_log ( tabela, operacao, dados1 ) select tg_table_name, tg_op::char, jsonb_object_agg( o.key, o.value ) from jsonb_each( to_jsonb( old ) ) o; else insert into _generic_log (tabela, operacao, dados1, dados2 ) select tg_table_name, tg_op::char, jsonb_object_agg( n.key, n.value ), jsonb_object_agg( o.key, o.value ) from jsonb_each( to_jsonb( new ) ) n join jsonb_each( to_jsonb( old ) ) o on n.key = o.key where (n.key = 'id') or (coalesce(n.value, o.value) is distinct from coalesce(o.value, n.value)); -- where (n.key = 'id' or n.value is distinct from o.value) and (n.key not in ( 'XXX','YYY' )); end if; return null; end; $$ language plpgsql; -- *************************************************** do $$ declare _comando text; declare _obj record; begin for _obj in select schemaname as schema, relname as tabela from pg_stat_user_tables loop -- insert or delete execute format('drop trigger if exists log_generic on %s;', ( _obj.schema || '.' || _obj.tabela)); execute format('create trigger log_generic after insert or delete on %s for each row execute function check_generic_log();', ( _obj.schema || '.' || _obj.tabela)); -- update --> somente se houve alteração ==> for each row WHEN (old.* is distinct from new.*) execute format('drop trigger if exists log_generic_update on %s;', ( _obj.schema || '.' || _obj.tabela)); execute format('create trigger log_generic_update after update on %s for each row WHEN (old.* is distinct from new.*) execute function check_generic_log();', ( _obj.schema || '.' || _obj.tabela)); end loop; end; $$
  13. boa noite, você tem que usar ":=" para mudar o campo status_op, CREATE OR REPLACE FUNCTION f_au_pcpcpr() RETURNS trigger AS $$ BEGIN IF NEW.pcpr_statuss_1 = 'C' THEN NEW.status_op := 'C'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql;
×
×
  • Criar Novo...