Em 05-02-2014 12:55, Matheus de Oliveira escreveu:



2014-02-05 Daniel Cordeiro <dmora...@gmail.com <mailto:dmora...@gmail.com>>:

    Bom dia,

    Em 05-02-2014 11:02, Rafael Fialho Corrêa escreveu:
    Em 5 de fevereiro de 2014 11:55, Matheus Saraiva
    <matheus.sara...@gmail.com <mailto:matheus.sara...@gmail.com>>
    escreveu:


        Rafael Fialho

        Não entendi o que vc quis dizer, o que preciso é que a
        clausula WHERE receba um parâmetro. Como:

        V = 'matheus'

        WHERE nome = V

        A variável V receberia o seu valor por parâmetro.


    O que quero dizer é o seguinte:

    CREATE OR REPLACE VIEW teste AS
      select
        id_nome
        , nome
      from
        nomes;
    GRANT ALL ON TABLE teste TO public;

    "select * from teste where nome = 'matheus';"

    Simples assim.. hehehe Isso que eu quis dizer.
    Acredito que esta não seja uma opção tão 'performática', uma vez
    que a view vai gerar todos os dados e só depois é que o planejador
    realizará a restrição através do cláusula WHERE e ordenações
    necessárias.


humm... Sua afirmação não está correta. Dada a view "teste" a seguinte consulta:

    SELECT * FROM teste WHERE nome = 'matheus';

Passa por algumas transformações, primeiro:

SELECT * FROM (SELECT id_nome, nome FROM nomes) teste WHERE nome = 'matheus';

Em seguida, o PostgreSQL "percebe" que não precisa da subquery e transforma a query acima em:

    SELECT id_nome, nome FROM nomes AS teste WHERE teste.nome = 'matheus';

Resumindo, a view não vai gerar todos os dados, a consulta (acima) é que será executada no final (claro ainda tem o plano de execução, métodos de acesso, etc.).

Eu até diria que nesse exemplo específico a view me parece até mais adequada e mais fácil de manter do que a função.

    Minha sugestão é criar uma função que realiza a consulta já
    adicionando as restrições necessárias para a triagem inicial dos
    dados desejados.

    Ex (descartando índices, segurança da função, etc)*1*.

        /CREATE TABLE lancamentos (id int, conta text, campo1 text,
        campo2 text);//
        //
        //INSERT INTO lancamentos
        VALUES(1,'Produtivo','valor1','valor2');//
        //INSERT INTO lancamentos
        VALUES(2,'Produtivo','valor1','valor2');//
        //INSERT INTO lancamentos
        VALUES(3,'Mecanica','valor1','valor2');//
        //INSERT INTO lancamentos
        VALUES(4,'Mecanica','valor1','valor2');//
        ....
        //
        //CREATE OR REPLACE FUNCTION sp_lancamentos(IN CODCONTA
        varchar) RETURNS TABLE(i int, c1 text,c2 text, c text)//
        //AS $$//
        //
        //    BEGIN//
        //        RETURN QUERY SELECT id,conta,campo1,campo2 FROM
        lancamentos WHERE conta = CODCONTA;//
        //    END;//
        //$$//
        //language 'plpgsql';/



OK. Realmente, para aceitar parâmetros da forma que o OP espera, é necessário sim uma função.

Eu só recomendaria, nesse caso especificamente, a usar uma função SQL ao invés de PL/pgSQL:

    CREATE OR REPLACE FUNCTION sp_lancamentos(IN CODCONTA varchar)
    RETURNS TABLE(i int, c1 text,c2 text, c text)
    AS $$
SELECT id,conta,campo1,campo2 FROM lancamentos WHERE conta = CODCONTA;
    $$
    LANGUAGE SQL;

Para chamá-la:

SELECT * FROM sp_lancamentos('Produtivo');

(a chamada em si seria igual à PL/pgSQL, só quis exemplificar)

    Para uma function muito grande e com muitas variáveis para
    substituição, vale a pena utilizar a cláusula EXECUTE no RETURN
    QUERY (isso já me salvou de vários problemas em functions com mais
    mais de 1500 linhas e código e dezenas de variáveis)*2*:
    /
        ....
        RETURN QUERY EXECUTE 'SELECT id,conta,campo1,campo2 FROM
    lancamentos WHERE conta = $1' USING CODCONTA;//
    /    ....



Ah? Por quê? Eu particularmente tento evitar o EXECUTE ao menos que estritamente necessário. Lembre-se que ele não pode ser otimizado pelo PL/pgSQL para armazenar o plano de execução.


    Lembrando que estas ações podem dificultar a análise de um
    problema futuro, pois o EXPLAIN não vai detalhar o conteúdo
    interno executado na função e nem nos logs.


+1. Otimizar funções é uma tarefa bem árdua. Só uma dica, a extensão auto_explain pode ajudar nessa tarefa. ;-)

    *1* -
    http://www.postgresql.org/docs/9.3/static/plpgsql-declarations.html
    *2* -
    http://www.postgresql.org/docs/9.3/static/plpgsql-statements.html




Atenciosamente,
--
Matheus de Oliveira
Analista de Banco de Dados
Dextra Sistemas - MPS.Br nível F!
www.dextra.com.br/postgres <http://www.dextra.com.br/postgres/>



_______________________________________________
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Acho que essa opção do Matheus Oliveira seria bem o que estou procurando, pois como respondi ao Euler Taveira, não quero escrever nenhuma clausula WHERE na chamada da VIEW. A não ser que view também receba parâmetros deste mesmo modo que as funções.
_______________________________________________
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a