Mostrando postagens com marcador sql server. Mostrar todas as postagens
Mostrando postagens com marcador sql server. Mostrar todas as postagens

Problemas de cache no SQL Server

Se você estiver recebendo uma mensagem do tipo:

O SQL Server encontrou %d ocorrência(s) de liberação de armazenamento em cache para o cache '%s' (parte do cache do esquema) devido à manutenção do banco de dados ou operações de reconfiguração.
ou
SQL Server has encountered %d occurrence(s) of cachestore flush for the '%s' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
É porque, segundo a MSDN, ao limpar o cache do plano gera uma recompilação de todos os planos de execução subseqüentes e pode provocar uma queda repentina e temporária no desempenho da consulta. Para cada armazenamento em cache limpo no cache do plano, aparece a mensagem supracitada.

Para resolver isso, basta ir no banco correspondente, clicar com o direito sobre ele e escolher Properties (Propriedades). Entre em Options (Opções) e configure o Auto-Close (Fechamento Automático) para False.

Mega Post de Erros

Lidar com erros é algo realmente muito chato... Chato demais! Esses dias fui convocado para fazer um certo trabalho de migração entre servidores. Um desses servidores era um Cloud Server Pro da Locaweb. Em muitos posts que aqui escrevi tem um pouco retratando sobre a Locaweb. Trabalho e já trabalhei muito com ela e sei de todos os seus passos e "artimanhas" de atendimento... O antigo Cloud Server foi até tranquilo de trabalhar, mas esse novo... Vamos aos problemas!

Uma dica que dou sempre quando alguém quer contratar um servidor: leiam muito sobre os prós e contras. Os prós vejam no próprio site do prestador, os contras vejam nos relatos de usuários. No post a seguir não estou jogando a Locaweb contra a parede, apenas estou expondo erros que podem ser sanados de forma fácil mas que burocraticamente é jogado para o cliente se virar (nos 30!).

Nesse Cloud Server vem embutido o Plesk. Em poucas palavras serve para gerenciar a hospedagem através de uma interface web. É uma boa ferramenta de gerência, tem tudo para gerenciar sua hospedagem. Só que esse demais gera ocupação demais (redundância) de espaço em disco. Dos 50 Gb que você contrata, 40Gb é para o sistema operacional e 10Gb para seus arquivos. Sendo que dos 10Gb é para todos os seus arquivos, e-mails, banco de dados, etc. Ou seja, apenas usufrui dos 10Gb um pouco menos que 9Gb e olhe lá.

Bem, dizem que vem tudo preparado e instalado para usar... Verdade até certa parte! Quem está usando e é iniciante vai ver que é mil maravilhas. Dá para fazer o básico de tudo. O problema vem a seguir...

Um cliente contratou o Cloud Server gerenciado pelo cliente (ou seja, sobrou para o usuário final) e me passou para configurar e deixar no ponto de uso fazendo toda a migração e instalação. Em um passe de mágica surgem os problemas...

Os bancos de dados que vem são o MS SQL Server 2008 e o MySQL. Não há interface para dump e recovery das bases forçando a usar o Plesk para isso, mas não queria. Onde está o Management Studio 2008? Onde está o MySQL Workbench? Como vou fazer para migrar as bases? Gerar script de bancos gigantes? Nem pensar! Preciso instalar!

Mas como instalar esses aplicativos? Se fazer download, gera tráfego. Se pedir para a Locaweb tem que pagar e se pedir, de graça, não instala! Lembrando que esses aplicativos, no mínimo, são gratuitos e deveriam estar em uma zona em que os usuários pudessem obtê-los de forma fácil e sem cobrança. Pois bem, feito o download, hora de instalar. Abrindo o executável (lembrando que tem que ser a da versão 64bits) dá aviso de incompatibilidade. É preciso instalar o Service Pack 1 do SQL Server 2008 (mais tráfego). Baixado o SP1 é preciso instalá-lo. Tranquilo e instalado sem problemas. Hora de instalar o Management Studio...

Ao tentar abrir, outro problema?!?! É preciso do Framework 3.5! Incrivel... No Cloud Server vem instalado a versão 2.0 e 4.0 do Framework ASP.NET mas não tem a 3.5 ativado. Menos mal, porque no Windows Server 2008 é nativo, basta ativar. Realize os seguintes passos (retirado do Wiki):

  1. Clique em Start, Administrative Tools e selecione Server Manager;
  2. Na interface, clique em Features e clique em Add Features;
  3. Selecione a primeira opção .NET Framework 3.5.1 Features e adicione todos seus dependentes;
  4. Conclua a instalação do Framework.

Agora sim, tudo pronto! Vamos instalar o Management Studio. Clica no instalador e... Erro! Caramba... de novo!


TITLE: SQL Server Setup failure.
-------------------------------


SQL Server Setup has encountered the following error:


Invoke or BeginInvoke cannot be called on a control until the window handle has been created.


A dica é: feche o Windows Explorer! Por algum motivo, a instalação do Management Studio não inicia quando o Windows Explorer estiver em aberto. Copie para a Área de Trabalho e abra o instalador... Agora sim! Depois de tanta malemolência pelo menos iniciemos a instalação. Para quem tem dúvidas e um passo-a-passo bem explicativo de como instalar o Management Studio, acesse aqui o post de Marcos dell Antonio. Há uma dica bem interessante que pode confundir o usuário na hora da instalação. Terminado a instalação, menos um item da lista de afazeres.

Consegui conectar ao SQL Server local, criei as bases, usuários, fiz restores, configurei o backup, providenciei tudo o que tinha que fazer onde o Plesk jamais pensaria em um dia ser. Agora o principal, testar um website. Publiquei o site no IIS e abri o navegador para visualizar. Erro!

Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

Sabe o porquê disso? Eu instalei o ASP.NET 3.5 depois que eu já tinha a versão 4.0 instalada por causa do Management Studio então gerou conflito nas DLL's. Para resolver, faça o seguinte:

  1. Vá para a pasta C:\Windows\Microsoft.NET\Framework64\v4.0.30319;
  2. Execute o comando aspnet_regiis.exe -iru


Agora vamos testar! Abri o navegador e digitei o endereço e... Mais erro!

There is a duplicate 'system.web.extensions/scripting/scriptResourceHandler' section defined

Mais conflitos! Se você tiver outra versão do System.Web.Extensions instalado, devido ao ASP.NET AJAX por exemplo, a versão que está no GAC do sistema difere da que você quer chamar ocorrendo ambiguidade. O correto seria alterar os assemblys mas como isso é muito trabalhoso e pode acontecer algum imprevisto para aqueles que não sabem manuseá-las, então aconselho o seguinte: remova toda a sectionGroup do seu web.config ou comente-as:

<!--
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
-->

No caso comentei o sectionGroup do System.Web.Extension que pode estar na versão 1.0, 2.0 ou 3.5 que for.

Agora vamos lá! De pés juntos e mãos dadas: Abre o navegador e... e... e... Funcionou! Depois de um árduo trabalho aparentemente tudo estava normal. Vamos testar outros sites e... e... e... Mais erros!

Quem ainda não está acostumado a trabalhar com Windows Server 2008 e IIS 7 terá que aprender muito sobre permissões e tratamento de erros. Incontestavelmente a tela do erro 500 irá aparecer e muito se sua aplicação não estiver configurada adequadamente para o IIS 7. Nem sempre a mesma aplicação que está no IIS 6 irá funcionar no IIS 7. Então eis que surge a tela do Erro 500 Erro Interno do Servidor ou Error 500 Internal Server Error:




Ou então:


Dá para descobrir o que é? Vou dar a dica: revise seu web.config. "Ah, mas está tudo certo, não sei porque não funciona...". Engano, está errado. Já disse que o IIS 7 é chato, muito chato. O parser dele é muito minucioso e se não estiver nos padrões vai dar problema.

Se você não sabe utilizar bem o IIS e tem medo de alterar uma coisinha ali e outra acolá vou dar a maior dica: saia abrindo cada opção do painel da aplicação até que uma delas acuse um erro de configuração.


Por exemplo, abra o item Documento Padrão. Se ele estiver configurado corretamente então abrirá a próxima tela normalmente. Se tiver algum erro, aparecerá um alerta. Então no web.config você deve corrigir a sessão correspondente. Ficou claro? Saia clicando um a um até que um deles se denuncie podendo então fazer a correção.

O que ocorreu comigo foi que um site que estava no IIS 6 podia colocar a mesma página (index.aspx) como padrão, duas vezes, e não tinha problema. Quando foi para o IIS 7, na qual estava herdando a configuração pai, e foi adicionar a página index.aspx como padrão novamente, ele dava erro e não sabia porquê. Então removi a entrada do web.config e funcionou. Desabilitar a mensagem de erro amigável no navegador vai funcionar (encontrar o erro)? Não. Desabilitar as páginas de erros personalizáveis do IIS vai funcionar (encontrar o erro)? Talvez ou não. Depende muito do ambiente que está configurado e quem está manipulando.

Pronto! Mais um problema solucionado... Vamos testar outro site e... e... e... Erro! Agora aconteceu um erro 404. Mas como? Erro 404 de página não encontrada mas se o caminho está lá? Incrivelmente no IIS do Cloud Server possuem dois Applications Pools do Plesk (e mais outros nativos): Plesk(default)(2.0) e Plesk(default)(4.0). O pool do 2.0 quase nem sempre funciona. E um comportamento anormal é que se você tem um site pai em 2.0 e um filho em 2.0 às vezes pára de funcionar. O "correto" é ter um pai 2.0 ou 4.0 com filho sempre 4.0. Estranho? Pode crer! E onde está o pool do 3.5? Tem que criar na mão mesmo.

Nota: Se você reiniciar o IIS o Plesk pára de vez e não volta:

Você terá que iniciá-lo manualmente. Mas antes terá que iniciar seu pool também (que é muito suspeito):


 Ajeitado uma coisinha ali, outra aqui, vamos testar mais algumas coisas e... e... e... Quase tudo certo. Em questão de funcionalidade (que deveria ser) está quase tudo certo a não ser o funcionamento do bom e velho Crystal Reports. Quem já leu o post de erros do Crystal aqui e aqui nos deparamos com o erro:


O inicializador de tipo de 'CrystalDecisions.CrystalReports.Engine.ReportDocument' acionou uma exceção

ou

The type initializer for 'CrystalDecisions.CrystalReports.Engine.ReportDocument' threw an exception

Cuidado! Esse não é o descritivo do erro. Só com isso não dá para saber o motivo. Faça o debug, log,  exibição da pilha ou na própria tela exiba o erro (sem ter AJAX) que teremos o erro completo. No link dos dois posts anteriores que fiz explica o problema do Crystal na plataforma 64bits e como pode resolver. Só que o problema no meu caso era permissão.


Server Error in '/virtual_directory_name' Application.
Error in File UNKNOWN.RPT:
The request could not be submitted for background processing.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.


Exception Details: System.Runtime.InteropServices.COMException: Error in File UNKNOWN.RPT: The request could not be submitted for background processing.


Os usuários listados abaixo, não tinham permissão na execução de scripts DCOM e gravação em algumas pastas (principalmente as que estão na unidade C):

  • IWAN_plesk(default)
  • IUSR
  • IIS_IUSR
  • NETWORK SERVICE
  • INTERACTIVE

Esses são os usuários que devem ter privilégio (descritos abaixo) nas pastas listadas abaixo:

  • C:\Windows\Temp\ : leitura \ escrita
  • C:\Program Files (x86)\Business Objects\Common\2.8\bin\ : leitura
  • C:\ : leitura

Obs: Para alguns servidores é preciso aplicar o Replace permission entries on all child objects nessas pastas.

Lembrando de reiniciar o IIS e/ou o servidor para recarregar as configurações.

Se estiver trabalhando com Windows Service ou Windows Form e ocorra o erro:


System.IO.FileNotFoundException: Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 8007007e


Basta compilar sua aplicação em x86.

E agora, tudo certo? Até o momento sim. Porque não dizer que está tudo OK? Depois de ter ocorrido todos esses problemas, fica-se receoso com o futuro. Pode ser que ocorra outro problema posteriormente? Sim e irá.

Conforme disse anteriormente, o post não é para dizer mal sobre a Locaweb e/ou Plesk. Acho que eles prestam um serviço adequado para o nível nacional (até uso) contudo são coisas que acontecem que simplesmente poderiam ser sanadas antes de jogar o pepino para o cliente. Se você tiver algum problema desses e sua gerência for pelo cliente, nem adianta pedir que eles vão lhe informar: "o gerenciamento é por conta do cliente e não nos responsabilizamos" ou "a ferramenta (Plesk) é terceirizada e não prestamos suporte.". Enfim, espero que o post ajude a você, cliente e usuário, a corrigir seus problemas/pepinos que ocorrerem. Isso me lembra quando lançou o plug-and-play... a velha piadinha do plug-and-pray (ligar e rezar) não some da cabeça quando ocorre esse tipo de problema. Porque será?

Melhorando o desempenho de consultas (SELECT) em tabelas grandes no SQL SERVER

"Tenho uma tabela com mais de um milhão de registros. Faço uma consulta... um simples SELECT... mas está demorando muito para retornar. O que fazer?"
Essa é a pergunta que você se faz nessa situação. Todo programador sabe trabalhar com banco, mas nem sempre sabemos utilizar da melhor forma. Um DBA já é craque na situação e sabe a melhor forma de melhorar o desempenho de uma consulta. A dica do dia é: índices! Se você não sabe o que são índices, veja essa matéria aqui de Thiago Pastorello que explica de forma bem compreensiva. Também recomendo que leia também esse artigo da Compute-rs onde explica as vantagens e desvantagens de usar índices.

É só isso? Talvez. Se você entedeu o significado de índices lendo os dois artigos (referência) e fez o que irei demonstrar abaixo pode ser que resolva. Na net você irá encontrar outros artigos semelhantes que irão mostrar outros caminhos que podem ajudar melhor. Aqui será de forma simplificada... Vamos?

Abra o Microsoft SQL Server Management Studio, conecte-se a base de dados e clique em New Query. Escreva a consulta que deseja avaliar e corrigir para ficar mais rápida. No meu caso irei executar uma Stored Procedure que contêm várias sub-consultas com manipulação de agrupamento tais como COUNT, SUM, etc. Na barra de ferramentas marque a opção Include Actual Execution Plan (Incluir Plano de Execução Atual).


Agora clique em Execute ou pressione F5 para executar a query e avaliá-la. Aguarde até que finalize completamente. Vá na última aba abaixo de Plano de Execução e veja os resultados.


Passando o mouse por cima de cada item irá ser exibidos detalhes acerca do custo de processamento. Depois procurem ai no Google mais explicações sobre cada item. Mas vamos nos atrelar a essa mensagem verde. Note que o próprio SQL Server informa que há indices ausentes! Vamos criá-los?

Clique com o direito sobre a mensagem e escolha Detalhes de Índices Ausentes.


Ao clicar, irá aparecer outra tela com um query de criação do índice, exemplo:

/*
Detalhes de Índice Ausentes de SQLQuery1.sql - SERVIDOR.Mailing (thiago (53))
O Processador de Consultas estima que a implementação do índice a seguir pode melhorar o custo da consulta em 99.7047%.
*/
/*
USE [Mailing]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[News_Envio] ([id_campanha])
GO
*/
 
A consulta de criação está praticamente pronta bastanto apenas dar um nome para o índice e remover o comentário, deixando da seguinte forma:
 
USE [Mailing]
GO
CREATE NONCLUSTERED INDEX PI_Index_Envio_Campanha
ON [dbo].[News_Envio] ([id_campanha])
GO

Pressione F5 ou Execute esse bloco de instruções para criar o índice. Antes de testarmos, vamos atualizar os índices e suas estatísticas.

Vá na tabela desejada, na opção de Índices e escolha Reorganizar Índices. Veja o nível de fragmentação e dê OK. Em seguida execute:

UPDATE STATISTICS News_Envio

No caso substitua News_Envio pelo nome de sua tabela. Agora execute novamente o primeiro processo e verá um ganho significativo de velocidade de consulta. O que levava 1 minuto para executar, em menos de 1 segundo obtêm-se o resultado. Bom né?

Aprecie com moderação o uso de índices e leiam as referências para saber quais situações onde é vantagem ou não o uso deles.

Exportar Banco de Dados (BAK ou MDF) do SQL Server 2008 para o 2005

A forma mais fácil de transferir um banco para outro é fazer um BAK dele e depois recuperar do outro lado. Do 2005 para o 2008 é possível realizar a recuperação, mas do 2008 para o 2005 não é possível realizar o downgrade. Qual a solução? Gerar o script geral do banco e executá-lo no banco de destino. Mas se meu banco é muito grande, como fazer? A dica está no final do post, mas façamos tudo desde o início.
Abra o SQL Server Management Studio (ou Express) e conecte-se ao Server. Clique com o botão direito sobre a base de dados e siga em Task (Tarefas) e escolha Generate Scritps (Gerar Scripts). Na tela de seleção de base, marque a opção Script all objects in the selected database (Scritp de todos os objetos da base selecionada) e avance. Nessa próxima tela procure os itens abaixo e atribua os seguintes valores:
  1. Script for Server Version (Versão de Script do Server): SQL Server 2005
  2. Script Data (Script de Dados): True
  3. Script USE DATABASE: False
Demais opções fica a seu critério optar... Agora avance e na próxima tela escolha salvar o arquivo em disco com as opções Simples (Single file) e Unicode text. Avance, revise o que foi selecionado e finalize. Aguarde até que o processo seja finalizado. Quando terminado seu script já estará pronto para ser executado no destino.
O próximo passo é executar o script gerado na base de destino. Crie a base de destino vazia e agora temos duas opções:
  • Se o script gerado for pequeno (ou seja base pequena) podemos simplesmente abrir pelo próprio SQL Server Management e executar como se fosse Querys consecutivas;
  • Se o script for grande vamos usar um artifícío para isso.
Como a primeira opção é a mais simples (e também porque gosto de aventurar-me) vamos optar pela segunda (e que também é nossa realidade). No meu exemplo, o script gerado ficou em torno de 1,5Gb. Se desejar reduzir o tamanho um pouco, às vezes, reduzir o log ajuda (saiba como reduzir aqui) antes de gerar o script.
Abra o Prompt de Comando (emulador do DOS no Windows) e digite o seguinte comando:


sqlcmd -U thiago -P blog -S THIAGOMARCAL\SQLEXPRESS -d BaseBlog -i C:\ScriptSQL.sql -o C:\LogExecucao.txt

Explicando os atributos:
  • U: informa o nome do usuário que está conectando (no caso, o usuário thiago);
  • P: informa a senha do usuário (a senha é blog);
  • S: nome do servidor (como está na minha máquina a instância é THIAGOMARCAL\SQLEXPRESS);
  • d: nome da base nova que receberá o resultado do script (BaseBlog é o nome da nova base criada);
  • i: local onde salvei o script de dados e que usarei como entrada;
  • o: arquivo de texto contendo o resultado da operações (log para análise - opcional).
Dê ENTER e aguarde toda a operação ser executada. Para quaisquer tamanho do arquivo ele será processado sem problemas. Se tentasse abrir pelo SQL Server um arquivo muito grande daria erro de alocação de memória, ou demoraria e nem conseguiria executar exibindo alguns dos seguintes erros:
  • Cannot Open Datafile
  • Insufficient memory
  • Out of Memory Exception
Dessa forma é mais tranquilo...

Utilizando função de uma DLL Externa no SQL Server

Esse é um tópico que irá mostrar algo que definitivamente você já precisou mas não sabia como fazer e que facilitará (e muito) alguns trabalhos. Programadores que usam o Bando de Dados para programar sendo por Stored Procedure, Functions e Triggers já passaram por maus bocados para preparar um algoritmo que realizasse um determinado processo, mas que esse mesmo algoritmo é mais fácil de ser escrito (ou possuir funcionalidades que o SGDB não possui) em outra linguagem de programação. Por exemplo: validar e-mail. É possível no SQL Server fazermos um Function que receba um VARCHAR e retorne um BIT informando que um e-mail é válido ou não, contudo seria uma função um tanto que trabalhosa para quem não está familiarizado com programação em banco. Para quem desenvolve em ASP.NET (C# ou VB.NET) basta usarmos expressão regular que, em duas linhas, resolve o problema. Portanto iremos utilizar uma função escrita em C# compilada em uma DLL e usarmos em um Function no SQL Server. Isso é possível através do CLR.
Primeiramente vamos criar a DLL contendo a função (no nosso exemplo vamos fazer a que valida e-mail - mas você pode desenvolver a que quiser). Abra o Visual Studio e crie um Project. Em Project Type escolha Visual C# Windows e o Template opte por uma Class Libary. Note que quando você cria uma classe vem com o nome Class1.cs. Para facilitar a compreensão, renomeie para FuncoesSql.cs (ou outra) e remova o namespace criado. Agora, escreva a função que deseja e adicione os namespaces necessários ficando da seguinte forma:

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Server;

public partial class FuncoesSql
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlBoolean IsMailValido(SqlString email)
    {
        // Cria um objeto de expressões regulares para validar e-mail
        Regex expressaoRegular = new Regex(@"^(([^<>()[\]\\.,;:\s@\""]+"
        + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)(\"".+\""))@"
        + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
        + @"\.[0-9]{1,3}\])(([a-zA-Z\-0-9]+\.)+"
        + @"[a-zA-Z]{2,}))$");

        // Realiza um teste na validação da expressão
        return new SqlBoolean(expressaoRegular.IsMatch(email.ToString()));
    }
}

No caso, precisamos explicitar os tipos de entrada e saída utilizados pelo banco de dados para que não haja problemas de tipagem. Poderia ser qualquer função ou quantas que quisesse, contanto que respeite os tipos. Agora compile a DLL pressionando F6 ou pelo menu Build. Já temos a DLL com a função. Copie a DLL (que está na pasta bin\Debug de sua solução) e coloque-a em um local onde seu Banco de Dados possa buscá-la. Para exemplo, colocarei em C:\SqlDlls\ no Servidor.
O próximo passo é verificar se no SQL Server está ativo a funcionalidade CLR, para isso vá em Iniciar > Todos os Programas > Microsft SQL Server 2008 (ou 2005) > Configuration Tools > SQL Server Surface Area Configuration. Entre em Surface Area Configuration for Features e na guia CLR Integration verifique se a função está habilitada. Se não estiver, habilite.


Dê OK e agora já poderá usar CLR no SQL Server. Abra o SQL Server Management Studio, conecte-se na base desejada e execute as seguintes instruções SQL (abra um New Query para isso):

-- CRIA O ASSEMBLY INDICANDO SUA ORIGEM
CREATE ASSEMBLY FuncoesSql FROM 'C:\SqlDlls\FuncoesSqlServerASPNET.dll'
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- CRIA A FUNÇÃO
CREATE FUNCTION dbo.Fun_Valida_Mail (@email NVARCHAR(350))
RETURNS BIT
-- INDICA A ORIGEM DA FUNÇÃO SQL: ASSEMBLY > CLASSE > FUNÇÃO
AS EXTERNAL NAME [FuncoesSql].FuncoesSql.IsMailValido
GO

Agora execute a Query (ou pressione F5)... Foi criada a função! Pronto... agora é só usar como se fosse uam função do SQL Server normalmente. Abaixo tem alguns exemplos de consulta e seus retornos:

Execuções:
SELECT dbo.Fun_Valida_Mail('tmarcal@gmail')
SELECT dbo.Fun_Valida_Mail('tmarcal@gmail.com')
SELECT dbo.Fun_Valida_Mail('tmarcal.. @gmail.com')
 
Retorno:
0
1
0
 
Apesar do trabalho inicial, pode-se aproveitar muito de ambos os recursos e criar cada vez mais funções complexas. Quanto ao desempenho da CLR, em comparação ao T-SQL, deve-se ficar a mesma coisa. A diferença é praticamente imperceptível. Espero que tenham gostado... Até breve!

Dicas de Instruções SQL para facilitar o uso no dia-a-dia

Bom, abaixo separei algumas instruções SQL que muitos programadores tem dúvidas de como usá-las e que facilitam muitas tarefas.

1) INSERT de SELECT: Fazer inserções em uma tabela puxando dados de outra(s)

Bem parecido com o SELECT INTO porém você pode fazer várias manipulações conforme desejar usando um simples SELECT. No caso vou mostrar um exemplo bem fácil: irei adicionar vários Alunos numa tabela sendo que os dados estão em outra tabela (Cadastros), logo minha instrução ficaria assim:

INSERT INTO Alunos (nome, email) SELECT nome, email FROM Cadastros

O nome dos campos não precisam serem iguais, basta estar na mesma ordem e respeitar o tipo de dados (tamanho também).

2) UPDATE relacionado com outra tabela

Nessa situação o que desejamos é fazer um UPDATE na tabela sendo que é preciso fazer um JOIN com outra tabela. No nosso exemplo: desejamos alterar o preco de um produto sendo que o valor do mesmo está relacionado com seu tipo e ele está armazenado em outra tabela. Logo podemos usar a seguinte instrução:

UPDATE Produto SET preco = T.preco FROM Produto AS P, Tipo AS T WHERE P.Id_Tipo = T.Id

Meio complicado quando se vê, né? Mas se você reparar detalhadamente verá que a atualização do preço é feita, para cada produto, quando o Id_Tipo (da tabela Produto) for igual ao Id (da tabela Tipo) obtendo assim o preco (da tabela Tipo).

3) Remover registros duplicados deixando apenas um

A explicação desse objetivo é bem óbvia: remover registros duplicados em uma determinada tabela sob,algum critério. Porém, sua sintaxe é mais complicada, mas vamos lá... Para nosso exemplo iremos remover os registros duplicados (ou mais que um) de e-mails deixando apenas um na tabela Mailing:

;WITH Listagem(email, ranking)
AS
(
SELECT email
,ranking = DENSE_RANK() OVER(PARTITION BY email ORDER BY NEWID() ASC)
FROM Mailing WITH (NOLOCK) WHERE email IS NOT NULL 
)
DELETE Listagem WHERE ranking > 1

Esse emaranhado de instruções se resume em gerar um ranking indicando quantas vezes o registro se repete. Esse ranking é armazenado em uma tabela "temporária" (tabela Listagem) com referência à original (tabela Mailing)... Logo que é gerado o ranking, é feita a exclusão dos registros que possuem ranking maior que 1, ou seja, apaga todos aqueles que estão se repetindo deixando apenas um deles.

Bem, é isso! Espero ter ajudado... Lembrando que os exemplos acima foram os mais simples e vocês podem encontrar situações semelhantes ou piores mas que, usando-os, podem ajudar a chegar na resolução.

Problema no uso de memória no SQL Server 2008

Se em algum momento, quando em trabalho, estiver recebendo uma das seguintes mensagens abaixo, você está tendo sérios problemas de uso de memória:

"There is insufficient system memory in resource pool 'internal' to run this query" *

ou

"Há memória de sistema insuficiente no pool de recursos internos para executar essa consulta" *

Isso ocorre quando há várias instruções SQL sendo executadas em seqüência. Como o pool não aguenta, os dados, em algumas vezes, podem travar... Mesmo que fisicamente eles estejam lá, não se pode mais ser utilizados até que o banco seja reiniciado. Para corrigir esse problema há duas formas: instalar o hotfix que a Microsoft disponibilizou ou reduzir quantidade de instruções a serem executadas por vez.

1) Instalar o HotFix

O arquivo está disponível em um pack cumulativo pós SP1 do SQL Server 2008. Para mais informações e download, clique aqui.

2) Reduzir a quantidade de instruções SQL

Fazendo um teste de vários UPDATE's seguidos, consegui obter tal erro. Gerei um arquivo .sql com quase 100mil updates e mandei o SQL Server executar, daí obtive o erro. Nunca tente isso! Se desejar executar vários UPDATE's ou INSERT's de vez fragmente a execução das instruções em blocos (nem tão grandes e nem tão pequenos) dando uma pausa entre as execuções. Pode-se utilizar uma Store Procedure buscando os dados em um tabela temporária e executar a instrução de forma genérica (INSERT com SELECT, por exemplo). Também pode-se usar um artifício do ASP.NET, Batch Update, para executar a instrução de forma genérica com alto desempenho.

* A depender da configuração do SQL Server, ao invés de ser o recurso interno (ou internal) pode ser o recurso default.

Reduzir Log SQL Server

Nesse primeiro post sobre SQL Server vou explicar como reduzir o log do SQL Server 2005 e 2008. No log contêm as instruções que foram executadas ultimamente no banco de dados. Para quem trabalha com recuperação em log pode preferir manter o log por algum período antes de fazer uma redução. Mas para outros bancos de dados que realizam inserções e atualizações constantes pode ficar inviável manter o log por grandes períodos devido a prover um crescimento exarcebado. Bem isso você pode ver melhor a depender da política de backup que você for utilizar. Considerando que o log para você não tem importância de mantê-lo por muito tempo e não quer mexer nas configurações no SQL Server, essa é uma boa dica de fazer a redução através de comandos SQL.

Pelo próprio SQL Server Management Studio você pode utilizar da função Shrink e fazer a redução do banco de dados e log. Muitas vezes a redução (vamos nos atentar ao do log) chega a ser pouca pois ele mantêm ainda algumas das instruções mais recentes. Mas para forçosamente realizar a redução execute a seguinte intrução:

SQL Server 2005
USE Banco_Dados
GO
BACKUP LOG Banco_Dados WITH TRUNCATE_ONLY
DBCC SHRINKFILE (Banco_Dados_log, 1)

SQL Server 2008
USE Banco_Dados;
GO
ALTER DATABASE Banco_Dados
SET RECOVERY SIMPLE;
GO
DBCC SHRINKFILE (Banco_Dados_Log, 1);
GO
ALTER DATABASE Banco_Dados
SET RECOVERY FULL;
GO
 
Ambos os procedimentos fazem com que o log seja reduzido a 1Mb. Nota-se que a instrução de redução é a mesma. A única diferença é que para realizar a trucamento, no 2005 é preciso informar que o backup de log será truncado explicitamente e no 2008 deve mudar o status para recuperação simples antes de truncá-lo. Se quiser realizar o truncamento automático de todos os bancos do servidor basta fazer um SELECT com cursor sobre todos os bancos pegando o name deles e executando o script acima. Mas isso deixarei para mostrar outro dia...