Digamos que eu tenha que implementar um trecho de código T-SQL que deve retornar uma tabela como resultado. Posso implementar uma função com valor de tabela ou então um procedimento armazenado que retorna um conjunto de linhas. O que devo usar?
Resumindo, o que eu quero saber é:
Quais são as principais diferenças entre funções e procedimentos armazenados? Que considerações devo levar em consideração para usar um ou outro?
Respostas:
Se você provavelmente deseja combinar o resultado desse trecho de código com outras tabelas, obviamente uma função com valor de tabela permitirá que você componha os resultados em uma única instrução SELECT.
Geralmente, há uma hierarquia (View <TV Function <Stored Proc). Você pode fazer mais em cada um, mas a capacidade de compor as saídas e de o otimizador realmente se envolver diminui à medida que a funcionalidade aumenta.
Portanto, use o que lhe permitir, no mínimo, expressar o resultado desejado.
fonte
As funções devem ser determinísticas e não podem ser usadas para fazer alterações no banco de dados, enquanto os procedimentos armazenados permitem que você faça inserções e atualizações, etc.
Você deve limitar o uso de funções, pois elas representam um grande problema de escalabilidade para consultas grandes e complexas. Eles se tornam uma espécie de "caixa preta" para o otimizador de consulta, e você verá enormes diferenças de desempenho entre usar funções e simplesmente inserir o código em uma consulta.
Mas eles são definitivamente úteis para retornos com valor de tabela em casos muito específicos.
Se você precisar analisar uma lista delimitada por vírgulas, para simular a passagem de um array para um procedimento, uma função pode transformar a lista em uma tabela para você. Esta é uma prática comum com o Sql Server 2005, uma vez que não podemos passar tabelas para stored procedures (podemos com 2008).
fonte
Dos documentos :
fonte
Vou escrever algumas diferenças interessantes entre procedimentos armazenados e funções.
Não podemos usar funções não determinísticas em funções, mas podemos usar funções não determinísticas em procedimentos armazenados. Agora surge a pergunta, o que é função não determinística .. Resp é: -
Exceção:-
Podemos usar instruções DML (inserir, atualizar, excluir) dentro de um procedimento armazenado, mas não podemos usar instruções DML em funções em tabelas físicas ou tabelas permanentes. Se quisermos fazer operação DML em funções, podemos fazê-lo sobre variáveis de tabela, não em tabelas permanentes.
Não podemos usar o tratamento de erros dentro da função, mas podemos fazer o tratamento de erros em procedimentos armazenados.
fonte
O procedimento pode retornar zero ou n valores, enquanto a função pode retornar um valor que é obrigatório.
Os procedimentos podem ter parâmetros de entrada / saída, enquanto as funções podem ter apenas parâmetros de entrada.
O procedimento permite selecionar, bem como a instrução DML nele, enquanto a função permite apenas selecionar a instrução nele.
As funções podem ser chamadas a partir do procedimento, enquanto os procedimentos não podem ser chamados a partir da função.
A exceção pode ser tratada pelo bloco try-catch em um procedimento, enquanto o bloco try-catch não pode ser usado em uma função.
Podemos ir para o gerenciamento de transações no procedimento, enquanto não podemos ir para a função.
Os procedimentos não podem ser utilizados em uma instrução select, enquanto a função pode ser incorporada em uma instrução select.
UDF (função definida pelo usuário) pode ser usada nas instruções SQL em qualquer lugar na seção
WHERE
/HAVING
/SELECT
, enquanto os procedimentos armazenados não podem ser.UDFs que retornam tabelas podem ser tratadas como outro conjunto de linhas. Isso pode ser usado em
JOIN
s com outras tabelas.UDFs embutidos podem ser vistos como visualizações que aceitam parâmetros e podem ser usados em se
JOIN
outras operações de conjunto de linhas.fonte
Se você tem uma função, você pode usá-la como parte de sua instrução SQL, por exemplo
Não funciona dessa maneira para procedimentos armazenados.
fonte
Eu executei alguns testes com um bit de lógica de longa execução, com o mesmo pedaço de código (uma instrução SELECT longa) em execução em uma Função com valor de tabela e em um procedimento armazenado, e um EXEC / SELECT direto, e cada um executado de forma idêntica.
Na minha opinião, sempre use uma função com valor de tabela em vez de um procedimento armazenado para retornar um conjunto de resultados, pois torna a lógica muito mais fácil e legível em consultas que subsequentemente se unem a eles e permite que você reutilize a mesma lógica. Para evitar um impacto excessivo no desempenho, costumo usar parâmetros "opcionais" (ou seja, você pode passar NULL para eles) para permitir que a função retorne o conjunto de resultados mais rápido, por exemplo:
Desta forma, você pode usar esta função para muitas situações diferentes e não terá um grande impacto no desempenho. Acredito que isso seja mais eficiente do que filtrar depois:
Usei essa técnica em várias funções, às vezes com uma longa lista de parâmetros "opcionais" desse tipo.
fonte
Eu pessoalmente uso funções com valor de tabela quando tudo que estou retornando é uma única tabela sem efeitos. Basicamente, eu os trato como visualizações parametrizadas.
Se eu precisar que vários conjuntos de registros sejam retornados ou se houver valores atualizados nas tabelas, eu uso um procedimento armazenado.
Meus 2 centavos
fonte
Como mencionado acima, as funções são mais legíveis / combináveis / autodocumentáveis, mas têm menos desempenho em geral, e podem ter muito menos desempenho se você se empolgar com elas em junções, como
Muitas vezes, você só precisa aceitar a redundância de código que um tvf poderia eliminar (a um custo de desempenho inaceitável).
Um outro ponto que ainda não vi mencionado é que você não pode usar tabelas temporárias de alteração de estado do banco de dados dentro de um tvf com várias instruções. O mecanismo mais funcionalmente equivalente a uma tabela temporária é a não mudança de estado, na variável da tabela de memória, e para grandes conjuntos de dados, uma tabela temporária provavelmente terá mais desempenho do que uma variável de tabela. (Outras alternativas incluem tabelas dinâmicas e expressões de valor de tabela comuns, mas em algum nível de complexidade, essas deixam de ser uma boa opção IMO.)
fonte
Gostaria de testar o desempenho de ambos. É provável que a abordagem sp ou uma tabela derivada seja significativamente mais rápida do que uma função e, nesse caso, essa abordagem deve ser usada. Em geral, evito funções porque podem ser um grande obstáculo.
fonte
Depende :) Se você quiser usar o resultado com valor de tabela em outro procedimento, é melhor usar uma função TableValued. Se os resultados forem para um cliente, o procedimento armazenado é geralmente o melhor caminho a seguir.
fonte
Stored procedures são queries pré-compiladas que executam mais rapidamente e economizam das injeções de sql. Eles podem retornar 0 ou N valores. Podemos realizar operações DML dentro dos procedimentos armazenados. Podemos usar funções dentro dos procedimentos e podemos usar funções na consulta selecionada. Funções são usadas para retornar qualquer valor e operações DML não possíveis em funções. as funções são de dois tipos escalares e com valor de tabela. função escalar retorna um único valor, função com valor de tabela usada para retornar linhas de tabelas.
fonte