Tenho essa função no PostgreSQL, mas não sei como retornar o resultado da consulta:
CREATE OR REPLACE FUNCTION wordFrequency(maxTokens INTEGER)
RETURNS SETOF RECORD AS
$$
BEGIN
SELECT text, count(*), 100 / maxTokens * count(*)
FROM (
SELECT text
FROM token
WHERE chartype = 'ALPHABETIC'
LIMIT maxTokens
) as tokens
GROUP BY text
ORDER BY count DESC
END
$$
LANGUAGE plpgsql;
Mas não sei como retornar o resultado da consulta dentro da função PostgreSQL.
Achei que o tipo de retorno deveria ser SETOF RECORD
, certo? Mas o comando de retorno não está certo.
Qual é a maneira certa de fazer isso?
sql
postgresql
return
plpgsql
return-type
Renato Dinhani
fonte
fonte
LANGUAGE SQL
.Respostas:
Use
RETURN QUERY
:Ligar:
Explicação:
É muito mais prático definir explicitamente o tipo de retorno do que simplesmente declará-lo como registro. Dessa forma, você não precisa fornecer uma lista de definição de coluna com cada chamada de função.
RETURNS TABLE
é uma maneira de fazer isso. Há outros. Os tipos de dados dosOUT
parâmetros devem corresponder exatamente ao que é retornado pela consulta.Escolha os nomes dos
OUT
parâmetros com cuidado. Eles são visíveis no corpo da função em quase qualquer lugar. Colunas de qualificação de tabela com o mesmo nome para evitar conflitos ou resultados inesperados. Fiz isso para todas as colunas do meu exemplo.Mas observe o possível conflito de nomenclatura entre o
OUT
parâmetrocnt
e o alias da coluna de mesmo nome. Neste caso particular (RETURN QUERY SELECT ...
) Postgres usa o alias da coluna sobre oOUT
parâmetro de qualquer maneira. Isso pode ser ambíguo em outros contextos, no entanto. Existem várias maneiras de evitar qualquer confusão:ORDER BY 2 DESC
. Exemplo:ORDER BY count(*)
.plpgsql.variable_conflict
ou use o comando especial#variable_conflict error | use_variable | use_column
na função. Vejo:Não use "texto" ou "contagem" como nomes de coluna. Ambos são permitidos no Postgres, mas "contagem" é uma palavra reservada no SQL padrão e um nome de função básica e "texto" é um tipo de dados básico. Pode levar a erros confusos. Eu uso
txt
ecnt
em meus exemplos.Foi adicionado um
;
erro de sintaxe ausente e corrigido no cabeçalho.(_max_tokens int)
, não(int maxTokens)
- digite após o nome .Ao trabalhar com divisão inteira, é melhor multiplicar primeiro e dividir depois, para minimizar o erro de arredondamento. Ainda melhor: trabalhe com
numeric
(ou um tipo de ponto flutuante). Ver abaixo.Alternativo
É assim que eu acho que sua consulta realmente deve ser (calculando um compartilhamento relativo por token ):
A expressão
sum(t.cnt) OVER ()
é uma função de janela . Você poderia usar um CTE em vez da subconsulta - bonito, mas uma subconsulta é normalmente mais barata em casos simples como este.Uma declaração explícita
RETURN
final não é necessária (mas permitida) ao trabalhar comOUT
parâmetros ouRETURNS TABLE
(o que faz uso implícito deOUT
parâmetros).round()
com dois parâmetros só funciona paranumeric
tipos.count()
na subconsulta produz umbigint
resultado e umsum()
over thisbigint
produz umnumeric
resultado, portanto, lidamos com umnumeric
número automaticamente e tudo simplesmente se encaixa.fonte
RETURN;
antes dissoEND;
, pelo menos eu precisava - mas estou fazendo um UNION, então não tenho certeza se isso o torna diferente.RETURN
. Corrigido um erro não relacionado e adicionando algumas melhorias enquanto fazia isso.Olá, por favor, verifique o link abaixo
https://www.postgresql.org/docs/current/xfunc-sql.html
EX:
fonte