AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-154216

Evgeny Nozdrev's questions

Martin Hope
Evgeny Nozdrev
Asked: 2018-07-14 04:17:32 +0800 CST

Como acessar outras linhas INSERTed/UPDATEd do gatilho no PostgreSQL?

  • 4

Solução em MS SQL

As funções de gatilho do MS SQL possuem tabelas deletedde insertedsistema nas quais todas as linhas afetadas pela operação são armazenadas. Você pode contar linhas atualizadas:

set @updatedCount = (select count(*) from deleted)

ou descubra o valor mínimo:

set @updatedMinimumCol1 = (select min(col1) from deleted)

Problema com PostgreSQL

Para FOR EACH ROWtriggers posso usar registros de sistema OLD e NEW, mas eles armazenam apenas 1 linha para cada chamada de trigger. As chamadas do gatilho são separadas, portanto, se o usuário atualizar 10 linhas, o gatilho será chamado 10 vezes, mas a cada vez posso saber apenas cerca de 1 linha atual, não todas as 10 linhas.

Pois FOR EACH STATEMENTnão conheço nenhum mecanismo de acesso a linhas atualizadas. Eu uso o PostgreSQL v9.6 e fui introduzido na v10.OLD TABLENEW TABLE

O PostgreSQL não permite que as tabelas antigas e novas sejam referenciadas em triggers de nível de instrução, ou seja, as tabelas que contêm todas as linhas antigas e/ou novas, que são referenciadas pelas cláusulas OLD TABLE e NEW TABLE no padrão SQL.


Tente com a coluna adicional transaction_timestamp()

Posso adicionar uma coluna especial DEFAULT transaction_timestamp()à tabela principal e usá-la para distinguir as linhas recém-atualizadas de outras, mas não é uma solução, pois várias INSERTs/UPDATEspodem estar em uma transação e elas terão o mesmo carimbo de data e hora da transação. Provavelmente eu poderia limpar essa coluna de carimbo de data/hora no gatilho após cada instrução para evitar esse problema, mas como fazer isso se essa limpeza emitir o gatilho de atualização novamente - será uma chamada de gatilho de atualização infinita.

Portanto, esta tentativa falhou.


Solução ruim no PostgreSQL

A única maneira que eu sei é que:

Primeiro, use FOR EACH ROWo gatilho para coletar estatísticas atuais (min e contagem) como funções agregadas. Eu uso a tabela temporária para armazená-la entre as chamadas (esse gatilho é chamado 1 vez para cada linha). Mas não saberemos qual linha é a última (quando chegará a hora de usar essas estatísticas).

CREATE TEMP TABLE IF NOT EXISTS _stats (
  _current_min   int,
  _current_count int
) ON COMMIT DROP;

IF EXISTS(SELECT 1 FROM _stats LIMIT 1) THEN
  --Current row is not first, there is statistics for previous rows.
  UPDATE _stats
  SET _current_min   = (CASE WHEN NEW.col1 < _current_min THEN NEW.col1
                        ELSE _current_min END)
    , _current_count = _current_count + 1;
ELSE
  --There is no stats because current row is first for this INSERT/UPDATE
  INSERT INTO _stats (_current_min, _current_count)
  VALUES (NEW.col1, 1);
END IF;

Segundo, use FOR EACH STATEMENTo gatilho para usar as estatísticas coletadas. Não se esqueça de limpar a tabela temporária (se o usuário executar vários INSERTs/UPDATEs em uma transação, as estatísticas antigas permanecerão na tabela temporária e corromperão todos os próximos cálculos!).

Para tarefas mais complexas podemos criar tabelas temporárias insertede deletedda mesma forma que _stats.


A solução alternativa

No PostgreSQL podemos usar a cláusula RETURNING para INSERT/UPDATE/DELETE para obter novos valores de todas as linhas afetadas pela operação. Então podemos manipular com eles, mas cada função com INSERTs/UPDATEs tem que implementar essa tecnologia ===> 1. código adicional em funções com tais INSERTs/UPDATEs - duplicação do RETURNING; 2. podemos esquecer de implementar tal tecnologia para nova função; 3. os dados serão corrompidos, pois as manipulações necessárias não serão chamadas automaticamente (como os gatilhos).


A questão

Talvez você conheça uma maneira melhor de acessar todas as linhas afetadas por INSERT/UPDATE?

postgresql trigger
  • 2 respostas
  • 10112 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve