SQL no código x Stored Procedures
11/10/2014
0
Fernanda Acacia
Posts
09/11/2014
Cleverson
09/11/2014
Soeuseijothaz
Pois é vai contra as melhores prática, pois caso haja uma mudança para outro banco de dados o trabalho de portar as regras de negócio pode ser duro. Se as regra de negócio estão em uma camada especifica e as sentenças SQL aderirem o padrão ASNSI o quanto possível, fica mais simples.
A mais ou menos 15 anos atrás trabalhei num projeto gigante usando asp, componentes vb e sybase. Naquela época o IIS e mesmo o windows não eram tão robustos e maduros quanto hoje, sem falar do hardware. Memória era cara e usada com parcimônia. Então tínhamos problemas de performance consideráveis. Veio uma diretriz tecnológica para que todas as regras de negócio e formatação de campos fossem para as SP´s. E realmente tivemos ganhos consideráveis de performance. Ficamso livres de uma baita dor de cabeça. Então para aquele cenário foi válido. Depois de uns anos com uma evolução natural dos softwares e hardware a diretriz mudou, a partir de agora toda as regras de negócio e formatação de campos não devem ser usados em SP.
Quanto o banco de dados senta e chora a "nabada" vai para os DB´s. Eles é que devem resolver o problema. Com o uso de SP´s fica claro tudo o que rodando no BD. Esta tudo ali a disposição para análise e tuning. Quando se usa sentenças SQL na aplicação nunca se sabe o que o infeliz do desenvolvedor vai usar. Poe exemplo trabalhei em uma empresa em que era desaconselhável (proibido mesmo) o uso de SELECT INTO. Então nada melhor do que ter as SP´s a traves de query verificar se alguém esta usando deste expediente. Via aplicação fica difícil. Além do mais ao usar SQL direto na aplicação você permite o desenvolvedor escrever qualquer sandice.
Eu particularmente gosto muito de SP´s, pois quando a sentença SQL é muto complexa fica um porre escrevê-la. O mais fácil é usar um software tipo o Manegement Studio para testar e depois colocar em um string. Usando SP`s a sentença fica mais legível, claro que você tem de ir lá e abrir a sp para ver o conteúdo, mas isto não me parece nada impeditivo.
Agora com estes framework de persistência e o ORM fica depressivo ficar escrevendo CRUD.
Ultimante estou trabalhando com .Net usando entyti e linq to SQL e já não me apego tanto assim a SP´s. Pois o linq realmente é muito interessante e poderoso.
Porém começa a ser questionado se é um boa deixar o entity fazer um cópia do BD com objetos relacionas em memória e sua implicações. Sempre vai haver prós e contras.
E existe ainda a querela entre a modelagem UML e a modelagem do BD. Para os puristas do UML o BD deve ser a cópia fiel da modelagem UML. Para os puristas DB nem sempre. Dai começam as polêmica.
Acho que qualquer que seja a bordagem tudo depende do bom senso e do cenário.
Agora quanto mais as camadas forem separadas melhor, acho que esta é a regra básica.
09/11/2014
Fernanda Acacia
09/11/2014
Soeuseijothaz
Quando uma empresa define que todo o acesso a dados seria obrigatoriamente realizado por SP´s seria para qualquer sistema. Neste caso não importa qual o tamanho do sistema ou mesmo se é para pesquisa ou CRUD.
Seria mais um estratégia para que os DBA´s pudessem ter uma visão e controle maior do que estaria rodando na base de dados.
A grosso modo seria como se você tivesse uma loja. Quando um ciente chega e solicita uma mercadoria que esta na vitrine fica simples atender o pedido. Se a mercadoria estiver no estoque ou mesmo tive de confeccionar ai há demora em atender o pedido. No caso do comerciante se a mercadoria tivesse de ser confeccionada ele agradeceria e dispensaria o cliente. O Mecanismo de banco de dados não têm este livre arbítrio se for feita uma solicitação que esta na vitrine (sp´s) ele atende. Se for feita uma solicitação que não esta na vitrine (sp), mas é uma solicitação válida e ele tem como atender ele vai lá construir a mercadoria (o resultado da execução da sentença slq) e entrega.
Em certas empresas a áreas de Dados tem muita influencia então para eles é melhor usar SP e isto se torna uma norma.
O Sybase e SQL Server usam como estratégia para melhorar a performance as "estatísticas" (os utros bd´s não me lembre se usam, mas acho que sim ) e com SP,que ficam em chace ou pré-compiladas, fica mais fácil atualizá-las.
Agora vai de sua intuição definir qual a melhor forma de abordar a questão. Como nos últimos anos sempre trabalhei em empresas em que o uso era uma norma eu sempre usava, pois acho que fica mais organizado e ficar fácil testá-las sem a necessidade de executar a aplicação. Só que .hoje com entity e linq SQL já não uso tanto. Só uso quando não consigo escrever minhas sentença em linq.
Agora NUCA COLOQUE AS REGRAS DE NEGÓCIO em SP´s, isto sim é um heresia como já expliquei no post anterior.
Se você ficar mais a vontade em colocar as sentenças no código vai em frente desde que sejam bem escritas não vai fazer diferença. Pois merdas podem ser feitas em SP´s ou via código.
Se for usar em código tente escrever algo limpo e usar parâmetros.
SqlCommand cmd = conn.CreateCommand(); cmd.CommandType = CommandType.Text; StringBuilder sbQuery = new StringBuilder(); sbQuery.Append("SELECT usr.IdUsuario,usr.NmUsuario,usr.Senha,usr.Login,usr.IdPerfil,usr.IdFazendeiro,usr.IdLaboratorio, "); sbQuery.Append("fz.IdFazendeiro,fz.NrCPF,fz.NmFazendeiro,fz.NmBairro,fz.NmEndereco,fz.NrCNPJ,fz.NmRazaoSocial, "); sbQuery.Append("lb.IdLaboratorio,lb.NmLaboratorio,lb.IdCidade "); sbQuery.Append("FROM Usuario usr "); sbQuery.Append("left join fazendeiro fz on fz.IdFazendeiro = usr.IdFazendeiro "); sbQuery.Append("left join laboratorio lb on lb.IdLaboratorio = usr.IdLaboratorio "); #endregion #region Filtros StringBuilder sbFiltro = new StringBuilder(); if (filtroUsuario != null) { if (!string.IsNullOrEmpty(filtroUsuario.Login)) { sbFiltro.Append(" usr.Login = @Login "); } if (!string.IsNullOrEmpty(filtroUsuario.Senha)) { sbFiltro.Append(!string.IsNullOrEmpty(sbFiltro.ToString()) ? "AND" : string.Empty); sbFiltro.Append(" usr.Senha = @Senha "); } } if (!string.IsNullOrEmpty(sbFiltro.ToString())) sbQuery.Append("WHERE ").Append(sbFiltro.ToString()); cmd.CommandText = sbQuery.ToString(); if (filtroUsuario != null) { if (!string.IsNullOrEmpty(filtroUsuario.Login)) { cmd.Parameters.AddWithValue("@Login", filtroUsuario.Login); } if (!string.IsNullOrEmpty(filtroUsuario.Senha)) { cmd.Parameters.AddWithValue("@Senha", filtroUsuario.Senha); } } #endregion
E principalmente criar tudo em uma linha só como se fosse um "linguição". E acredite-me já vi muito disso por ai.
Para finalizar existem muitos preconceitos (conceitos preconcebidos) com relação ao uso de certas abordagens e até acho válido. Agora o que não pode ser é intolerante.E para ser um profissional completo saiba usar as expressões SQL tanto no código, como em SP´s ou mesmo framework de persistência. Você só tem a ganhar.
Qualquer dúvida é só se manifestar.
09/11/2014
Soeuseijothaz
Então vai uma correção:
Onde esta:
"E principalmente criar tudo em uma linha só como se fosse um "linguição". E acredite-me já vi muito disso por ai."
O correto é:
E principalmente NUNCA criar tudo em uma linha só como se fosse um "linguição". E acredite-me já vi muito disso por ai.
09/11/2014
Soeuseijothaz
executa (CommandType.Text, "instrução SQL").
Poderá alguém ajudar com outro assunto: Quando e porquê usar functions?
Já çi sobre isso, mas os comentários aqui são sempre mais construtivos
As funciotns no BD são como as fucntions usadas no código.
São códigos que executam uma tarefe e devolve um o resultado.
Você poderia consistir o CNPJ via funciton SQL:
/* Calculo do Digito Verificador para CNPJ por: Antonio Rodrigues dos Santos Filho - antonio@aikon.com.br Instruções 1- O CPF deve ser passado contendo apenas os numero. Não coloque os '.' e '/' 2- O resultado da função será o Digito Verificador em char(2) Exemplo: declare @dv as char(2) set @dv = dbo.CalculaCNPJ ('123456780001') print @dv obs: Neste caso o DV = 95 qualquer erro, o resultado do DV será -- */ alter function dbo.CalculaCNPJ (@cnpj as varchar(13)) returns char(2) as Begin declare @soma as int, @dv as char(2), @dv1 as int, @dv2 as int, @i as int, @somando as int, @cnpj1 as char(8) set @cnpj1 = substring(@cnpj, 1, 8) set @dv = '--' -- Teste 1. O cpf nao pode ser tudo 1 ou 2 e etc if not (@cnpj1 = '11111111' or @cnpj1 = '22222222' or @cnpj1 = '33333333' or @cnpj1 = '44444444' or @cnpj1 = '55555555' or @cnpj1 = '66666666' or @cnpj1 = '77777777' or @cnpj1 = '88888888' or @cnpj1 = '99999999' or @cnpj1 = '00000000') begin -- Teste 2. Verifica se o cpf tem os 9 digitos preenchidos If rtrim(Len(@cnpj)) = 12 begin --Calcula DV1 (1o Digito Verificador) set @soma = 0 set @somando = 5 set @i = 1 while @i < 5 begin set @soma = @soma + Substring(@cnpj, @i, 1) * @somando set @somando = @somando - 1 set @i = @i +1 end set @somando = 9 set @i = 5 while @i < 13 begin set @soma = @soma + Substring(@cnpj, @i, 1) * @somando set @somando = @somando - 1 set @i = @i +1 end set @dv1 = 11 - (@soma - (@soma/11) * 11) If @dv1 > 9 set @dv1 = 0 -- Calcula DV2 (2o Digito Verificador) set @cnpj = @cnpj + ltrim(str(@dv1)) set @soma = 0 set @somando = 6 set @i = 1 while @i < 6 begin set @soma = @soma + Substring(@cnpj, @i, 1) * @somando set @somando = @somando - 1 set @i = @i +1 end set @somando = 9 set @i = 6 while @i < 14 begin set @soma = @soma + Substring(@cnpj, @i, 1) * @somando set @somando = @somando - 1 set @i = @i +1 end set @dv2 = 11 - (@soma - (@soma/11) * 11) If @dv2 > 9 set @dv2= 0 if @dv1 <> 0 begin set @dv = ltrim(str(@dv1 * 10 + @dv2)) end else begin set @dv = '0' + ltrim(str(@dv2)) end end end return (@dv) end
O código acima é só um exemplo, pois a melhor abordagem é fazer este tipo de tarefa na camada de negócios.
No link tem mais algumas informações.
http://www.linhadecodigo.com.br/artigo/687/sql-server-funcoes-de-usuario-user-functions.aspx
10/11/2014
Clayton Silva
Sobre functions, é recomendável evitar o uso delas no BD, melhor serem feitas na aplicação.
10/11/2014
Soeuseijothaz
Sobre functions, é recomendável evitar o uso delas no BD, melhor serem feitas na aplicação.
Como sempre depende do cenário.
No exemplo que postei foi só ilustrativo e para mostra o poder das functions.
Se for relacionado a regras de negócio deve ficar na aplicação sem dúvidas.
No link que postei existe alguns exemplos de uso que não seira uma heresia.
Veja o exemplo:
CREATE FUNCTION funcionariosApos(@dt datetime) RETURNS TABLE AS RETURN (SELECT * FROM FUNCIONARIO WHERE dataContratacao >= @dt)
Para usar:
SELECT * FROM funcionariosApos('2000-01-01')
No caso esta função podeira ser usada em várias consultas, reaproveitando a mesma.
Agora ser for migrar para outro banco de dados pode dar trabalho.
Então deve ser usada com parcimônia e sempre de forma bem planejada.
11/11/2014
Fernanda Acacia
11/11/2014
Soeuseijothaz
Stored procedures vantagens:
1-fica em cache e a performance é maior
2-menor trafego na rede, pois só passa o nome da sp e parâmetros e não todo a expressão.
3-fica mais organizado.
4-ajuda a manter as estatísticas do servidor o que ajuda na performance como um todo
5-pode ser testada fora da aplicação
6-oferece um controle de grant maior
Stored procedures desvantagens:
1-quando da implantação da aplicação na produção tem-se que gerá-las para o novo server
2-o conteúdo fica encapsulado na sp, então tem-se o trabalho de sempre abri-la para ver o conteúdo
3-é mais um objeto para você se preocupar
Usar SQL no código vantagens:
1-dá atomicidade ao código tudo o que é preciso esta no código visível e a mão
2-fica-se livre da área de dados
3-quando da implantação da aplicação na produção não precisa de se preocupar com atualizar nada no server de bd
Usar SQL no código desvantagens:
1-é mais lento pois além do server ter de ler as instrução tem de fazer o parse
2-pode sobrecarregar a rede pois trafega por ela toda a instrução
13/11/2014
Alex Lekao
O que tiro disso eh que temos mais vantagens em nao utilizar no codigo. rsrsr
Obrigado.
Aprendendo cada dia mais. rsrsr
19/07/2015
Edgard Santos
Já trabalhei em vários projetos e não recomendo utilizar Stored Procedure. Imagine que as consultas estão nas SPs e você precisa migrar do MySql para o Sql Server, e agora? refazer tudo?
Esse é o problema das Stored Procedure.
Para os projetos utilize ORM, NHibernate ou Entity Framework.
Clique aqui para fazer login e interagir na Comunidade :)