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 / 141419
Accepted
jlandercy
jlandercy
Asked: 2016-06-17 05:02:17 +0800 CST2016-06-17 05:02:17 +0800 CST 2016-06-17 05:02:17 +0800 CST

PostgreSQL: Passar tabela como argumento na função

  • 772

Estou descobrindo TYPEno PostgreSQL. Tenho um TABLE TYPEque alguma tabela deve respeitar (interface). Por exemplo:

CREATE TYPE dataset AS(
    ChannelId INTEGER
   ,GranulityIdIn INTEGER
   ,GranulityId INTEGER
   ,TimeValue TIMESTAMP
   ,FloatValue FLOAT
   ,Status BIGINT
   ,QualityCodeId INTEGER
   ,DataArray FLOAT[]
   ,DataCount BIGINT
   ,Performance FLOAT
   ,StepCount INTEGER
   ,TableRegClass regclass
   ,Tags TEXT[]
   ,WeightedMean FLOAT
   ,MeanData FLOAT
   ,StdData FLOAT
   ,MinData FLOAT
   ,MaxData FLOAT
   ,MedianData FLOAT
   ,Percentiles FLOAT[]
);

Eu posso criar uma tabela usando este modelo com:

CREATE TABLE test OF dataset;

Já vi muitas opções na API , mas estou um pouco perdido. Gostaria de saber se é possível atribuir esse tipo aos INPUT/OUTPUTparâmetros da função.

Digamos que eu tenha um FUNCTIONchamado processque receba uma amostra de registros de um dataset TABLE source, os processe e depois retorne um TABLE sinkcom o mesmo TYPE.

Ou seja, gostaria de saber se é possível criar um TYPEque se comporte assim:

CREATE FUNCTION process(
    input dataset
) RETURNS dataset
AS ...

E isso pode ser chamado assim:

SELECT
    *
FROM
    source, process(input := source) AS sink;

Eu me pergunto se isso é possível com o PostgreSQL e pergunto como fazer isso. Alguém de vocês sabe?


Aqui está um MWE do que estou tentando fazer:

DROP TABLE IF EXISTS source;
DROP FUNCTION IF EXISTS process(dataset);
DROP TYPE dataset;

CREATE TYPE dataset AS (
    id INTEGER
   ,t  TIMESTAMP
   ,x  FLOAT
);


CREATE TABLE source OF dataset;
ALTER TABLE source ADD PRIMARY KEY(Id);
INSERT INTO source VALUES
    (1, '2016-01-01 00:00:00', 10.0)
   ,(2, '2016-01-01 00:30:00', 11.0)
   ,(3, '2016-01-01 01:00:00', 12.0)
   ,(4, '2016-01-01 01:30:00',  9.0)
   ;

CREATE OR REPLACE FUNCTION process(
    _source dataset
)
RETURNS SETOF dataset
AS
$BODY$
SELECT * FROM source;
$BODY$
LANGUAGE SQL;

SELECT * FROM process(source);

Mas não tem sucesso, é como se a fonte fosse percebida como uma coluna em vez de uma SETOF RECORDScom o tipo de conjunto de dados.

postgresql functions
  • 2 2 respostas
  • 46939 Views

2 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2016-06-21T18:10:07+08:002016-06-21T18:10:07+08:00

    O parâmetro _sourceno MWE (exemplo de trabalho mínimo) não é referenciado em nenhum lugar. O identificador sourceno corpo da função não tem sublinhado à esquerda e é interpretado como nome de tabela constante de forma independente.

    Mas não funcionaria assim de qualquer maneira. SQL só permite parametrizar valores em instruções DML. Ver:

    • Erro ao definir n_distinct usando uma variável plpgsql

    Solução

    Você ainda pode fazê-lo funcionar usando SQL dinâmico com EXECUTEuma função plpgsql:

    CREATE TYPE dataset AS (id integer, t timestamp, x float);
    
    CREATE TABLE source OF dataset (PRIMARY KEY(Id));  -- add constraints in same command
    
    INSERT INTO source VALUES
        (1, '2016-01-01 00:00:00', 10.0)
       ,(2, '2016-01-01 00:30:00', 11.0);
    
    CREATE OR REPLACE FUNCTION process(_tbl regclass)
      RETURNS SETOF dataset AS
    $func$
    BEGIN
    RETURN QUERY EXECUTE 'SELECT * FROM ' || _tbl;
    END
    $func$  LANGUAGE plpgsql;
    
    SELECT * FROM process('source');  -- table name as string literal 
    

    Ver:

    • Nome da tabela como um parâmetro de função do PostgreSQL

    Ou procure perguntas e respostas relacionadas no site.

    Para fazê-lo funcionar para qualquer tabela:

    CREATE OR REPLACE FUNCTION process2(_tbl anyelement)
      RETURNS SETOF anyelement AS
    $func$
    BEGIN
    RETURN QUERY EXECUTE 'SELECT * FROM ' || pg_typeof(_tbl);
    END
    $func$  LANGUAGE plpgsql;
    
    SELECT * FROM process2(NULL::source);  -- note the call syntax!!
    

    Explicação detalhada:

    • Refatorar uma função PL/pgSQL para retornar a saída de várias consultas SELECT
    • 18
  2. Sam Fed
    2019-12-03T11:34:49+08:002019-12-03T11:34:49+08:00

    Isso fará o que você deseja sem precisar de nenhum SQL dinâmico :

    drop table if exists source cascade;
    drop function if exists process(dataset) cascade;
    drop type if exists dataset cascade;
    
    create type dataset as (
        id integer
       ,t  timestamp
       ,x  float
    );
    
    create table source of dataset;
    alter table source add primary key(id);
    insert into source values
       (1, '2016-01-01 00:00:00', 10.0)
     , (2, '2016-01-01 00:30:00', 11.0)
    ;
    
    create or replace function process(
        x_source dataset[]
    )
    returns setof dataset
    as
    $body$
    select * from unnest(x_source);
    $body$
    language sql;
    
    select *
    from
      process(
        array(
          select
            row(id, t, x)::dataset
          from source
        )
      );
    

    Tanto quanto eu posso dizer (depois de pesquisar extensivamente, porque eu tive o mesmo problema) você não pode passar uma tabela diretamente para uma função.

    No entanto, conforme mostrado, você pode transformar uma tabela em uma matriz []de um tipo personalizado que consiste em vários tipos básicos (semelhante a uma definição de tabela).

    Em seguida, você pode passar esse array e desaninha-lo de volta em uma tabela quando estiver na função.

    • 8

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