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 / dba / Perguntas / 186257
Accepted
hky404
hky404
Asked: 2017-09-19 11:58:01 +0800 CST2017-09-19 11:58:01 +0800 CST 2017-09-19 11:58:01 +0800 CST

Como posso retornar várias linhas de registros em PL/pgSQL

  • 772

Estou tentando retornar vários registros usando o tipo de dados RECORD, existe uma maneira de anexar a RECORD e adicionar/anexar um novo valor a cada iteração a este RECORD.

isto é, eu quero anexar para recque recse torne um conjunto de linhas quando o loop terminar, que eu possa apenas RETURN no final da minha função. Atualmente, estou fazendo isso -

SELECT temp_table.col1, temp_table.col2, temp_table.col3
      INTO rec
      FROM temp_table
      WHERE temp_table.col3 = false;

meu código completo está aqui:

CREATE OR REPLACE FUNCTION validation()
  RETURNS RECORD AS $$
DECLARE
        rec RECORD;
        temp_row RECORD;
BEGIN

  CREATE TEMPORARY TABLE temp_table (col1 TEXT, col2 INTEGER, col3 BOOLEAN) ON COMMIT DROP;

  FOR temp_row IN SELECT * FROM staging.validation
  LOOP

    RAISE NOTICE 'sql: %', temp_row.sql;

    EXECUTE format('INSERT INTO temp_table %s', temp_row.sql);

    IF (SELECT DISTINCT temp_table.col3 FROM temp_table WHERE temp_table.col3 = false)=false THEN
      RAISE NOTICE 'there is a false value';

      SELECT temp_table.col1, temp_table.col2, temp_table.col3
      INTO rec
      FROM temp_table
      WHERE temp_table.col3 = false;
    END IF;


  END LOOP;
  RETURN rec;
END; $$
LANGUAGE plpgsql;

Saída de corrente apósSELECT validation();

validation
(crea_ddf,8095,f)

Saída Desejada

validation
(crea_ddf,8095,f)
(some_source_system,some_count,f)
(some_other_source_system,some_count,f)
(.....)
postgresql plpgsql
  • 3 3 respostas
  • 56041 Views

3 respostas

  • Voted
  1. Best Answer
    Daniel Vérité
    2017-09-19T13:54:04+08:002017-09-19T13:54:04+08:00

    A função precisa retornar a SETOF RECORDem vez de RECORDe ter um RETURN NEXTpor linha em vez de um único RETURN, como em:

    CREATE FUNCTION test() RETURNS SETOF RECORD AS $$
    DECLARE
     rec record;
    BEGIN
      select 1,2 into rec;
      return next rec;
    
      select 3,4 into rec;
      return next rec;
    END $$ language plpgsql;
    

    Chamador:

    => selecione * de test() como x(a int ,b int) ;
     um | b
    ---+---
     1 | 2
     3 | 4
    (2 linhas)
    
    

    Observe que o SQL sendo fortemente e estaticamente tipado, o RECORDpseudo-tipo é difícil de trabalhar.
    Muitas vezes é menos complicado usar desde o início um tipo composto com uma definição completa de nomes e tipos para cada coluna, seja com a TABLE(...)sintaxe para um tipo anônimo ou com CREATE TYPEpara um tipo nomeado persistente.

    • 19
  2. klin
    2017-09-19T12:56:08+08:002017-09-19T12:56:08+08:00

    Use setof recorde return next recse quiser retornar vários registros de uma função, exemplo:

    create or replace function test_function()
        returns setof record 
        language plpgsql as $$
    declare
        rec record;
    begin
        for rec in
            select i, format('str%s', i), i/2*2 = i
            from generate_series(1, 3) i
        loop
            return next rec;
        end loop;
    end $$;
    

    Tal função precisa ser chamada na cláusula FROM com uma lista de definição de coluna:

    select test_function(); -- NO
    
    ERROR:  set-valued function called in context that cannot accept a set  
    
    select * from test_function();  -- NO
    
    ERROR:  a column definition list is required for functions returning "record"
    
    select * from test_function() as (id int, str text, is_even boolean);
    
     id | str  | is_even 
    ----+------+---------
      1 | str1 | f
      2 | str2 | t
      3 | str3 | f
    (3 rows)
    

    Uma opção melhor é usar returns table(...)e return query:

    drop function if exists test_function();
    create or replace function test_function()
        returns table (id int, str text, is_even boolean)
        language plpgsql as $$
    begin
        return query
            select i, format('str%s', i), i/2*2 = i
            from generate_series(1, 3) i;
        -- you can use return query multiple times
        -- or assign values to columns
        -- and return the row:
        id = 100;
        str = 'extra';
        is_even = true;
        return next; -- without a parameter
    end $$;
    

    Uso:

    select test_function(); -- possible but rather impractical
    
     test_function 
    ---------------
     (1,str1,f)
     (2,str2,t)
     (3,str3,f)
     (100,extra,t)
    (4 rows)
    
    select * from test_function();
    
     id  |  str  | is_even 
    -----+-------+---------
       1 | str1  | f
       2 | str2  | t
       3 | str3  | f
     100 | extra | t
    (4 rows)
    
    • 13
  3. Evan Carroll
    2017-09-19T14:57:03+08:002017-09-19T14:57:03+08:00

    Isso é uma bandeira vermelha..

    1. Você tem uma mesa validation.
    2. Você move as linhas para uma tabela temporária staging.
    3. Quaisquer linhas com temp_table.col3IS FALSE você retorna ao usuário
    4. Junto com quaisquer outras linhas em uma lista especificada de tabelas em que essa coluna é falsa.
    5. Então você descarta a tabela temporária (no commit)

    Basta fazer isso..

    WITH t AS ( SELECT true AS runthis FROM staging.validation WHERE col3 IS FALSE )
    SELECT *
    FROM staging.validation
    WHERE t.runthis && col3 = 3
    UNION ALL 
      SELECT *
      FROM some_source_system
      WHERE t.runthis && some_source_system.col3 = 3
    UNION ALL 
      SELECT *
      FROM some_other_source_system
      WHERE t.runthis && some_other_source_system.col3 = 3;
    

    Você pode até colocar isso em um VIEWse quiser

    Como uma nota rodapé

    SELECT DISTINCT temp_table.col3
    FROM temp_table
    WHERE temp_table.col3 = false
    

    O que DISTINCTaqui faz? Basta fazer LIMIT um. Na verdade, eu diria que isso é ainda mais limpo.

    SELECT true
    FROM temp_table
    WHERE temp_table.col3 = false
    LIMIT 1;
    

    Então você não precisa do estranho= false ) = FALSE

    • 2

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

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