Você pode conseguir isso com uma função SQL simples. O recurso principal é a função
generate_subscripts()
:CREATE OR REPLACE FUNCTION f_attendance(_arr2d int[])
RETURNS SETOF attendance AS
$func$
SELECT a.*
FROM generate_subscripts($1, 1) i
JOIN attendance a ON a.class = $1[i][1]
AND a.section = $1[i][2]
$func$ LANGUAGE ROWS 10 sql STABLE;
Ligar:
SELECT * FROM f_attendance(ARRAY[[1,1],[2,2]]);
Ou o mesmo com um array literal - o que é mais conveniente em alguns contextos, especialmente com declarações preparadas:
SELECT * FROM f_attendance('{{1,1},{2,2}}');
A função sempre espera uma matriz 2D. Mesmo se você passar um único par, aninhe-o:
SELECT * FROM f_attendance('{{1,1}}');
Auditoria de sua implementação
-
Você fez a funçãoVOLATILE
, mas pode serSTABLE
. Por documentação:
Devido a esse comportamento de instantâneo, uma função contendo apenasSELECT
comandos podem ser marcados com segurança comoSTABLE
.
Relacionado:
- Como passar um parâmetro para uma função de data
-
Você também usaLANGUAGE plpgsql
em vez desql
, o que faz sentido se você executar a função várias vezes na mesma sessão. Mas então você também deve torná-loSTABLE
ou você perde esse potencial benefício de desempenho. O manual mais uma vez:
STABLE
eIMMUTABLE
as funções usam um instantâneo estabelecido no início da consulta de chamada, enquanto as funções VOLATILE obtêm um instantâneo no início de cada consulta que executam.
-
SeuEXPLAIN
a saída mostra uma Varredura somente de índice , não uma varredura sequencial como você suspeita em seu comentário.
-
Há também uma etapa de classificação em seuEXPLAIN
saída que não corresponde ao código que você mostra. Tem certeza de que copiou oEXPLAIN
correto saída? Como você conseguiu isso de qualquer maneira? As funções PL/pgSQL são caixas pretas paraEXPLAIN
. Você usouauto_explain
? Detalhes:
- Plano de consulta Postgres de uma invocação de UDF escrita em pgpsql
-
O planejador de consultas do Postgres não tem ideia de quantos elementos de array o parâmetro passado terá, então é difícil planejar a consulta e pode ser padrão para uma varredura sequencial (dependendo de mais fatores). Você pode ajudar declarando o número esperado de linhas. Se você normalmente não tiver mais de 10 itens, adicioneROWS 10
como eu fiz agora acima. E teste novamente.