Pergunta para iniciantes:
Eu tenho uma função cara f(x, y)
em duas colunas xey na minha tabela de banco de dados.
Eu quero executar uma consulta que me dê o resultado da função como uma coluna e coloque uma restrição nela, algo como
SELECT *, f(x, y) AS func FROM table_name WHERE func < 10;
No entanto, isso não funciona, então terei que escrever algo como
SELECT *, f(x, y) AS func FROM table_name WHERE f(x, y) < 10;
Isso executará a função cara duas vezes? Qual é a melhor forma de fazer isso?
postgresql
postgresql-9.4
Jack Black
fonte
fonte
STABLE
/IMMUTABLE
ouVOLATILE
?Respostas:
Vamos criar uma função que tenha um efeito colateral para que possamos ver quantas vezes ela é executada:
E então chame assim:
Como você vê, a função é chamada pelo menos uma vez (da
WHERE
cláusula) e, quando a condição for verdadeira, mais uma vez para produzir a saída.Para evitar a segunda execução, você pode fazer o que Edgar sugere - ou seja, agrupar a consulta e filtrar o conjunto de resultados:
Para verificar ainda mais como isso funciona, pode-se ir
pg_stat_user_functions
e verificarcalls
lá (o dadotrack_functions
é definido como 'all).Vamos tentar com algo que não tem efeito colateral:
simple()
é realmente muito simples para que possa ser incorporado , portanto, não aparece na exibição. Vamos torná-lo inlinável:Como parece, a imagem é a mesma com ou sem efeitos colaterais.
Mudar
other_one()
paraIMMUTABLE
mudar o comportamento (talvez surpreendentemente) para pior, como será chamado 13 vezes em ambas as consultas.fonte
Tente chamá-lo novamente:
fonte