<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Thiago Zavaschi R2 &#187; Tutorial</title>
	<atom:link href="http://zavaschi.com/index.php/category/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://zavaschi.com</link>
	<description>www.zavaschi.com</description>
	<lastBuildDate>Mon, 02 Jan 2012 16:51:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Instalando o PowerPivot for SharePoint CTP3 (November CTP)</title>
		<link>http://zavaschi.com/index.php/2010/03/instalando-o-powerpivot-for-sharepoint-ctp3-november-ctp/</link>
		<comments>http://zavaschi.com/index.php/2010/03/instalando-o-powerpivot-for-sharepoint-ctp3-november-ctp/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 00:16:24 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[PowerPifot for SharePoint]]></category>
		<category><![CDATA[PowerPivot]]></category>

		<guid isPermaLink="false">http://zavaschi.com/index.php/2010/03/instalando-o-powerpivot-for-sharepoint-ctp3-november-ctp/</guid>
		<description><![CDATA[Olá pessoal,
Sei que no meu post anterior (http://zavaschi.com/index.php/2010/03/powerpivot-mltiplas-fontes-de-dados/) falei que o próximo artigo da série seria sobre DAX (Data Analysis eXpressions), mas recentemente tive uma série de problemas para instalar o PowerPivot for SharePoint, o que é compreensível visto que é um CTP (beta) e a base de dados utilizada (SQL Server 2008 R2) também [...]]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal,</p>
<p>Sei que no meu post anterior (<a title="http://zavaschi.com/index.php/2010/03/powerpivot-mltiplas-fontes-de-dados/" href="http://zavaschi.com/index.php/2010/03/powerpivot-mltiplas-fontes-de-dados/">http://zavaschi.com/index.php/2010/03/powerpivot-mltiplas-fontes-de-dados/</a>) falei que o próximo artigo da série seria sobre DAX (Data Analysis eXpressions), mas recentemente tive uma série de problemas para instalar o PowerPivot for SharePoint, o que é compreensível visto que é um CTP (beta) e a base de dados utilizada (SQL Server 2008 R2) também é CTP, então decidi blogar sobre!</p>
<p>Esta instalação é para propósitos de demonstrações e testes, para cenários de produção haverão outras coisas para se atentar. O cenário que utilizei para iniciar a instalação foi:</p>
<p>Utilizei o Virtualbox para a construção da VM, pois necessitava de uma VM x64 e não tinha como utilizar o Hyper-V.</p>
<p>Windows Server 2008 R2 Enterprise x64, com o papel de domain control (controladora de domínio). Em um ambiente de produção você NÃO DEVE utilizar o servidor de domain control para isto. Vocês verão que pela máquina ser controladora de domínio tem uma série de passos/preocupações que devemos ter para garantir a instalação com sucesso.</p>
<p>Este artigo, em grande parte, é uma tradução/baseado do/no artigo escrito pelo Vidas (@VidasM – <a href="http://www.powerpivot-info.com">www.powerpivot-info.com</a>). Apenas adicionei alguns detalhes relativos ao meu caso e removi algumas coisas para simplicar. O cenário da instalação descrito pelo Vidas é muito similar ao meu. Utilizei o guia dele para alguns apectos dos workarounds necessários.</p>
<p>Fonte em inglês: <a title="http://powerpivot-info.com/post/66-step-by-step-guide-on-installing-powerpivot-for-sharepoint" href="http://powerpivot-info.com/post/66-step-by-step-guide-on-installing-powerpivot-for-sharepoint">http://powerpivot-info.com/post/66-step-by-step-guide-on-installing-powerpivot-for-sharepoint</a></p>
<p><strong><em>Este é um guia para a instalação do produto BETA! Na versão RTM será bem mais tranquilo, e claro, postarei um passo a passo para vocês também!</em></strong></p>
<p><strong>Instalação do SharePoint Server 2010</strong></p>
<p>Além de colocar a máquina como domain control, habilite no servidor a feature “Desktop Experience” (&quot;Server Manage&quot;-&gt;&quot;Features&quot;-&gt;&quot;Add Feature&quot;), para habilitar o servidor a trabalhar como uma <a href="http://blogs.msdn.com/boduff/archive/2009/11/15/data-connection-libraries-missing-in-sharepoint-2010.aspx">estação de trabalho</a>.</p>
<p>A sua conta de login deve ser administradora do domínio!</p>
<p>NÃO INSTALE o SQL Server 2008 R2 ainda, você fará isso em um passo mais adiante.</p>
<p>Antes de instalar o SharePoint, você deve instalar os pré-requisitos.</p>
<p>O único problema que tive neste ponto foi que o Microsoft Chart Controls for Microsoft .NET Framework 3.5 não conseguiu ser baixado sozinho. Baixei e instalei separadamente. <a title="http://www.microsoft.com/downloads/details.aspx?FamilyId=130F7986-BF49-4FE5-9CA8-910AE6EA442C&amp;displaylang=en" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=130F7986-BF49-4FE5-9CA8-910AE6EA442C&amp;displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyId=130F7986-BF49-4FE5-9CA8-910AE6EA442C&amp;displaylang=en</a></p>
<p>Caso encontre outros problemas, terá que fazer a instalação manual dos pré-requisitos.</p>
<p>Observações: Se você tiver o PowerShell 1.0 instalado na máquina você terá problemas. Você terá que remover o PowerShell1.0 manualmente (isto não se aplica ao PowerShell 2.0).</p>
<p>Instale um hotfix WCF</p>
<ul>
<li>Windows 2008 e Vista:      <br /><a href="http://support.microsoft.com/kb/971831">http://support.microsoft.com/kb/971831</a> (this is the KB article)       <br /><a href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=KB971831&amp;DownloadId=7285">http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=KB971831&amp;DownloadId=7285</a> (this is the download) </li>
<li>Para Windows Server 2008 R2 e Windows 7      <br /><a href="https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=23806&amp;wa=wsignin1.0">https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=23806&amp;wa=wsignin1.0</a> </li>
</ul>
<p>Se a sua máquina for controladora de domínio (como a minha) você terá qeu rodar o seguinte script em PowerShell para ativar soluções sandbox.    <br />Observação: O script foi escrito por <a href="http://blogs.msdn.com/opal/archive/2009/11/16/installation-notice-for-sharepoint-2010-public-beta.aspx" target="_blank">Jie Li e foi copiado daqui</a>.</p>
<p>Crie um arquivo de texto chamado sp.ps1 e coloque dentro dele:    </p>
<p>$acl = Get-Acl HKLM:\System\CurrentControlSet\Control\ComputerName    <br />$person = [System.Security.Principal.NTAccount]&quot;Users&quot;     <br />$access = [System.Security.AccessControl.RegistryRights]::FullControl     <br />$inheritance = [System.Security.AccessControl.InheritanceFlags]&quot;ContainerInherit,ObjectInherit&quot;     <br />$propagation = [System.Security.AccessControl.PropagationFlags]::None     <br />$type = [System.Security.AccessControl.AccessControlType]::Allow     <br />$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person, $access,$inheritance, $propagation, $type)     <br />$acl.AddAccessRule($rule)     <br />Set-Acl HKLM:\System\CurrentControlSet\Control\ComputerName $acl</p>
<p>Para executar o script:</p>
<p>1) copy script to file sp.ps1    <br />2) in command line enter &quot;PowerShell&quot;     <br />3) enter &quot;Set-executionpolicy unrestricted&quot; (without double quotes)     <br />4) enter &quot;C:\Scripts\sp.ps1&quot; (without double quotes)     <br />5) enter &quot;Set-executionpolicy restricted&quot; (without double quotes)     <br />6) enter &quot;Exit&quot; (without double quotes)</p>
<p><em>Inicie a instalação do SharePoint 2010.</em></p>
<p>Cuidado: É muito importante que você siga estas opções de configuração. Caso contrário você não conseguirá configurar para o PowerPivot for SharePoint em passos futuros.ê esteja instalando tudo em um único servidor (Standalone) você <strong>não</strong> deve selecionar a opção standalone.</p>
<p>Na próxima janela em server type, escolha a opção <strong>Complete - Install all components. Can add servers to form a SharePoint farm&quot;.</strong></p>
<p>Termine de instalar o SharePoint, e após isto na janela que aparecer (“Run configuration Wizard”) <strong>desmarque</strong> a opção “Run the SharePoint Products and Technologies Configuration Wizard now&quot;” e clique em close.</p>
<p><strong>Instalando o SQL Server 2008 R2 November CTP</strong></p>
<p>Agora é hora de configurar o PowerPivot e isto é feito através da instalação do SQL Server 2008 R2.</p>
<p>Inicie a instalação do SQL Server e na parte de “Setup Role” escolha: <strong>&quot;Analysis Services with SharePoint Integration&quot; </strong>e para a opção &quot;Add Gemini service to:&quot; escolha <strong>&quot;New farm&quot;</strong>.</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2010/03/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://zavaschi.com/wp-content/uploads/2010/03/image_thumb.png" width="526" height="396" /></a> </p>
<p>Na janela de &quot;New SharePoint Farm Configuration&quot; especifique os dados pedidos.</p>
<p>No meu caso utilizei a mesma conta que estou usando. Não é o método mais seguro, mas como eu disse, é apenas para efeitos de demonstração e teste.</p>
<p>Nas próximas janelas preencha os dados conforme requeridos e se coloque como administrador e outros usuários conforme necessário. E inicie a instalação propriamente dita.</p>
<p>Se o seu controlador de domínio (domain controler) é outra máquina então estará tudo praticamente pronto. Caso contrário você <strong>DEVE</strong> seguir os passos abaixo:</p>
<p>Durante a instalação propriamente dita do Analysis Services (geminibi) abra o gerenciador de serviços (services.msc).</p>
<p>Durante a instalação ele trocará a conta que vai subir o serviço do Analysis Services para “Local system account”. Isto ocasionará um erro de timeout. Então quando a instalação chegar aproximadamente neste ponto (ver figura abaixo), troque a conta de serviço para a correta e reinicie(referência em inglês: <a title="http://powerpivotgeek.com/2009/11/17/installing-powerpivot-for-sharepoint-on-a-domain-controller/" href="http://powerpivotgeek.com/2009/11/17/installing-powerpivot-for-sharepoint-on-a-domain-controller/">http://powerpivotgeek.com/2009/11/17/installing-powerpivot-for-sharepoint-on-a-domain-controller/)</a>.</p>
<p>Sim, você deve ficar dando refresh na lista o tempo inteiro até o serviço aparecer e ocorrer a mudança. Lembre-se, é um produto beta.</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2010/03/image1.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://zavaschi.com/wp-content/uploads/2010/03/image_thumb1.png" width="527" height="397" /></a> </p>
<p><a href="http://zavaschi.com/wp-content/uploads/2010/03/image2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://zavaschi.com/wp-content/uploads/2010/03/image_thumb2.png" width="449" height="154" /></a> </p>
<p>Depois de você mudar o serviço, reinicie-o e deixe o setup do SQL Server terminar.</p>
<p><em>Observação: Na minha máquina virtual levou cerca de 45 minutos neste passo final até que a instalação fizesse a troca das contas e desligasse o serviço. A isntalação do SQL Server levou uma hora ao todo.</em></p>
<p>A instalação foi feita com sucesso. Já pode acessar o SharePoint pelo nome da sua maquina (<a href="http://maquina/">http://maquina/</a>). :)</p>
<p>Agora configure seu SharePoint da maneira que preferir. :)</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2010/03/createpowerpivotsite.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="create powerpivot site" border="0" alt="create powerpivot site" src="http://zavaschi.com/wp-content/uploads/2010/03/createpowerpivotsite_thumb.png" width="543" height="353" /></a> </p>
<p><a href="http://zavaschi.com/wp-content/uploads/2010/03/image3.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://zavaschi.com/wp-content/uploads/2010/03/image_thumb3.png" width="544" height="433" /></a> </p>
<p>Próximos post relacionados a PowerPivot (não necessariamente nesta ordem):</p>
<ol>
<li>DAX </li>
<li>PowerPivot for SharePoint problemas conehcidos (CTP3) </li>
<li>Deploy dos reports no PowerPivot for SharePoint </li>
</ol>
<p>Por hoje é isto!</p>
<p>Abraços a todos!!    <br />Thiago Zavaschi</p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2010/03/instalando-o-powerpivot-for-sharepoint-ctp3-november-ctp/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Prevendo o crescimento da suas databases com o SQL Server Data Mining Add-ins for Microsoft Office 2007 &#8211; Parte I</title>
		<link>http://zavaschi.com/index.php/2010/01/prevendo-o-crescimento-da-suas-databases-com-o-sql-server-data-mining-add-ins-for-microsoft-office-2007-parte-i/</link>
		<comments>http://zavaschi.com/index.php/2010/01/prevendo-o-crescimento-da-suas-databases-com-o-sql-server-data-mining-add-ins-for-microsoft-office-2007-parte-i/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 14:19:17 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[Data Mining]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Office 2007]]></category>

		<guid isPermaLink="false">http://zavaschi.com/index.php/2010/01/prevendo-o-crescimento-da-suas-databases-com-o-sql-server-data-mining-add-ins-for-microsoft-office-2007-parte-i/</guid>
		<description><![CDATA[Olá pessoal,
O artigo de hoje é a base de um dos itens/indicadores utilizados nas suas análises de health check dos servidores SQL Server: Verificar o crescimento dos seus arquivos de base de dados e log.
Antes de mais nada vamos revisar um ponto importante quanto ao crescimento das databases:
É muito comum encontrar em servidores configurações como: [...]]]></description>
			<content:encoded><![CDATA[<p align="justify">Olá pessoal,</p>
<p align="justify">O artigo de hoje é a base de um dos itens/indicadores utilizados nas suas análises de health check dos servidores SQL Server: Verificar o crescimento dos seus arquivos de base de dados e log.</p>
<p align="justify">Antes de mais nada vamos revisar um ponto importante quanto ao crescimento das databases:</p>
<p align="justify">É muito comum encontrar em servidores configurações como: crescimento proporcional 10% para a base e para o arquivo de log e com irrestrito por exemplo. A imagem a seguir mostra onde visualizar estas informações.</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2010/01/img1.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="img1" border="0" alt="img1" src="http://zavaschi.com/wp-content/uploads/2010/01/img1_thumb.png" width="477" height="144" /></a> </p>
<p align="justify"><em>Em que isso impacta?</em> Valores pequenos de taxas de crescimento para bases que crescem muito é extremamente prejudicial, pois teremos <em>altas taxas (overhead) de I/O</em> para o crescimento dos arquivos. Por outro lado, valores muito grandes podem gerar um uso descontrolado dos seus discos.</p>
<p align="justify">Em um mundo/cenário ideal os crescimentos das databases são monitorados e o aumento físico dos mesmos são planejados e executados de maneira manual. Claro que pela comodidade, é difícil DBAs optarem por esta abordagem.</p>
<p align="justify">Mas e como monitorar, ou melhor, prever o crescimento, já que muitos DBAs deixam essas configurações automáticas? Uma das maneiras que eu acho muito elegante é através da utilização do Add-in para o Office 2007, mais especificamente a opção <em>Forecast</em>.</p>
<p align="justify">O conteúdo deste post pode ser adaptado para fazer outras previsões através do Office!</p>
<p><strong>O que preciso para começar?</strong>&#160;</p>
<p><em>“Então Thiago, o que eu preciso para iniciar?”</em></p>
<p>Será necessário basicamente:</p>
<p><strong>Microsoft Office Excel 2007; </strong><em>(a princípio não funciona no Office 2010 beta, mas estou verificando se há algum meio).</em></p>
<p>E um dos pares abaixo:</p>
<p><strong>SQL Server Analysis Service 2008;      <br />Data Mining Add-Ins for Office 2007 (SQL 2008);       <br /></strong><a title="http://www.microsoft.com/downloads/details.aspx?familyid=AF070F2C-46F4-47B6-B7BF-48979B999AEB&amp;displaylang=en" href="http://www.microsoft.com/downloads/details.aspx?familyid=AF070F2C-46F4-47B6-B7BF-48979B999AEB&amp;displaylang=en">http://www.microsoft.com/downloads/details.aspx?familyid=AF070F2C-46F4-47B6-B7BF-48979B999AEB&amp;displaylang=en</a></p>
<p>OU</p>
<p><strong>SQL Server Analysis Service 2005;      <br />Data Mining Add-Ins for Office 2007 (SQL 2005);       <br /></strong><a title="http://www.microsoft.com/downloads/details.aspx?familyid=7C76E8DF-8674-4C3B-A99B-55B17F3C4C51&amp;displaylang=en" href="http://www.microsoft.com/downloads/details.aspx?familyid=7C76E8DF-8674-4C3B-A99B-55B17F3C4C51&amp;displaylang=en">http://www.microsoft.com/downloads/details.aspx?familyid=7C76E8DF-8674-4C3B-A99B-55B17F3C4C51&amp;displaylang=en</a></p>
<p><em>Mãos a obra!</em></p>
<p><strong>Coletando os dados de tamanho das databases</strong></p>
<p align="justify">O primeiro passo é definir um mecanismo para a coleta dos dados.</p>
<p align="justify">Para isso vamos criar uma tabela que armazenará os dados relativos ao tamanho dos arquivos. Essa tabela poderá ter variações para outros fins, mas manterei ela com um certo grau de simplicidade.</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:a858288f-d639-40f8-8344-359173516c0b" class="wlWriterSmartContent">
<pre style="background-color: whitesmoke; overflow: auto"><span style="color: #0000ff">CREATE</span><span style="color: #000000"> </span><span style="color: #0000ff">TABLE</span><span style="color: #000000"> TamanhoBaseHistorico
(
    id </span><span style="color: #0000ff">INT</span><span style="color: #000000"> </span><span style="color: #0000ff">PRIMARY</span><span style="color: #000000"> </span><span style="color: #0000ff">KEY</span><span style="color: #000000"> </span><span style="color: #ff00ff">IDENTITY</span><span style="color: #000000">,
    nome </span><span style="color: #0000ff">varchar</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">128</span><span style="color: #000000">) </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">, </span><span style="color: #008080">--</span><span style="color: #008080"> nome da base</span><span style="color: #008080">
</span><span style="color: #000000">    nome_fisico </span><span style="color: #0000ff">VARCHAR</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">2000</span><span style="color: #000000">) </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">, </span><span style="color: #008080">--</span><span style="color: #008080"> nome físico do arquivo, com diretório</span><span style="color: #008080">
</span><span style="color: #000000">    tamanho </span><span style="color: #0000ff">INT</span><span style="color: #000000"> </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">, </span><span style="color: #008080">--</span><span style="color: #008080"> tamanho do arquivo em Kb</span><span style="color: #008080">
</span><span style="color: #000000">    dblog </span><span style="color: #0000ff">BIT</span><span style="color: #000000"> </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000">, </span><span style="color: #008080">--</span><span style="color: #008080"> se o arquivo é de log</span><span style="color: #008080">
</span><span style="color: #000000">    data </span><span style="color: #0000ff">DATETIME</span><span style="color: #000000"> </span><span style="color: #808080">NOT</span><span style="color: #000000"> </span><span style="color: #0000ff">NULL</span><span style="color: #000000"> </span><span style="color: #008080">--</span><span style="color: #008080"> data da medição</span><span style="color: #008080">
</span><span style="color: #000000">)
</span><span style="color: #0000ff">GO</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p align="justify">De tempos em tempos algum mecanismo deverá coletar os dados necessários e inserí-los nesta tabela.</p>
<p align="justify">Entre outras formas (como por exemplo o powershell), podemos fazer uso da system stored procedure chamada <em>sp_msforeachdb </em>e associar a execução da mesma a um job do banco de dados.</p>
<p align="justify">Essa stored procedure executa um comando para cada database, substituindo a “tag” <em>[?]</em> pelo nome da base. As informações virão da system view chamada <em>sys.database_files</em>.</p>
<p align="justify">O comando que será agendado como um job no SQL Server Agent será, para o nosso caso, o seguinte:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:422841b8-10e4-4a45-b1bd-5e59affab4cb" class="wlWriterSmartContent">
<pre style="background-color: whitesmoke; overflow: auto"><span style="color: #0000ff">EXECUTE</span><span style="color: #000000"> sp_msforeachdb
        </span><span style="color: #ff0000">'</span><span style="color: #ff0000">INSERT INTO TamanhoBaseHistorico
        SELECT name, physical_name, size, type, GETDATE()
        FROM [?].sys.database_files</span><span style="color: #ff0000">'</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>&#160;</p>
<p>Não vou entrar nos méritos da criação de jobs no Agent, mas vamos assumir que estes dados sejam carregados todos os meses, uma vez por mês.</p>
<p><em>Na próxima parte veremos o processo de instalação do add-in e a utilização do mesmo!</em></p>
<p>Abraços,<br />
  <br />Thiago Zavaschi</p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2010/01/prevendo-o-crescimento-da-suas-databases-com-o-sql-server-data-mining-add-ins-for-microsoft-office-2007-parte-i/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Novidades do SQL Server 2008 R2 &#8211; Parte III &#8211; Iniciando com o PowerPivot for Excel 2010</title>
		<link>http://zavaschi.com/index.php/2009/12/novidades-do-sql-server-2008-r2-parte-iii-iniciando-com-o-powerpivot-for-excel-2010/</link>
		<comments>http://zavaschi.com/index.php/2009/12/novidades-do-sql-server-2008-r2-parte-iii-iniciando-com-o-powerpivot-for-excel-2010/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 02:00:55 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[SQL Server 2008 R2]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Novidades]]></category>
		<category><![CDATA[PowerPivot]]></category>

		<guid isPermaLink="false">http://zavaschi.com/index.php/2009/12/novidades-do-sql-server-2008-r2-parte-iii-iniciando-com-o-powerpivot-for-excel-2010/</guid>
		<description><![CDATA[Olá pessoal,
No artigo anterior (http://zavaschi.com/index.php/2009/11/novidades-do-sql-server-2008-r2-parte-ii-powerpivot-conceitos/) eu introduzi os conceitos relacionados ao self-service BI, mais precisamente os relacionados ao PowerPivot. Consulte-os quando surgirem dúvidas. :)
Apenas lembrando, PowerPivot é uma grande promessa de Self-Service BI real da Microsoft (“Mas e o Report Builder?” - Calma, depois comento sobre ele), anteriormente era conhecido como projeto Gemini. E ele [...]]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal,</p>
<p align="justify">No artigo anterior (<a title="http://zavaschi.com/index.php/2009/11/novidades-do-sql-server-2008-r2-parte-ii-powerpivot-conceitos/" href="http://zavaschi.com/index.php/2009/11/novidades-do-sql-server-2008-r2-parte-ii-powerpivot-conceitos/">http://zavaschi.com/index.php/2009/11/novidades-do-sql-server-2008-r2-parte-ii-powerpivot-conceitos/</a>) eu introduzi os conceitos relacionados ao self-service BI, mais precisamente os relacionados ao PowerPivot. Consulte-os quando surgirem dúvidas. :)</p>
<p align="justify">Apenas lembrando, PowerPivot é uma grande promessa de Self-Service BI real da Microsoft (<em>“Mas e o Report Builder?”</em> - <em>Calma, depois comento sobre ele</em>), anteriormente era conhecido como projeto Gemini. E ele é divido basicamente em PowerPivot for Excel 2010 e PowerPivot for SharePoint 2010.</p>
<p align="justify"><a href="http://zavaschi.com/wp-content/uploads/2009/12/PowerPivot_2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="PowerPivot_2" border="0" alt="PowerPivot_2" src="http://zavaschi.com/wp-content/uploads/2009/12/PowerPivot_2_thumb.png" width="242" height="244" /></a></p>
<p align="justify">O PowerPivot for Excel 2010, como veremos, é muito simples de usar e possui poderosa capacidade de análise.</p>
<p align="justify"><em>“Ok Thiago, este nome significa que nós o usaremos de dentro do Excel 2010, certo? O quão rápida essa solução é?” </em></p>
<p align="justify">Sim, o uso (composição da análise) será de dentro do Microsoft Excel 2010. Isto é devido ao fato de que o Excel é a ferramenta mais usada e familiar para as pessoas que usualmente tomam as decisões ou que fazem análise. Isso já ocorre atualmente com o uso de tabelas dinâmicas associadas a cubos do Analysis Services, ou através dos plugins de Data Mining para o Excel. Nós normalmente temos uma quantidade muito grande de dados para analizar, oq ue pode ser um processo caro computacionalmente se não for otimizado, mas com o novo PowerPivot for Excel nós podemos analisar grandes quantidades de dados de uam forma bem rápida.</p>
<p align="justify">Aqui cabem algumas ressalvas: o comportamento em ambientes cuja arquitetura é x64 é melhor que x86 para trabalhar com o PowerPivot (desempenho). O PowerPivot faz operações em memória então pode ser necessário um hardware que acompanhe, porém como eu disse, ele está otimizado e consegue trabalhar com enorme quantidade de dados (dezenas de milhões de linhas) fácil e rapidamente.</p>
<p align="justify">O PowerPivot é muito mais poderoso do que simplesmente utilizar tabelas dinâmicas com cubos SSAS (na série de artigos que estou iniciando sobre PowerPivot veremos com detalhes todo o poder disponível). A análise gerada pelo Excel pode ser publicada no SharePoint 2010 e assim ter esses dados disponíveis a todos (entenda-se todos como aqueles que possuem permissões para acessar essa área no SharePoint).</p>
<p align="justify">O que você pode estar pensado é que a planilha com a análise uma vez no servidor pode ficar vulnerável e desatualizada. Ou você pode estar pensando neste exato momente “Ih.. é mesmo, então o PowerPivot não é legal, certo?!”.. <strong>ERRADO!!! </strong></p>
<p align="justify">Você pode fazer (agendar) com que a planilha se atualize sozinha no servidor, além de ter o Excel Services (componente do SharePoint 2010) que torna possível fazer pequenas alterações na planilha para visualização momentânea (mas considere a planilha como sendo sempre read-only, após publicada, isso garante a consistência dos dados).</p>
<p align="justify">Mas a integração com o SharePoint 2010 é tema de um próximo post. (:</p>
<p align="justify"><em>“Ok Thiago, você me convenceu. Como começo? O que eu preciso para trabalhar com o PowerPivot for Excel?”</em></p>
<p align="justify">Tudo o que você vai precisar já está disponível publicamente, seguem os links para download:</p>
<p><em>Microsoft SQL Server 2008 R2 (Nov CTP): </em><a title="http://www.microsoft.com/sqlserver/2008/en/us/R2.aspx" href="http://www.microsoft.com/sqlserver/2008/en/us/R2.aspx">http://www.microsoft.com/sqlserver/2008/en/us/R2.aspx</a></p>
<p><em>Microsoft Office 2010 Beta:</em> <a title="http://www.microsoft.com/office/2010/en/default.aspx" href="http://www.microsoft.com/office/2010/en/default.aspx">http://www.microsoft.com/office/2010/en/default.aspx</a></p>
<p>PowerPivot for Excel 2010 (certifique-se de pegar o plugin correspondente a arquitetura que o seu Office está instalado, pois você pode ter um sistema com arquitetura x64 e ter botado o Office x86): <a title="http://powerpivot.com/download.aspx" href="http://powerpivot.com/download.aspx">http://powerpivot.com/download.aspx</a></p>
<p>Instale o Microsoft Office 2010, o SQL Server 2008 R2 (Nov CTP) e então o plugin para o&#160; PowerPivot for Excel. No site oficial do PowerPivot (<a href="http://www.powerpivot.com">www.powerpivot.com</a>) também há um guia (em inglês) para o processo de instalação se acharem necessário. O processo é bem tranquilo, até eu consegui! :)</p>
<p><em>“Bom Thiago eu tenho tudo instalado e agora vou analizar .... Vou analizar o que?”</em></p>
<p>Com o PowerPivot nós podemos usar uma série de recursos como fontes de dados: cubos SSAS, tabelas do excel, SQL Server, Oracle e assim por diante. o seguinte site contém diversas bases de dados que você pode utilizar como fonte para os seus experimentos: <a title="http://www.powerpivot-info.com/post/50-list-suggested-datasets-to-test-powerpivot" href="http://www.powerpivot-info.com/post/50-list-suggested-datasets-to-test-powerpivot">http://www.powerpivot-info.com/post/50-list-suggested-datasets-to-test-powerpivot</a>.</p>
<p>Eu irei usar para os experimentos deste post a seguinte base de dados (em Access): <a title="http://powerpivotsampledata.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=35438" href="http://powerpivotsampledata.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=35438">http://powerpivotsampledata.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=35438</a>.</p>
<p>Agora com tudo instalado e um conjunto de dados, podemos começar a diversão!</p>
<p><strong>Primeras Impressões</strong></p>
<p>A primeira coisa que você irá perceber é uma nova aba no Excel, denominada PowerPivot (conforme a figura 1):</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic1_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic1_powerpivot" border="0" alt="pic1_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic1_powerpivot_thumb.png" width="546" height="189" /></a>    <br /><em>Figura 1: A nova aba no Microsoft Excel 2010.</em></p>
<p>Nesta aba nós temos seis grupos: Launch. Measures, View, Excel Data, Help e Show/Hide.</p>
<p>O início de tudo se dá no grupo Launch, mais precisamente no botão <em>PowerPivot Window</em> presente na Ribbon. A figura 2 mostra a janela que deverá aparecer para você.</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic2_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic2_powerpivot" border="0" alt="pic2_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic2_powerpivot_thumb.png" width="551" height="237" /></a>    <br /><em>Figura 2: A janela do PowerPivot</em></p>
<p>Nós não temos nenhum dado carregado ainda. O que nós temos basicamente habilitados são os botões de recuperação dos dados, listar/configurar as conexões existentes. Você também tem a opçõ de retornar para a janela principal do Excel.</p>
<p>Antes de importar os dados da fonte que mencionei anteriormente, vamos ver quais são os tipos de fontes de dados que podemos utilizar. Inicialmente você irá ver os tipos mais comuns de fontes de dados, mas você pode clicar em “From Other Sources” para ver a grande gama que temos disponível. E são eles (pelo menos no CTP de novembro do SQL Server 2008 R2):</p>
<ul>
<li>Microsoft SQL Server </li>
<li>Microsoft SQL Azure </li>
<li>Microsoft Access </li>
<li>Microsoft SQL Server Analysis Services </li>
<li>PowerPivot workbooks published to Analysis Services running in SharePoint Integrated Mode </li>
<li>Oracle </li>
<li>Teradata </li>
<li>Sybase </li>
<li>Informix </li>
<li>DB2 </li>
<li>DataFeeds </li>
<li>Excel workbooks </li>
<li>Text files </li>
</ul>
<p>Você pode conectar também com qualquer fonte de dados que seja compatível com conexões ODBC ou OLEDB.</p>
<p>Na minha opinião, a possibilidade de usar informação proveniente de um cubo SSAS com outras fontes de informação (por exemplo) é fantástica! Esta capacidade é muitas vezes mais poderosa doq ue simplesmente utilizar as tabelas dinâmicas com cubos SSAS.</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic3_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic3_powerpivot" border="0" alt="pic3_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic3_powerpivot_thumb.png" width="469" height="479" /></a>    <br /><em>Figura 3: Fontes de Dados Disponíveis.</em></p>
<p><strong>Fonte de dados de Exemplo</strong></p>
<p>A fonte de dados de exemplo contém quatro arquivos:</p>
<ul>
<li>AccessQuery.txt - contém uma query de exemplo pra executar contra o banco fornecido no pacote também. Utilizaremos em nosso exemplo. </li>
<li>AW_Companysales.accdb e IndustryBikeSales.accdb - que são bases de exemplo em Access que estão disponíveis para testes. </li>
<li>Country.xlsx - que é um arquivo excel simples que contém um mapeamento sigla-país. </li>
</ul>
<p><strong>Alimentando o PowePivot</strong></p>
<p>Clique em “From Database” e selecione “From Access”, selecione a base de dados IndustryBikeSales. Preencha o nome com um nome amigável ( :) ). esta base de dados não necessita de login e senha, deixe estes campos em branco.</p>
<p>Na próxima janela selecione a opção que deixe você escrever a sua query customizada. Coloque a seguinte query (é a fornecida nos arquivos mencionados anteriormente) e clique no botão <em>Import</em>:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:dabab780-827a-4e0b-b161-bb51b56e410e" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;overflow: auto;"><span style="color: #0000FF;">SELECT</span><span style="color: #000000;"> IndustrySales.Country, IndustrySales.Quarter,
IndustrySales.</span><span style="color: #FF0000;">[</span><span style="color: #FF0000;">Type Of Bike</span><span style="color: #FF0000;">]</span><span style="color: #000000;">, IndustrySales.Channel,
IndustrySales.Units
</span><span style="color: #0000FF;">FROM</span><span style="color: #000000;"> IndustrySales
</span><span style="color: #0000FF;">WHERE</span><span style="color: #000000;"> ( (IndustrySales.Quarter </span><span style="color: #808080;">&gt;=</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">2001 Q3</span><span style="color: #FF0000;">'</span><span style="color: #000000;">)
</span><span style="color: #808080;">AND</span><span style="color: #000000;"> (IndustrySales.Quarter</span><span style="color: #808080;">&lt;=</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">2009 Q2</span><span style="color: #FF0000;">'</span><span style="color: #000000;">) )</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>A sua janela do PowerPivot deve estar parecida com a figura 4:</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic4_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic4_powerpivot" border="0" alt="pic4_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic4_powerpivot_thumb.png" width="564" height="488" /></a></p>
<p><em>Figura 4: Dados resultantes da query sobre a base IndustryBikeSales</em></p>
<p>Nós temos as informações sobre as vendas por trimestre, divididas por tipo de produto (bicicleta no caso). Vocês devem concordar comigo que é um pouco confuso tomar desições através da análise direta destes dados (1152 linhas). Não seria muito bom se nós pudéssemos simplesmente organizar o total de vendas por tipo, ou por país (trimestre etc.) de uma maneira rápida e com poucos cliques?</p>
<p>Nós podemos fazer isso utilizando o PowerPivot for Excel, com pousos esforços podemos extrair muita informação. Você pode adicionar fórmlas do excel, expressões DAX, criando novas colunas baseadas nos seus dados (sobre isso teremos novos posts) para ter mais subsídios para a sua análise.</p>
<p>na figura 4 você pode observar que nós temos vários outros botões habilitados: Refresh, Manual e PivotTable.</p>
<p>O botão “Refresh” importa novamente os dados das fontes. É como qualquer outro botão de atualizar :). O botão PivotTable é o próximo botão que você tem que olhar. Clicar nele irá te mostrar algo similar a figura 5.</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic5_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic5_powerpivot" border="0" alt="pic5_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic5_powerpivot_thumb.png" width="281" height="416" /></a></p>
<p><em>Figura 5: Menu PivotTable</em></p>
<p>Quando você selecionar um destes itens, o Exel irá perguntar onde você quer criar o template: num novo worksheet ou em um existente. Independente do que você escolher, o template será criado pelo PowerPivot. O seu Microsoft Excel 2010 deverá estar parecido com a figura 6. Para o meu exemplo usei a opção: Four Charts (quatro gráficos).</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic6_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic6_powerpivot" border="0" alt="pic6_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic6_powerpivot_thumb.png" width="552" height="369" /></a></p>
<p><em>Figura 6: O template com os gráficos gerados pelo PowerPivot</em></p>
<p>Eu selecionei para adicionar em um workbook existente (”Sheet 1”). agora nós temos algumas coisas que você provavelmente (espero, hehe) percebeu: nós temos 4 abas novas (Data for Sheet 1 Chart 1, Data for Sheet 1 Chart 2, ... e assim por diante) e quando você clica em um destes gráficos você verá o grupo Pivot Chart Toolsna ribbon (figura 7) e o Gemini Task Pane (figura 8). Eu não vou entrar em detalhes sobre a ribbon, a maioria das opções são sobre formatações e coisas do gênero.</p>
<p>Ess painel do Gemini é familiar pra você? Eu acho que é muito parecido com o painel de tabela dinâmica do Excel, mas com os slicers (veremos a seguir).</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic7_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic7_powerpivot" border="0" alt="pic7_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic7_powerpivot_thumb.png" width="554" height="76" /></a></p>
<p><em>Figura 7: PivotChart Tools: Design</em></p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic8_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic8_powerpivot" border="0" alt="pic8_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic8_powerpivot_thumb.png" width="190" height="453" /></a></p>
<p><em>Figura 8: Gemini Task Pane</em></p>
<p>Nós agora iremos selecionar alguns dados para popular os relatóios. Você pode simplesmente marcar as checkboxes ou arrastar e soltar na região que desejar: Legend Fields, Axis fields, Values ou filtrar alguma informação. Você também pode usar os slicers. Os slicers são como filtros que você pode ligá-los ou desligá-los apenas clicando neles! Vamos relembrar que o PowerPivot é voltado aos gerentes, diretores e tomadores de decisão, então este comportamento é realmente útil.</p>
<p>Após simplesmente adicionar algumas colunas aos gráficos e adicionado o Trimestre (Quarter) e País (Country) como slicers (com, realmente, poucos cliques) nós temos algo parecido com a figura 9.</p>
<p><a href="http://zavaschi.com/wp-content/uploads/2009/12/pic9_powerpivot.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="pic9_powerpivot" border="0" alt="pic9_powerpivot" src="http://zavaschi.com/wp-content/uploads/2009/12/pic9_powerpivot_thumb.png" width="553" height="280" /></a></p>
<p><em>Figura 9: Dashboard sobre os dados sendo analisados com o PowerPivot!!! Criado com pouquíssimos cliques!</em></p>
<p>Olhe na parte esquerda da figura 9. Estes são os slicers que comentei anteriormente. eu facilmente selecionei apenas as informações de 2003 e 2004 e excluí da análise os Estados Unidos. Se o desejo fosse analisar Estados Unidos x Alemanha, por exemplo, eu poderia simplesmente clicar nos slicers correspondentes e não ateraria nada nos gráficos! Eu também tenho que dizer que essa operação é extremamente rápida, mesmo quando tivermos milhões de linhas.</p>
<p>A última coisa que você tem que olhar agora é nas outras abas criadas pelo PowerPivot. Os dados parecem familiares? Estes são os dados que estão sendo usados na criação dos ráficos apresentados na dashboard.</p>
<p>O próximo passo é compartilhar a análise feta no Excel, para evitar duplicamento de informações e manter tudo em um ponto central. O PowerPivot for SharePoint vem somar recursos às capacidades grande que já temos (veremos com mais detalhes em artigos futuros)!</p>
<p>Bom, isso é tudo que eu queria mostrar hoje pessoal. E essa é só a ponta deste iceberg chamado PowerPivot. Eu irei mostrar features mais avançadas e a integração com o SharePoint 2010 (múltiplas fontes simultâneas, DAX) no próximo artigo!</p>
<p>Abraços a todos!</p>
<p>Thiago Zavaschi</p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2009/12/novidades-do-sql-server-2008-r2-parte-iii-iniciando-com-o-powerpivot-for-excel-2010/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Entendendo as Common Table Expressions &#8211; CTE &#8211; Parte 2 (Final)</title>
		<link>http://zavaschi.com/index.php/2009/09/entendendo-as-common-table-expressions-cte-parte-2-final/</link>
		<comments>http://zavaschi.com/index.php/2009/09/entendendo-as-common-table-expressions-cte-parte-2-final/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 11:47:28 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[Common Table Expression]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">8DE5A8EFC1819ECA!391</guid>
		<description><![CDATA[Exemplos de queries recursivas
Bom, mostrei um pouco de teoria, mostrei alguns exemplos didáticos (o de números é bastante utilizado na prática), mas vamos ver mais alguns exemplos:
Vou começar com um exemplo já mostrado aqui no blog (sim, finalmente este é o post sobre o qual falei no referido post :) ).
Este é o método baseado [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Exemplos de queries recursivas</strong></p>
<p>Bom, mostrei um pouco de teoria, mostrei alguns exemplos didáticos (o de números é bastante utilizado na prática), mas vamos ver mais alguns exemplos:</p>
<p>Vou começar com um <a href="http://thiagozavaschi.spaces.live.com/Blog/cns!8DE5A8EFC1819ECA!277.entry" target="_blank">exemplo já mostrado aqui no blog</a> (sim, finalmente este é o post sobre o qual falei no referido post :) ).</p>
<p>Este é o método baseado em CTE para realizar Split no SQL Server (atentar para o limite da recursividade, se necessário usar o maxrecursion).</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#0000ff">DECLARE</span><span style="color:#000000"> </span><span style="color:#008000">@s</span><span style="color:#000000"> </span><span style="color:#0000ff">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">8000</span><span style="color:#000000">), </span><span style="color:#008000">@d</span><span style="color:#000000"> </span><span style="color:#0000ff">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">10</span><span style="color:#000000">)
</span><span style="color:#0000ff">SET</span><span style="color:#000000"> </span><span style="color:#008000">@s</span><span style="color:#000000"> </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#ff0000">'</span><span style="color:#ff0000">separar por espaço em branco</span><span style="color:#ff0000">'</span><span style="color:#000000">
</span><span style="color:#0000ff">SET</span><span style="color:#000000"> </span><span style="color:#008000">@d</span><span style="color:#000000"> </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#ff0000">'</span><span style="color:#ff0000"> </span><span style="color:#ff0000">'</span><span style="color:#000000"> 

;</span><span style="color:#0000ff">WITH</span><span style="color:#000000"> split(i,j) </span><span style="color:#0000ff">AS</span><span style="color:#000000">
(
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> i </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">, j </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#ff00ff">CHARINDEX</span><span style="color:#000000">(</span><span style="color:#008000">@d</span><span style="color:#000000">, </span><span style="color:#008000">@s</span><span style="color:#000000"> </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#008000">@d</span><span style="color:#000000">)
</span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> i </span><span style="color:#808080">=</span><span style="color:#000000"> j </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">, j </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#ff00ff">CHARINDEX</span><span style="color:#000000">(</span><span style="color:#008000">@d</span><span style="color:#000000">, </span><span style="color:#008000">@s</span><span style="color:#000000"> </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#008000">@d</span><span style="color:#000000">, j </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">) </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> split
   </span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> </span><span style="color:#ff00ff">CHARINDEX</span><span style="color:#000000">(</span><span style="color:#008000">@d</span><span style="color:#000000">, </span><span style="color:#008000">@s</span><span style="color:#000000"> </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#008000">@d</span><span style="color:#000000">, j </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">) </span><span style="color:#808080">&lt;&gt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">0</span><span style="color:#000000">
)
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#ff00ff">SUBSTRING</span><span style="color:#000000">(</span><span style="color:#008000">@s</span><span style="color:#000000">,i,j</span><span style="color:#808080">-</span><span style="color:#000000">i)
</span><span style="color:#0000ff">FROM</span><span style="color:#000000"> split
</span></pre>
</div>
<p>O método é facilmente adaptável para o seu outro grande uso: parser de textos CSV. Basta apenas trocar o delimitador. Simples não?</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#0000ff">DECLARE</span><span style="color:#000000"> </span><span style="color:#008000">@s</span><span style="color:#000000"> </span><span style="color:#0000ff">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">8000</span><span style="color:#000000">), </span><span style="color:#008000">@d</span><span style="color:#000000"> </span><span style="color:#0000ff">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">10</span><span style="color:#000000">)
</span><span style="color:#0000ff">SET</span><span style="color:#000000"> </span><span style="color:#008000">@s</span><span style="color:#000000"> </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#ff0000">'</span><span style="color:#ff0000">123;4;thiago@zavaschi.com;2232323</span><span style="color:#ff0000">'</span><span style="color:#000000">
</span><span style="color:#0000ff">SET</span><span style="color:#000000"> </span><span style="color:#008000">@d</span><span style="color:#000000"> </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#ff0000">'</span><span style="color:#ff0000">;</span><span style="color:#ff0000">'</span><span style="color:#000000"> 

</span><span style="color:#008080">--</span><span style="color:#008080"> Continuação mostrada anteriormente.</span></pre>
</div>
<p>Um exemplo interessante que sempre cobro em aula (acho que vou ter que parar de cobrar :P) é para realizar o exemplo clássico do fatorial. O resultado final eu diria ser muito elegante.</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#0000ff">WITH</span><span style="color:#000000"> fat(f, n) </span><span style="color:#0000ff">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#ff00ff">CAST</span><span style="color:#000000"> (</span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> </span><span style="color:#0000ff">bigint</span><span style="color:#000000">) </span><span style="color:#0000ff">as</span><span style="color:#000000"> f, </span><span style="color:#800000;font-weight:bold">0</span><span style="color:#000000">  </span><span style="color:#0000ff">as</span><span style="color:#000000"> n </span><span style="color:#008080">--</span><span style="color:#008080"> fat de 0 é 1</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#ff00ff">CAST</span><span style="color:#000000"> (</span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> </span><span style="color:#0000ff">bigint</span><span style="color:#000000">) </span><span style="color:#0000ff">as</span><span style="color:#000000"> f, </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> n </span><span style="color:#008080">--</span><span style="color:#008080"> fat de 1 é 1</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> f </span><span style="color:#808080">*</span><span style="color:#000000"> (n </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">), n </span><span style="color:#808080">+</span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">
    </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> fat
    </span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> n </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">20</span><span style="color:#000000"> </span><span style="color:#808080">AND</span><span style="color:#000000"> n </span><span style="color:#808080">&lt;&gt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">0</span><span style="color:#000000">
    </span><span style="color:#008080">--</span><span style="color:#008080"> 20 é o limite neste caso, pois o fatorial de 21 </span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#008080">--</span><span style="color:#008080"> não cabe em um tipo bigint. O &lt;&gt; 0 é para cortar a recursão</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#008080">--</span><span style="color:#008080"> do primeiro âncora, senão repetiria tudo, faça o teste. </span><span style="color:#008080">
</span><span style="color:#000000">)
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> f
</span><span style="color:#0000ff">FROM</span><span style="color:#000000"> fat
</span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> n </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">6</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> troque n pelo fatorial que quer calcular</span></pre>
</div>
<p>Para melhorar a legibilidade das queries. podemos encapsular isso em uma função:</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#0000ff">CREATE</span><span style="color:#000000"> </span><span style="color:#0000ff">FUNCTION</span><span style="color:#000000"> fatorial
(
    </span><span style="color:#008000">@n</span><span style="color:#000000"> </span><span style="color:#0000ff">INT</span><span style="color:#000000">
)
</span><span style="color:#0000ff">RETURNS</span><span style="color:#000000"> </span><span style="color:#0000ff">INT</span><span style="color:#000000">
</span><span style="color:#0000ff">AS</span><span style="color:#000000">
</span><span style="color:#0000ff">BEGIN</span><span style="color:#000000">
    </span><span style="color:#0000ff">DECLARE</span><span style="color:#000000"> </span><span style="color:#008000">@val</span><span style="color:#000000"> </span><span style="color:#0000ff">INT</span><span style="color:#000000">;
    </span><span style="color:#0000ff">WITH</span><span style="color:#000000"> fat(f, n) </span><span style="color:#0000ff">AS</span><span style="color:#000000">
    (
        </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#ff00ff">CAST</span><span style="color:#000000"> (</span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> </span><span style="color:#0000ff">bigint</span><span style="color:#000000">) </span><span style="color:#0000ff">as</span><span style="color:#000000"> f, </span><span style="color:#800000;font-weight:bold">0</span><span style="color:#000000">  </span><span style="color:#0000ff">as</span><span style="color:#000000"> n
        </span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
        </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#ff00ff">CAST</span><span style="color:#000000"> (</span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> </span><span style="color:#0000ff">bigint</span><span style="color:#000000">) </span><span style="color:#0000ff">as</span><span style="color:#000000"> f, </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> n
        </span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
        </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> f </span><span style="color:#808080">*</span><span style="color:#000000"> (n </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">), n </span><span style="color:#808080">+</span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">
        </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> fat
        </span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> n </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">20</span><span style="color:#000000"> </span><span style="color:#808080">AND</span><span style="color:#000000"> n </span><span style="color:#808080">&lt;&gt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">0</span><span style="color:#000000">
    )
    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#008000">@val</span><span style="color:#000000"> </span><span style="color:#808080">=</span><span style="color:#000000"> f
    </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> fat
    </span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> n </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#008000">@n</span><span style="color:#000000">
    </span><span style="color:#0000ff">RETURN</span><span style="color:#000000"> </span><span style="color:#008000">@val</span><span style="color:#000000">
</span><span style="color:#0000ff">END</span><span style="color:#000000">
</span><span style="color:#0000ff">GO</span><span style="color:#000000">

</span><span style="color:#008080">--</span><span style="color:#008080"> Testando a função</span><span style="color:#008080">
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> dbo.fatorial(</span><span style="color:#800000;font-weight:bold">3</span><span style="color:#000000">);
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> dbo.fatorial(</span><span style="color:#800000;font-weight:bold">4</span><span style="color:#000000">);
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> dbo.fatorial(</span><span style="color:#800000;font-weight:bold">7</span><span style="color:#000000">);</span></pre>
</div>
<p><strong>(Abrindo um parênteses importante:</strong></p>
<p>A única resalva que faço é quanto a estes calculos matemáticos intensos em queries. O SQL Server trabalha muito bem com as ditas <em>set based operations. </em>ou seja, operações baseadas em conjuntos. Operações envolvendo manipulação de strings e cálculos matemáticos complexos não são o forte do SQL Server. Como resolver então, de outra maneira?</p>
<p>Desde o SQL Server 2005 (apareceu junto com as CTEs) o SQL Server tem a CLR integrada ao seu core. Isso quer dizer que é possível criar objetos para o SQL Server (User Defined Types – UDT, Stored Procedures, Functions, etc) programando em uma linguagem compatível com a Common Language Runtime e adicionar o assembly gerado ao seu banco SQL Server. Não fiz testes para esse exemplo do fatorial (farei em um futuro breve), mas é provável que o tempo de execução seja menor se o mesmo estivesse sendo executado pela CLR.</p>
<p>Farei um post detalhando melhor e também na Mundo.NET da edição de Dezembro/2009 sairá um artigo meu sobre como programar com SQLCLR usando C#!</p>
<p><strong>Fechando o parênteses muito importante)</strong></p>
<p>Para o próximo exemplo eu preciso fazer algumas considerações.</p>
<p>Com o SQL Server 2008 surgiu o tipo de dados HIERACHYID e que é, na minha visão, o melhor método de se trabalhar com registros que possuem comportamento hierárquico. Por uma série de motivos: o banco é SQL Server 2005 (ou esta com Compability Level 90), ou é uma estrutura legada, e se você deseja tratar hierarquias? </p>
<p>Commom Table Expressions podem fazer, e fazem, esse papel muito bem. Digamos que temos uma estrutura hirárquica de empregados e cada registro faz uma referência a outro registro que seria o seu supervisor dentro de uma empresa. O diretor da empresa não possui ligação com ninguém, uma vez que ele não teria um supervisor.</p>
<p>Para esse exemplo poderia usar a tabela de empregados do AdventureWorks, mas como nem sempre todos a possuem instalada (deveriam, pois há centenas de exemplos que a utilizam), eu mesmo montarei uma pequena “base”.</p>
<p>Segue o modelo de dados e script para criação da estrutura.</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#008080">--</span><span style="color:#008080"> Cria tabela base</span><span style="color:#008080">
</span><span style="color:#0000ff">CREATE</span><span style="color:#000000"> </span><span style="color:#0000ff">TABLE</span><span style="color:#000000"> Empregado
(
    id </span><span style="color:#0000ff">INT</span><span style="color:#000000"> </span><span style="color:#0000ff">PRIMARY</span><span style="color:#000000"> </span><span style="color:#0000ff">KEY</span><span style="color:#000000">,
    nome </span><span style="color:#0000ff">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">50</span><span style="color:#000000">) </span><span style="color:#808080">NOT</span><span style="color:#000000"> </span><span style="color:#0000ff">NULL</span><span style="color:#000000">,
    cargo </span><span style="color:#0000ff">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">50</span><span style="color:#000000">) </span><span style="color:#808080">NOT</span><span style="color:#000000"> </span><span style="color:#0000ff">NULL</span><span style="color:#000000">,
    id_supervisor </span><span style="color:#0000ff">INT</span><span style="color:#000000"> </span><span style="color:#0000ff">NULL</span><span style="color:#000000">
        </span><span style="color:#0000ff">CONSTRAINT</span><span style="color:#000000"> fk_productSales_pid
        </span><span style="color:#0000ff">FOREIGN</span><span style="color:#000000"> </span><span style="color:#0000ff">KEY</span><span style="color:#000000"> </span><span style="color:#0000ff">REFERENCES</span><span style="color:#000000"> Empregado(id)
);

</span><span style="color:#008080">--</span><span style="color:#008080"> Popula a tabela (reparem na sintaxe do insert, </span><span style="color:#008080">
--</span><span style="color:#008080"> só é permitida no SQL Server 2008 ou superior).</span><span style="color:#008080">
</span><span style="color:#0000ff">INSERT</span><span style="color:#000000"> </span><span style="color:#0000ff">INTO</span><span style="color:#000000"> Empregado </span><span style="color:#0000ff">VALUES</span><span style="color:#000000">
(</span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Thiago Zavaschi</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Diretor</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#0000ff">null</span><span style="color:#000000">),
(</span><span style="color:#800000;font-weight:bold">2</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Angelina Jolie</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Gerente de Vendas</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">),
(</span><span style="color:#800000;font-weight:bold">3</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Megan Fox</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Gerente de Marketing</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">),
(</span><span style="color:#800000;font-weight:bold">4</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Uma Thurman</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Vendedor</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#800000;font-weight:bold">2</span><span style="color:#000000">),
(</span><span style="color:#800000;font-weight:bold">5</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Jessica Alba</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Vendedor</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#800000;font-weight:bold">2</span><span style="color:#000000">),
(</span><span style="color:#800000;font-weight:bold">6</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Julia Roberts</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#ff0000">'</span><span style="color:#ff0000">Estagiário</span><span style="color:#ff0000">'</span><span style="color:#000000">, </span><span style="color:#800000;font-weight:bold">3</span><span style="color:#000000">);

</span></pre>
</div>
<p>Ao executar um simples select nesta tabela temos:</p>
<p><font size="2" face="Courier New">id       nome                       cargo                            id_supervisor<br />-------- -------------------------- -------------------------------- -------------<br />1        Thiago Zavaschi            Diretor                          NULL<br />2        Angelina Jolie             Gerente de Vendas                1<br />3        Megan Fox                  Gerente de Marketing             1<br />4        Uma Thurman                Vendedor                         2<br />5        Jessica Alba               Vendedor                         2<br />6        Julia Roberts              Estagiário                       3 </font></p>
<p>Creio que todos deverão concordar comigo que esta visulização torna praticamente impossível a noção de hierarquia (e olhe que temos poucos registros, imagine termos centenas dos mesmos.</p>
<p>É fácil retornar qual é o nome do supervisor, mas isso de maneira recursiva não seria nada tranquilo. Vou montar uma query que me retorne o nível da pessoa na hierarquia. Ou seja, para o Diretor o valor será 1, para os gerentes será 2, e para o restante será 3. Com a minah CTE retornando isso, a query subsequente, que consome a CTE podera formatar os resultados, filtrar, enfim, tudo baseado no resultado da consulta recursiva já processada, bacana né? Vamos lá!</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000ff">WITH</span><span style="color:#000000"> hierarquia(id, nome, cargo, id_supervisor, nivel_hierarquia)
</span><span style="color:#0000ff">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000">  id, nome, cargo, id_supervisor, </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> nivel_hierarquia
    </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> Empregado
    </span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> id_supervisor </span><span style="color:#0000ff">IS</span><span style="color:#000000"> </span><span style="color:#0000ff">NULL</span><span style="color:#000000">
    </span><span style="color:#008080">--</span><span style="color:#008080"> Perceba que aqui no âncora temos como retorno somente o diretor.</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> Ligação para a recursão</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> e.id, e.nome, e.cargo, e.id_supervisor, nivel_hierarquia </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">
    </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> Empregado e
    </span><span style="color:#0000ff">INNER</span><span style="color:#000000"> </span><span style="color:#808080">JOIN</span><span style="color:#000000"> hierarquia h </span><span style="color:#0000ff">ON</span><span style="color:#000000"> h.id</span><span style="color:#808080">=</span><span style="color:#000000"> e.id_supervisor
)
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#808080">*</span><span style="color:#000000"> </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> hierarquia</span></pre>
</div>
<p>A saída deste script é (reparem na coluna nivel_herarquia):</p>
<p><font size="2" face="Courier New">id       nome                 cargo                       id_supervisor nivel_hierarquia<br />-------- -------------------- --------------------------- ------------- ----------------<br />1        Thiago Zavaschi      Diretor                     NULL          1<br />2        Angelina Jolie       Gerente de Vendas           1             2<br />3        Megan Fox            Gerente de Marketing        1             2<br />6        Julia Roberts        Estagiário                  3             3<br />4        Uma Thurman          Vendedor                    2             3<br />5        Jessica Alba         Vendedor                    2             3</font> </p>
<p><em>“Ok thiago, mas ainda assim não estou conseguindo visualizar, por exemplo, quem é o supervisor, tem como melhorar?”</em></p>
<p>Tem sim. uma das utilidades das CTEs é: a mesma retornar um result set “complexo de ser calculado” (como o caso da hierarquia) e deixar para o select mais abaixo fazer a formatação/filtragem/ordenação. Isso eixar a estrutura da sua CTE mais genérica e menos “engessada”, fazendo até mesmo com que você possa reaproveitar esse código em outro lugar.</p>
<p>Por exemplo: quero uma listagem com todo o time operacional (maior valor em nivel_hierarquia) da empresa, com seus respectivos supervisores. A query poderia ficar assim:</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000ff">WITH</span><span style="color:#000000"> hierarquia(id, nome, cargo, id_supervisor, nivel_hierarquia)
</span><span style="color:#0000ff">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000">  id, nome, cargo, id_supervisor, </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000ff">as</span><span style="color:#000000"> nivel_hierarquia
    </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> Empregado
    </span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> id_supervisor </span><span style="color:#0000ff">IS</span><span style="color:#000000"> </span><span style="color:#0000ff">NULL</span><span style="color:#000000">
    </span><span style="color:#008080">--</span><span style="color:#008080"> Perceba que aqui no âncora temos como retorno somente o diretor.</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> Ligação para a recursão</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> e.id, e.nome, e.cargo, e.id_supervisor, nivel_hierarquia </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">
    </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> Empregado e
    </span><span style="color:#0000ff">INNER</span><span style="color:#000000"> </span><span style="color:#808080">JOIN</span><span style="color:#000000"> hierarquia h </span><span style="color:#0000ff">ON</span><span style="color:#000000"> h.id</span><span style="color:#808080">=</span><span style="color:#000000"> e.id_supervisor
)
</span><span style="color:#0000ff">SELECT</span><span style="color:#000000">
h.nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#ff0000">'</span><span style="color:#ff0000">/</span><span style="color:#ff0000">'</span><span style="color:#000000"> </span><span style="color:#808080">+</span><span style="color:#000000"> h.cargo </span><span style="color:#0000ff">as</span><span style="color:#000000"> </span><span style="color:#ff0000">[</span><span style="color:#ff0000">Operacional</span><span style="color:#ff0000">]</span><span style="color:#000000">, </span><span style="color:#008080">--</span><span style="color:#008080"> perceba a formatação ocorrendo aqui</span><span style="color:#008080">
</span><span style="color:#000000">s.nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#ff0000">'</span><span style="color:#ff0000">/</span><span style="color:#ff0000">'</span><span style="color:#000000"> </span><span style="color:#808080">+</span><span style="color:#000000"> s.cargo </span><span style="color:#0000ff">as</span><span style="color:#000000"> </span><span style="color:#ff0000">[</span><span style="color:#ff0000">Tático</span><span style="color:#ff0000">]</span><span style="color:#000000">
</span><span style="color:#0000ff">FROM</span><span style="color:#000000"> hierarquia h </span><span style="color:#808080">JOIN</span><span style="color:#000000"> Empregado s </span><span style="color:#0000ff">ON</span><span style="color:#000000"> h.id_supervisor </span><span style="color:#808080">=</span><span style="color:#000000"> s.id
</span><span style="color:#0000ff">WHERE</span><span style="color:#000000"> h.nivel_hierarquia </span><span style="color:#808080">=</span><span style="color:#000000">
(</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> </span><span style="color:#ff00ff">MAX</span><span style="color:#000000">(nivel_hierarquia) </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> hierarquia) </span><span style="color:#008080">--</span><span style="color:#008080"> perceba que o filtro ocorreu aqui</span><span style="color:#008080">
</span></pre>
</div>
<p>Com o seguinte output:</p>
<p><font size="2" face="Courier New">Operacional                     Tático<br />------------------------------- ------------------------------------<br />Julia Roberts/Estagiário        Megan Fox/Gerente de Marketing<br />Uma Thurman/Vendedor            Angelina Jolie/Gerente de Vendas<br />Jessica Alba/Vendedor           Angelina Jolie/Gerente de Vendas</font> </p>
<p>Tranquilo né? E assim poderíamos evoluir de “N” formas, cada uma atendendo a uma necessidade específica.</p>
<p>Common table Expressions também podem ser utilizadas de outras formas, para fazer tratamento de datas, carga, e muitas outras funções (ver links no final do post para maiores informações).</p>
<p><strong>O que mais saber sobre Common Table Expressions (CTE) ?</strong></p>
<p>Bom, já vimos bastante coisa sobre o que é uma CTE, como funciona, onde se aplica (com alguns exemplos), mas o que mais devemos saber?</p>
<p>Devemos saber que há <em>restrições</em> sobre oq eu podemos usar ou não em CTEs. Vou listar alguams das que eu considero principais (no Books Online – BOL, há a lista completa, ver link ao final do post).</p>
<p>Bom acredito que a primeira coisa que é importante saber é que NÃO é permitido fazer uma referência recursiva dentro de uma subquery. Vou usar o exemplo anterior para demonstrar:</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#f4f4f4;overflow:auto"><span style="color:#000000">...
</span><span style="color:#0000ff">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> e.id, e.nome, e.cargo, e.id_supervisor,
    (</span><span style="color:#0000ff">SELECT</span><span style="color:#000000"> h.nivel_hierarquia_2 </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> hierarquia) </span><span style="color:#008080">--</span><span style="color:#008080"> ISSO NÃO É PERMITIDO.</span><span style="color:#008080">
</span><span style="color:#000000">    </span><span style="color:#0000ff">FROM</span><span style="color:#000000"> Empregado e
    ...
)
...</span></pre>
</div>
<p>O que nos gera um erro similar a:</p>
<p><font color="#ff0000" size="2" face="Courier New">Msg 465, Level 16, State 1, Line 32<br />Recursive references are not allowed in subqueries.</font> </p>
<p>O que mais não é permitido na definição do membro recursivo? Segue a lista: </p>
<ul>
<li>SELECT DISTINCT
<li>GROUP BY
<li>HAVING
<li>Scalar aggregation
<li>TOP
<li>LEFT, RIGHT, OUTER JOIN (obs: o INNER JOIN é permitido)
<li>A hint applied to a recursive reference to a CTE inside a <em>CTE_query_definition</em>.</li>
</li>
</li>
</li>
</li>
</li>
</li>
</ul>
<p>Você, leitor, deve ter percebido que eu normalmente iniciei minhas CTE’s com um ponto e vírgula (‘;’), não, não fiquei maluco e nem coloquei por engano.<br />A questão é que a sintaxe para execução da CTE <strong>obriga</strong> que o statement anterior termine com ponto e vírgula, então acabo sempre colocando, já que o statement anterior normalmente não possui “;” ao seu término!</p>
<p>Há algumas guidelines no books online e vou apenas trancrever aqui, em inglês mesmo (consultar o link no final para o texto completo – em inglês), omiti sobre o maxrecursion que eu já comentei.</p>
<li>All columns returned by the recursive CTE are nullable regardless of the nullability of the columns returned by the participating SELECT statements.
<li>A view that contains a recursive common table expression cannot be used to update data.
<li>Cursors may be defined on queries using CTEs. The CTE is the <em>select_statement</em> argument that defines the result set of the cursor. Only fast forward-only and static (snapshot) cursors are allowed for recursive CTEs. If another cursor type is specified in a recursive CTE, the cursor type is converted to static.
<li>Tables on remote servers may be referenced in the CTE. If the remote server is referenced in the recursive member of the CTE, a spool is created for each remote table so the tables can be repeatedly accessed locally. If it is a CTE query, Index Spool/Lazy Spools is displayed in the query plan and will have the additional WITH STACK predicate. This is one way to confirm proper recursion.
<li>SQL Server 2008 does not allow for analytic and aggregate functions in the recursive part of the CTE.
<p> </p>
<p>Com alguns cuidados básicos é possível extrair o máximo da capacidade das CTEs!</p>
<p><strong>Para saber mais</strong></p>
<p>Seguem alguns links aonde é possível encontrar mais informações sobre as Common Table Expressions. A diferença entre CTE no SQL Server 2008 para o 2008 são mínimas, mas como a própria Microsoft mantém em links separados, seguem ambos os links!</p>
<p>Using Common Table Expressions (SQL Server 2008):<br /><a title="http://msdn.microsoft.com/en-us/library/ms190766.aspx" href="http://msdn.microsoft.com/en-us/library/ms190766.aspx">http://msdn.microsoft.com/en-us/library/ms190766.aspx</a>.</p>
<p>Using Common Table Expressions (SQL Server 2005): <br /><a title="http://msdn.microsoft.com/en-us/library/ms190766%28SQL.90%29.aspx" href="http://msdn.microsoft.com/en-us/library/ms190766(SQL.90).aspx">http://msdn.microsoft.com/en-us/library/ms190766%28SQL.90%29.aspx</a></p>
<p>WITH common_table_expression (Transact-SQL) (SQL Server 2008, contém diversos exemplos, muito bom!):<br /><a title="http://msdn.microsoft.com/en-us/library/ms175972.aspx" href="http://msdn.microsoft.com/en-us/library/ms175972.aspx">http://msdn.microsoft.com/en-us/library/ms175972.aspx</a></p>
<p>WITH common_table_expression (Transact-SQL) (SQL Server 2005):<br /><a title="http://msdn.microsoft.com/en-us/library/ms175972%28SQL.90%29.aspx" href="http://msdn.microsoft.com/en-us/library/ms175972(SQL.90).aspx">http://msdn.microsoft.com/en-us/library/ms175972%28SQL.90%29.aspx</a></p>
<p>While x CTE (com exemplos de como fazer carga de dados usando CTE):<br /><a title="http://sqlfromhell.wordpress.com/2009/09/12/while-vs-cte-popular-tabela-de-testes/" href="http://sqlfromhell.wordpress.com/2009/09/12/while-vs-cte-popular-tabela-de-testes/">http://sqlfromhell.wordpress.com/2009/09/12/while-vs-cte-popular-tabela-de-testes/</a></p>
<p>Recursive Queries Using Common Table Expressions (SQL Server 2008):<br /><a title="http://msdn.microsoft.com/en-us/library/ms186243.aspx" href="http://msdn.microsoft.com/en-us/library/ms186243.aspx">http://msdn.microsoft.com/en-us/library/ms186243.aspx</a></p>
<p>Recursive Queries Using Common Table Expressions (SQL Server 2005):<br /><a title="http://msdn.microsoft.com/en-us/library/ms186243%28SQL.90%29.aspx" href="http://msdn.microsoft.com/en-us/library/ms186243(SQL.90).aspx">http://msdn.microsoft.com/en-us/library/ms186243%28SQL.90%29.aspx</a></p>
<h6>Mundo .NET Ed. № 16 – Recursividade, Hierarquias, CTEs e Consultas SQL aplicadas ao Marketing de Rede</h6>
<p>(Tive a oportunidade de revisar este artigo do Gustavo Maia Aguiar – MVP em SQL Server, vale a pena conferir! O artigo se encontra apenas na revista)<br /><a title="http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!695.entry" href="http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!695.entry">http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!695.entry</a></p>
</li>
<p>Using CLR Integration in SQL Server 2005 (Se alguém quiser ir se adiantando um pouco no assunto!)<br /><a title="http://msdn.microsoft.com/en-us/library/ms345136%28SQL.90%29.aspx" href="http://msdn.microsoft.com/en-us/library/ms345136(SQL.90).aspx">http://msdn.microsoft.com/en-us/library/ms345136%28SQL.90%29.aspx</a></p>
<p><strong>Finalizando</strong></p>
<p>UFA! Bom pessoal, espero que todos tenham chegado até aqui, e espero também que gostem tanto do artigo quanto eu gostei de fazê-lo!</p>
<p>Utilizem como referência para consultas futuras e qualquer sugestão estou aberto para ouvir!</p>
<p>Comentei que há o tipo de dados HIERARCHYID, presente no SQL Server 2008 e superirores) para manipular registros essencialmente hierárquicos, mas acho que isso não compete a este post, abordo isso mais profundamente numa próxima oportunidade!</p>
<p>Grande abraço!<br />Thiago Zavaschi</p>
<p><em>PS: Tive que dividir o artigo em duas partes, pois o Spaces não deixa publicar posts grandes (para a primeira parte veja o post anterior).</em></p>
</li>
</li>
</li>
</li>
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2009/09/entendendo-as-common-table-expressions-cte-parte-2-final/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Entendendo as Common Table Expressions &#8211; CTE &#8211; Parte 1</title>
		<link>http://zavaschi.com/index.php/2009/09/entendendo-as-common-table-expressions-cte-parte-1/</link>
		<comments>http://zavaschi.com/index.php/2009/09/entendendo-as-common-table-expressions-cte-parte-1/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 11:40:40 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[Common Table Expression]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">8DE5A8EFC1819ECA!390</guid>
		<description><![CDATA[Antes de mais nada devo dizer que não é um recurso novo, mas muitos desenvolvedores nunca ouviram falar sobre, ou se ouviram desistiram de tentar usar. Este recurso existe desde a versão 2005 do SQL Server e continua existindo nas versões posteriores (2008, 2008 R2 “Kilimanjaro”).
A uma primeira vista parece que as coisas “complicaram”, mas [...]]]></description>
			<content:encoded><![CDATA[<p>Antes de mais nada devo dizer que não é um recurso novo, mas muitos desenvolvedores nunca ouviram falar sobre, ou se ouviram desistiram de tentar usar. Este recurso existe desde a versão 2005 do SQL Server e continua existindo nas versões posteriores (2008, 2008 R2 “Kilimanjaro”).</p>
<p>A uma primeira vista parece que as coisas “complicaram”, mas depois de escrever uma ou duas CTE’s é facilmente perceptível o quão fácil (e vantajoso) é trabalhar com as mesmas.</p>
<p>Antes de dar uma descrição formal de uma CTE, vou executar um dos exemplos mais simples que pode ser feito.</p>
</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> Simples(valor, nome)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">, </span><span style="color:#FF0000">'</span><span style="color:#FF0000">thiago</span><span style="color:#FF0000">'</span><span style="color:#000000">
)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#808080">*</span><span style="color:#000000"> </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Simples</span></pre>
</div>
<p>E o resultado é: </p>
<p><font size="2" face="Courier New">valor       nome<br />----------- ------<br />1           thiago</font> </p>
<p>(1 row(s) affected) </p>
<p><p>Ahmm, ok, eu poderia ter feito o mesmo usando simplesmente algo como:</p>
</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">, </span><span style="color:#FF0000">'</span><span style="color:#FF0000">thiago</span><span style="color:#FF0000">'</span><span style="color:#000000"> </span></pre>
</div>
<p>Mas a vantagem (a primeira das muitas) é que você pode referenciar várias vezes a cte em sua query. Mas antes de demonstrar isso, creioq eu cabe a necessidade de uma definição formal do que seja uma Common Table Expression. Definição segundo o Books Online do SQL Server 2008:</p>
<p>Uma CTE (Common Table Expression) pode ser encarada como um result set que tem seu escopo definido pela execução de um única cláusula SELECT, INSERT, UPDATE, DELETE ou CREATE VIEW. O result set da CTE existe apenas durante a execução da query.<br />Uma CTE tem duas grandes capacidades: pode se auto referenciar (CTE recursiva) e pode ser referenciada várias vezes na mesma query. </p>
<p>A sintaxe de uma CTE é demonstrada a seguir: </p>
<p><code>WITH expression_name [ ( column_name [,...n] ) ]<br /></code><code>AS<br /></code><code>( CTE_query_definition )</code> </p>
<p>A lista de nomes de colunas é opcional somente se a query da CTE retornar colunas com nomes únicos. Contudo, é uma boa prática definir os nomes. </p>
<p>O comando para rodar a CTE seria: </p>
<p><code>SELECT &lt;column_list&gt;<br /></code><code>FROM expression_name;</code> </p>
<p>Um exemplo de uma CTE sendo referenciada várias vezes na mesma query: </p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> VariasVezes(valor)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000">
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">33</span><span style="color:#000000">
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">8</span><span style="color:#000000">
)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000">
(</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">MAX</span><span style="color:#000000">(valor) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> VariasVezes) </span><span style="color:#808080">+</span><span style="color:#000000">
(</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">SUM</span><span style="color:#000000">(valor) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> VariasVezes) </span><span style="color:#0000FF">AS</span><span style="color:#000000"> val</span></pre>
</div>
<p>Perceba que no select que consome a CTE eu a referenciei (“VariasVezes”) duas vezes. Cuidado que nas funções agregadas o conteúdo da CTE sofre scan para cada função agregada, e, dependendo,<em> uma abordagem diferente pode ser mais performática</em>, mas ganha-se muito com a legibilidade da query. Observe os scans no plano de execução da CTE VariasVezes.</p>
<p>Para facilitar a análise, segue o plano de execução em modo texto (instrução <em>SET SHOWPLAN_TEXT</em>). </p>
<p><font size="2" face="Courier New">StmtText<br />----------------------------------------------------------------------------------------------------------<br />  |--Compute Scalar(DEFINE:([Expr1012]=[Expr1004]+[Expr1010]))<br />       |--Nested Loops(Inner Join)<br />            |--Stream Aggregate(DEFINE:([Expr1004]=MAX([Union1003])))<br />            |    |--Concatenation<br />            |        </font><font size="2"><font face="Courier New"><strong>|--Constant Scan(VALUES:(((1))))<br /></strong>            | </font></font><font size="2"><font face="Courier New"><strong>        |--Constant Scan(VALUES:(((33))))<br /></strong>            |<strong>         |--Constant Scan(VALUES:(((8))))</strong><br />            |--Compute Scalar(DEFINE:([Expr1010]=CASE WHEN [Expr1019]=(0) THEN NULL ELSE [Expr1020] END))<br />                 |--Stream Aggregate(DEFINE:([Expr1019]=Count(*), [Expr1020]=SUM([Union1009])))<br />                      |--Concatenation<br />                          </font></font><strong><font size="2" face="Courier New">|--Constant Scan(VALUES:(((1))))<br />                           |--Constant Scan(VALUES:(((33))))<br />                           |--Constant Scan(VALUES:(((8))))</font></strong> </p>
<p>Essa característica já seria o suficiente para tornar o uso de CTEs muito interessante, mas na minha opinião a capacidade de auto-referenciar (queries recursivas) é que torna CTE um recurso tão poderoso.</p>
<p><strong>Queries Recursivas com Common Table Expressions</strong></p>
<p>Como já mencionei as CTEs podem se auto referenciar, isto é, dentro da própria definição da CTE.<br />Já ministrei diversos treinamentos em que CTE era um dos itens da ementa, e percebi que o melhor jeito de entender o funcionamento das mesmas é através de exemplos. Começarei com alguns simples e vou até alguns mais elaborados, com o passo a passo de cada execução para facilitar. :)</p>
<p>Vamos pensar um pouco, em que seria interessante a utilização de uma query recursiva? O exemplo clássico seria o cálculo de fatorial (faremos mais adiante), geração de números sequênciais, etc, etc.</p>
<p>Mas para usar uma CTE recursiva basta apenas referenciar ela mesma? Sim e não, na verdade não. É necessário a utilização do operador UNION ALL além da introdução de dois novos termos/conceitos: Membro Âncora e o Membro Recursivo. Segue a estruturação na forma de um exemplo que gera números sequênciais de 1 até 10:</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> NumerosSequenciais(num)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#008080">--</span><span style="color:#008080"> Este é o membro âncora, será o primeiro a ser executado. </span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> Fará a ligação do membro âncora com o membro recursivo.</span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> num </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais
     </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> num </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">10</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> perceba que o WHERE é bastante importante para delimitar a parada da recursão.</span><span style="color:#008080">
</span><span style="color:#000000">)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#808080">*</span><span style="color:#000000"> </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais</span></pre>
</div>
<p>Uma coisa comum, que vejo muitos se confundirem (o que é razoavél, uma vez que essa recursão é um pouco diferente das demais), é achar que o membro âncora será o critério de parada, e isso <strong>NÃO</strong> é verdade. Na realidade, ele é o primeiro a ser executado. O critério de parada é o membro recursivo parar de fornecer novas linhas de retorno para serem “processadas”. Veja a execução do passo a passo mais adiante.</p>
<p>Segue mais um exemplo, mas agora manipulando um elemento do tipo VARCHAR. Um ponto importante a se observar é que não funcionará sem a utilização da função CONVERT, e se deve ao fato de que os (os? veja adiante) membros âncoras e recursicos (plural novamente? veja adiante)  devem retornar o mesmo tipo de dado em cada coluna (no caso, VARCHAR(4000)).</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> Nome(nome)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),</span><span style="color:#FF0000">'</span><span style="color:#FF0000">Thiago</span><span style="color:#FF0000">'</span><span style="color:#000000">)
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#FF0000">'</span><span style="color:#FF0000">Zavaschi</span><span style="color:#FF0000">'</span><span style="color:#000000">) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome
    </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> </span><span style="color:#FF00FF">LEN</span><span style="color:#000000">(nome) </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">30</span><span style="color:#000000">
)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome</span></pre>
</div>
<p>O resultado da query recursiva acima é:</p>
<p><font size="2" face="Courier New">Thiago<br />ThiagoZavaschi<br />ThiagoZavaschiZavaschi<br />ThiagoZavaschiZavaschiZavaschi</font> </p>
<p><strong>Queries recursivas com mais de um membro âncora/recursivo</strong></p>
<p>Aqui é que as coisas podem parecer confusas (e até são de certo modo), tenho que confessar que nunca (que eu me lembre) precisei usar mais de um membro recursivo na mesma CTE, mas devemos conhecer todas as possibilidades!</p>
<p>Vamos voltar a query anterior que concatenava ‘Zavaschi’ ao nome ‘Thiago’ e adicionarei um novo âncora.</p>
<p>Mas e como fazer isso? Basta adicionar mais um SELECT que não faça referência à propria CTE (senão seria um membro recursivo, hehe). o resultado fica algo parecido com:</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> Nome(nome)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),</span><span style="color:#FF0000">'</span><span style="color:#FF0000">Thiago</span><span style="color:#FF0000">'</span><span style="color:#000000">)
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),</span><span style="color:#FF0000">'</span><span style="color:#FF0000">José</span><span style="color:#FF0000">'</span><span style="color:#000000">)
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#FF0000">'</span><span style="color:#FF0000">Zavaschi</span><span style="color:#FF0000">'</span><span style="color:#000000">) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome
    </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> </span><span style="color:#FF00FF">LEN</span><span style="color:#000000">(nome) </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">30</span><span style="color:#000000">
)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome</span></pre>
</div>
<p>Conseguem imaginar o que irá acontecer? Na verdade o que eu acho que um desenvolvedor tem que se preocupar é a ORDEM com que será retornado os registros (supondo que já haja um entendimento sobre CTEs).</p>
<p>O resultado desta query é:</p>
<p><font size="2" face="Courier New">nome<br />-------------------------------------<br />Thiago<br />José<br />JoséZavaschi<br />JoséZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschiZavaschi<br />ThiagoZavaschi<br />ThiagoZavaschiZavaschi<br />ThiagoZavaschiZavaschiZavaschi</font> </p>
<p>(9 row(s) affected) </p>
<p>Por que isso ocorre? Ou melhor, “me explica o que ocorreu”. Vamos lá! Obs: vou ir negritando os registros e colocando a query que foi “executada” para facilitar no entendimento do output encontrado. </p>
<p>1) Como a “parte” que é executada primeiro é a da âncora, ou das âncoras, e por ordem no UNIOL ALL, temos o ‘Thiago’ e depois o ‘José’. </p>
<p><font size="2" face="Courier New">SELECT nome = CONVERT(VARCHAR(4000),'Thiago')<br />UNION ALL<br />SELECT nome = CONVERT(VARCHAR(4000),'José')</font> </p>
<p><font size="2"><font face="Courier New"><strong>Thiago<br />José</strong><br />JoséZavaschi<br />JoséZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschiZavaschi<br />ThiagoZavaschi<br />ThiagoZavaschiZavaschi<br />ThiagoZavaschiZavaschiZavaschi</font></font> </p>
<p>2) Foram executados os âncoras agora é a vez da execução do membro recursivo.</p>
<p><font size="2" face="Courier New">SELECT CONVERT(VARCHAR(4000),nome + 'Zavaschi') FROM Nome<br />    WHERE LEN(nome) &lt; 30</font> </p>
<p>O conteúdo do “nome” atual é “José” (última âncora selecionada), perceba que no FROM temos referenciada a própria CTE! </p>
<p>A execução da query seria algo como (de maneira BEM simplificada):</p>
<p><font size="2" face="Courier New">SELECT ‘José’ + 'Zavaschi' WHERE LEN(‘José’ + 'Zavaschi') &lt; 30</font></p>
<p>Esse registro retornou alguma linha? Sim. então continua processando esta query recursiva.</p>
<p><font size="2"><font face="Courier New"><strong>Thiago<br />José</strong><br /></font></font><font size="2"><font face="Courier New"><strong>JoséZavaschi<br /></strong>JoséZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschiZavaschi<br />ThiagoZavaschi<br />ThiagoZavaschiZavaschi<br />ThiagoZavaschiZavaschiZavaschi</font></font> </p>
<p>3) Mas qual é o conteúdo do “nome” neste momento? “JoséZavaschi”.</p>
<p>A query recursiva retorna mais alguma linha (atentar para o WHERE)? Sim. entao retorna o valor presente em “nome” e continua.<br />O processo se mantém enquanto o conteúdo de “nome” atender à nossa restrição no WHERE (o WHERE é feito com o conteúdo de nome da iteracao anterior, ANTES, da concatenação).</p>
<p><font size="2"><font face="Courier New"><strong>Thiago<br />José</strong><br /></font></font><font size="2"><font face="Courier New"><strong>JoséZavaschi<br />JoséZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschiZavaschi</strong><br />ThiagoZavaschi<br />ThiagoZavaschiZavaschi<br />ThiagoZavaschiZavaschiZavaschi</font></font> </p>
<p>4) o Conteúdo de “nome” agora é:  JoséZavaschiZavaschiZavaschiZavaschi que possui mais de 30 caracteres, então a query recursiva não retorna mais registros e se encerra…ria, caso só tivéssemos uma única âncora. Mas o processo continua para a âncora anterior e assim por diante. E é por isto que temos a saída do Thiago, ThiagoZavaschi, e assim por diante.</p>
<p><font size="2"><font face="Courier New"><strong>Thiago<br />José</strong><br /></font></font><font size="2"><font face="Courier New"><strong>JoséZavaschi<br />JoséZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschi<br />JoséZavaschiZavaschiZavaschiZavaschi</strong><br /></font></font><strong><font size="2" face="Courier New">ThiagoZavaschi<br />ThiagoZavaschiZavaschi<br />ThiagoZavaschiZavaschiZavaschi</font></strong> </p>
<p>5) Quando a query recursiva não retornar mais nada, a CTE verifica se há alguma outra âncora “esperando”, se não há então já temos o result set que servirá de base para o SELECT, INSERT, DELETE, etc., que estiver após a CTE. Caso tenha uma outra âncora, esta será processada e assim por diante.</p>
<p>---</p>
<p>E para mais de um membro recursivo, como ficaria? Bem não vou fazer execução detalha, pois ficaria muito grande e seria muito repetitivo, mas vejam os seguintes scripts (e os testem).</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> Nome(nome)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),</span><span style="color:#FF0000">'</span><span style="color:#FF0000">Thiago</span><span style="color:#FF0000">'</span><span style="color:#000000">)
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#FF0000">'</span><span style="color:#FF0000">Zavaschi</span><span style="color:#FF0000">'</span><span style="color:#000000">) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome
    </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> </span><span style="color:#FF00FF">LEN</span><span style="color:#000000">(nome) </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">30</span><span style="color:#000000">
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#FF0000">'</span><span style="color:#FF0000">Silva</span><span style="color:#FF0000">'</span><span style="color:#000000">) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome
    </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> </span><span style="color:#FF00FF">LEN</span><span style="color:#000000">(nome) </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">30</span><span style="color:#000000">
)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome</span></pre>
</div>
<p>Para esse teremos (omitindo o output): <br />(39 row(s) affected)</p>
<p>E se colocarmos mais uma âncora? Vai dobrar o número de resultados, certo? Errado. Esqueceu do WHERE LEN(nome) &lt; 30?</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> Nome(nome)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),</span><span style="color:#FF0000">'</span><span style="color:#FF0000">Thiago</span><span style="color:#FF0000">'</span><span style="color:#000000">)
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#808080">=</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),</span><span style="color:#FF0000">'</span><span style="color:#FF0000">José</span><span style="color:#FF0000">'</span><span style="color:#000000">)
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#FF0000">'</span><span style="color:#FF0000">Zavaschi</span><span style="color:#FF0000">'</span><span style="color:#000000">) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome
    </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> </span><span style="color:#FF00FF">LEN</span><span style="color:#000000">(nome) </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">30</span><span style="color:#000000">
    </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000">
    </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#FF00FF">CONVERT</span><span style="color:#000000">(</span><span style="color:#0000FF">VARCHAR</span><span style="color:#000000">(</span><span style="color:#800000;font-weight:bold">4000</span><span style="color:#000000">),nome </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#FF0000">'</span><span style="color:#FF0000">Silva</span><span style="color:#FF0000">'</span><span style="color:#000000">) </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome
    </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> </span><span style="color:#FF00FF">LEN</span><span style="color:#000000">(nome) </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">30</span><span style="color:#000000">
)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> nome </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> Nome</span></pre>
</div>
<p>Se utilizarmos os mesmos valores para âncoras e nas partes recursivas aí sim a adição de um âncora dobraria o total atual de registros retornados.</p>
<p>--</p>
<p><strong>Limite de Recursividade</strong></p>
<p>Para este caso utilizarei um dos exemplos já mostrados:</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> NumerosSequenciais(num)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#008080">--</span><span style="color:#008080"> Este é o membro âncora, será o primeiro a ser executado. </span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> Fará a ligação do membro âncora com o membro recursivo.</span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> num </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais
     </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> num </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">10</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> perceba que o WHERE é bastante importante para delimitar a parada da recursão.</span><span style="color:#008080">
</span><span style="color:#000000">)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#808080">*</span><span style="color:#000000"> </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais</span></pre>
</div>
<p>É conhecido que o resultado desta CTE será uma sequência de 1 até 10. A query a seguir retornaria o que?.</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> NumerosSequenciais(num)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#008080">--</span><span style="color:#008080"> Este é o membro âncora, será o primeiro a ser executado. </span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> Fará a ligação do membro âncora com o membro recursivo.</span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> num </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais
     </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> num </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1000</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> perceba que o WHERE é bastante importante para delimitar a parada da recursão.</span><span style="color:#008080">
</span><span style="color:#000000">)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#808080">*</span><span style="color:#000000"> </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais</span></pre>
</div>
<p>O que mudou foi o nosso “critério de parada” permitindo listar até o número 1000, e é isso que vai acontecer, certo?</p>
<p>Errado. A execução será interrompida em um certo momento e teremos um output semelhante a:</p>
<p><font size="2" face="Courier New">1<br />2<br />3<br />…<br />98<br />99<br />100<br />101<br /><font color="#ff0000">Msg 530, Level 16, State 1, Line 1<br />The statement terminated. The maximum recursion 100 has been exhausted before statement completion.</font></font></p>
<p><em>“Ahhhhm, não entendi.”</em></p>
<p>O SQL Server por padrão tem um mecanismo que serve para evitar que “descuidados” larguem queries recursivas infinitas, o que pode compromoter o desempenho do ambiente. É possível colocar um outro valor até o máximo de 32767. Basta adicionar ao final da query o hint: OPTION (maxrecursion &lt;n&gt;). No nosso exemplo anterior ficaria:</p>
<div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px">
<pre style="background-color:#F4F4F4;overflow:auto"><span style="color:#000000">;</span><span style="color:#0000FF">WITH</span><span style="color:#000000"> NumerosSequenciais(num)
</span><span style="color:#0000FF">AS</span><span style="color:#000000">
(
     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#008080">--</span><span style="color:#008080"> Este é o membro âncora, será o primeiro a ser executado. </span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">UNION</span><span style="color:#000000"> </span><span style="color:#808080">ALL</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> Fará a ligação do membro âncora com o membro recursivo.</span><span style="color:#008080">
</span><span style="color:#000000">     </span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> num </span><span style="color:#808080">+</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1</span><span style="color:#000000"> </span><span style="color:#0000FF">AS</span><span style="color:#000000"> num </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais
     </span><span style="color:#0000FF">WHERE</span><span style="color:#000000"> num </span><span style="color:#808080">&lt;</span><span style="color:#000000"> </span><span style="color:#800000;font-weight:bold">1000</span><span style="color:#000000"> </span><span style="color:#008080">--</span><span style="color:#008080"> perceba que o WHERE é bastante importante para delimitar a parada da recursão.</span><span style="color:#008080">
</span><span style="color:#000000">)
</span><span style="color:#0000FF">SELECT</span><span style="color:#000000"> </span><span style="color:#808080">*</span><span style="color:#000000"> </span><span style="color:#0000FF">FROM</span><span style="color:#000000"> NumerosSequenciais
</span><span style="color:#0000FF">OPTION</span><span style="color:#000000"> (maxrecursion </span><span style="color:#800000;font-weight:bold">3000</span><span style="color:#000000">)</span></pre>
</div>
<p>Ainda assim a sua recursividade passa do limite de 32767? Então avalie: </p>
<p>É REALMENTE necessária uma recursão maior que isso?</p>
<p>Não há uma maneira alternativa (e menos custosa) de executar a mesma tarefa? Normalmente há.</p>
<p>Nunca precisei na prática, mas é possível colocar “ilimitadas” recursões: basta colocar o valor do “maxrecursion” para 0.<br /><em>Mas lembro: eu, Thiago Zavaschi, não vejo isso como uma boa prática.</em></p>
<p><em>Continua no próximo post..</em></p>
</p>
</p>
</p>
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2009/09/entendendo-as-common-table-expressions-cte-parte-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Repostagem &#8211; Utilizando Campos Identity no SQL Server</title>
		<link>http://zavaschi.com/index.php/2009/06/repostagem-utilizando-campos-identity-no-sql-server/</link>
		<comments>http://zavaschi.com/index.php/2009/06/repostagem-utilizando-campos-identity-no-sql-server/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 00:08:00 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Identity]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://zavaschi.com/?p=43</guid>
		<description><![CDATA[Olá a todos!   Primeiramente gostaria de dizer que este é um post para o nível iniciante, e serve como base para aquelas perguntas “como é que eu fazia aquilo mesmo?”. É baseado em um mini artigo que escrevi, e este post também já publiquei no DevBR.
Em muitas ocasiões nos deparamos com situações em [...]]]></description>
			<content:encoded><![CDATA[<p>Olá a todos!   <br />Primeiramente gostaria de dizer que este é um post para o nível iniciante, e serve como base para aquelas perguntas “como é que eu fazia aquilo mesmo?”. É baseado em um mini artigo que escrevi, e este post também já publiquei no <a href="http://devbr.blogspot.com/">DevBR</a>.</p>
<p>Em muitas ocasiões nos deparamos com situações em que precisamos trabalhar em alguma coluna que seja <i>identity</i>. Este mini-artigo descreve alguns comandos úteis na manipulação destas colunas.</p>
<p><b>Criando uma tabela com campo <i>identity</i></b>: Devemos criar com o parâmetro <i>identity</i>, e configurar o primeiro valor, e o valor de incremento, respectivamente (<i>IDENTITY (&lt;inicio&gt;,&lt;incremento&gt;)</i>). Conforme no exemplo a seguir: </p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:de7a8aab-339b-4839-9945-26df5a70744d" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;overflow: auto;"><span style="color: #0000FF;">CREATE</span><span style="color: #000000;"> </span><span style="color: #0000FF;">TABLE</span><span style="color: #000000;"> Tabela (
      Id </span><span style="color: #0000FF;">INT</span><span style="color: #000000;"> </span><span style="color: #FF00FF;">IDENTITY</span><span style="color: #000000;"> (</span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">,</span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">) </span><span style="color: #0000FF;">PRIMARY</span><span style="color: #000000;"> </span><span style="color: #0000FF;">KEY</span><span style="color: #000000;">,
      Valor </span><span style="color: #0000FF;">VARCHAR</span><span style="color: #000000;">(</span><span style="color: #800000; font-weight: bold;">50</span><span style="color: #000000;">)
)</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p><b>Reiniciando o valor do campo <i>identity</i></b>: Algumas vezes precisamos alterar o valor do identity (para reiniciar a contagem, por exemplo). Há o comando <i>truncate</i> que além de limpar a tabela (entre outras coisas), também zera o valor do <i>identity</i>. No entanto, se o nosso objetivo é <b>apenas</b> trocar o valor do <i>identity</i>, o <i>truncate</i> não é uma saída interessante. Para manipular o <i>identity</i> podemos fazer como descrito a seguir: </p>
<p>Vamos imaginar que queremos que o próximo registro a ser inserido na tabela <i>Tabela </i>queremos que sua chave primária <i>Id</i>, se inicie em 1. </p>
<p>Para resolver esse problema, podemos usar a seguinte instrução: </p>
<p><b><i>DBCC CHECKIDENT (Tabela, reseed, 0)</i></b><b></b></p>
<p>O último parâmetro se torna o valor atual do <i>identity</i>. Ao inserir o próximo registro, o mesmo virá com o seu <i>Id</i> com o valor <i>identity</i> somado de 1 (caso seja um <i>identity</i> de incremento 1), o valor do <i>identity</i> da tabela vai para 1, e assim por diante. </p>
<p><b>Recuperar o último valor inserido de um campo <i>identity</i></b>: Para recuperar o último valor de <i>identity</i> inserido (ex: inserir algo em uma tabela, e cadastrar um novo registro com o id do registro recém inserido), podemos utilizar: </p>
<blockquote>
<p><b>@@IDENTITY</b>, que retorna o valor do <i>identity</i> do último registro inserido na tabela, ou; </p>
</blockquote>
<blockquote>
<p><b>SCOPE_IDENTITY()</b>, que retorna o último valor mas dentro do escopo em que a <i>query</i> foi executada. </p>
</blockquote>
<p>Não recomendo a utilização de @@IDENTITY, pois isso pode acarretar problemas de consistência em cenários onde existe um alto grau de inserção/manipulação dos dados no banco (ou mais especificamente, na tabela em questão). </p>
<p>Um exemplo simples de uso pode ser: </p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:5a8a28d4-8480-4e35-a84b-b6fe1fa23cb0" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;overflow: auto;"><span style="color: #0000FF;">DECLARE</span><span style="color: #000000;"> </span><span style="color: #008000;">@techId</span><span style="color: #000000;"> </span><span style="color: #0000FF;">INT</span><span style="color: #000000;">
</span><span style="color: #0000FF;">INSERT</span><span style="color: #000000;"> </span><span style="color: #0000FF;">INTO</span><span style="color: #000000;"> Tabela (Valor) </span><span style="color: #0000FF;">VALUES</span><span style="color: #000000;"> (‘Testando </span><span style="color: #FF00FF;">Identity</span><span style="color: #000000;">’)
</span><span style="color: #0000FF;">SELECT</span><span style="color: #000000;"> </span><span style="color: #008000;">@techId</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF00FF;">SCOPE_IDENTITY</span><span style="color: #000000;">()</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p><b></b></p>
<p>--- </p>
<p>Um complemento em relação ao post original:<br />
  <br /><em>”Zavaschi, e se eu quiser<strong> </strong><u>inserir um registro</u> em uma tabela, mas somente nessa inserção <u>quero especificar o valor do campo identity</u>. É possível?”</em></p>
<p>É sim, basta fazer da seguinte forma: </p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:9ce5c13a-6473-4c27-8145-d5aaa9ac3cdb" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;overflow: auto;"><span style="color: #0000FF;">SET</span><span style="color: #000000;"> </span><span style="color: #0000FF;">IDENTITY_INSERT</span><span style="color: #000000;"> Tabela </span><span style="color: #0000FF;">ON</span><span style="color: #000000;">
</span><span style="color: #0000FF;">INSERT</span><span style="color: #000000;"> </span><span style="color: #0000FF;">INTO</span><span style="color: #000000;"> Tabela (Id, Valor) </span><span style="color: #0000FF;">VALUES</span><span style="color: #000000;"> (</span><span style="color: #800000; font-weight: bold;">123</span><span style="color: #000000;">, ‘Informação’)
</span><span style="color: #0000FF;">SET</span><span style="color: #000000;"> </span><span style="color: #0000FF;">IDENTITY_INSERT</span><span style="color: #000000;"> Tabela </span><span style="color: #0000FF;">OFF</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>&#160;</p>
<p>Simples, mas temos que lembrar que precisamos explicitar os campos, ainda que estejamos fazendo uma inserção em todas as colunas. </p>
<p>É isso, espero que tenham gostado!<br />
  <br />Abraços!</p>
<p>Thiago Zavaschi</p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2009/06/repostagem-utilizando-campos-identity-no-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Repostagem &#8211; Database Mail &#8211; Configura&#231;&#227;o Atrav&#233;s de Scripts</title>
		<link>http://zavaschi.com/index.php/2009/06/repostagem-database-mail-configurao-atravs-de-scripts/</link>
		<comments>http://zavaschi.com/index.php/2009/06/repostagem-database-mail-configurao-atravs-de-scripts/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 22:51:00 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Database Mail]]></category>

		<guid isPermaLink="false">http://zavaschi.com/?p=35</guid>
		<description><![CDATA[DatabaseMail – Configuração através de scripts
Postei um tempo atrás um artigo sobre o DatabaseMail (aqui), mas era através dos menus de configuração. Hoje trago para vocês a realização da mesma tarefa, só que através de scripts.
Configurando o DatabaseMail

-- Cria uma account do Database Mail
EXECUTE msdb.dbo.sysmail_add_account_sp
    @account_name = 'SQL',
    @description [...]]]></description>
			<content:encoded><![CDATA[<h6>DatabaseMail – Configuração através de scripts</h6>
<p>Postei um tempo atrás um artigo sobre o DatabaseMail (<a title="http://zavaschi.com/?p=31" href="http://zavaschi.com/?p=31" target="_blank">aqui</a>), mas era através dos menus de configuração. Hoje trago para vocês a realização da mesma tarefa, só que através de scripts.</p>
<p><strong>Configurando o DatabaseMail</strong></p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:25820279-065e-4fd2-b1d5-c7531e6f1ba8" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;overflow: auto;"><span style="color: #008080;">--</span><span style="color: #008080;"> Cria uma account do Database Mail</span><span style="color: #008080;">
</span><span style="color: #0000FF;">EXECUTE</span><span style="color: #000000;"> msdb.dbo.sysmail_add_account_sp
    </span><span style="color: #008000;">@account_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">SQL</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
    </span><span style="color: #008000;">@description</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Conta de email para o envio do
    email na rotina de log de erro.</span><span style="color: #FF0000;">'</span><span style="color: #000000;">, </span><span style="color: #008080;">--</span><span style="color: #008080;"> Uma descrição para a sua account</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">@email_address</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">sql@zavaschi.com</span><span style="color: #FF0000;">'</span><span style="color: #000000;">, </span><span style="color: #008080;">--</span><span style="color: #008080;"> Email que será </span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008080;">--</span><span style="color: #008080;"> mostrado como o emissor</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">@replyto_address</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">sql@zavaschi.com</span><span style="color: #FF0000;">'</span><span style="color: #000000;">, </span><span style="color: #008080;">--</span><span style="color: #008080;"> Email de reply</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">@display_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">SQL Server</span><span style="color: #FF0000;">'</span><span style="color: #000000;">, </span><span style="color: #008080;">--</span><span style="color: #008080;"> Nome mostrado no email enviado</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">@mailserver_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">smtp.zavaschi.com</span><span style="color: #FF0000;">'</span><span style="color: #000000;">, </span><span style="color: #008080;">--</span><span style="color: #008080;"> Servidor smtp</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">@port</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #800000; font-weight: bold;">25</span><span style="color: #000000;">, </span><span style="color: #008080;">--</span><span style="color: #008080;"> Porta</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">@username</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">sql</span><span style="color: #FF0000;">'</span><span style="color: #000000;">, </span><span style="color: #008080;">--</span><span style="color: #008080;"> Login do servidor de smtp</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">@password</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">sql</span><span style="color: #FF0000;">'</span><span style="color: #000000;">; </span><span style="color: #008080;">--</span><span style="color: #008080;"> senha do servidor de smtp </span><span style="color: #008080;">
</span><span style="color: #000000;">
</span><span style="color: #008080;">--</span><span style="color: #008080;"> Cria um profile do Database Mail</span><span style="color: #008080;">
</span><span style="color: #0000FF;">EXECUTE</span><span style="color: #000000;"> msdb.dbo.sysmail_add_profile_sp
    </span><span style="color: #008000;">@profile_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">SQL Profile</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
    </span><span style="color: #008000;">@description</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Profile usado para o
    envio do email na rotina de log de erro.</span><span style="color: #FF0000;">'</span><span style="color: #000000;"> ;
    </span><span style="color: #008080;">--</span><span style="color: #008080;"> Cria o profile </span><span style="color: #008080;">
</span><span style="color: #000000;">
</span><span style="color: #008080;">--</span><span style="color: #008080;"> Adiciona a account ao profile</span><span style="color: #008080;">
</span><span style="color: #0000FF;">EXECUTE</span><span style="color: #000000;"> msdb.dbo.sysmail_add_profileaccount_sp
    </span><span style="color: #008000;">@profile_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">SQL Profile</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
    </span><span style="color: #008000;">@account_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">SQL</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
    </span><span style="color: #008000;">@sequence_number</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;"> ; </span><span style="color: #008080;">--</span><span style="color: #008080;"> Associa a account ao profile, recém criados. </span><span style="color: #008080;">
</span><span style="color: #000000;">
</span><span style="color: #008080;">--</span><span style="color: #008080;"> Garante acesso ao profile a todos os usuarios da base msdb</span><span style="color: #008080;">
</span><span style="color: #0000FF;">EXECUTE</span><span style="color: #000000;"> msdb.dbo.sysmail_add_principalprofile_sp
    </span><span style="color: #008000;">@profile_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">SQL Profile</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
    </span><span style="color: #008000;">@principal_name</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">public</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
    </span><span style="color: #008000;">@is_default</span><span style="color: #000000;"> </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">; </span><span style="color: #008080;">--</span><span style="color: #008080;"> Configura o profile criado como público e padrão. </span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>&#160;</p>
<p>Pronto, só isso. E agora para enviar email é da mesma maneira: </p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:8b4e4535-6032-4c90-a0da-4b737c55ed49" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;overflow: auto;"><span style="color: #0000FF;">EXEC</span><span style="color: #000000;"> msdb.dbo.sp_send_dbmail </span><span style="color: #008000;">@profile_name</span><span style="color: #808080;">=</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">SQL Profile</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
</span><span style="color: #008000;">@recipients</span><span style="color: #808080;">=</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">sql@zavaschi.com</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
</span><span style="color: #008000;">@subject</span><span style="color: #808080;">=</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Titulo</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,
</span><span style="color: #008000;">@body</span><span style="color: #808080;">=</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Corpo da mensagem.</span><span style="color: #FF0000;">'</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>&#160;</p>
<p>Tranquilo né? Mas se ao executar a procedure de envio de email você obter o seguinte erro:</p>
<p><em>Msg 15281, Level 16, State 1, Procedure sp_send_dbmail, Line 0<br />
    <br />SQL Server blocked access to procedure 'dbo.sp_send_dbmail' of component 'Database Mail XPs' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Database Mail XPs' by using sp_configure. For more information about enabling 'Database Mail XPs', see &quot;Surface Area Configuration&quot; in SQL Server Books Online.</em> </p>
<p>É pelo fato do DatabaseMail estar desabilitado no seu SQL Server, então rode o seguinte script:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:c4412003-dd56-4a7d-98de-e6a9dd11f0af" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;overflow: auto;"><span style="color: #000000;">sp_configure </span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Database Mail XPs</span><span style="color: #FF0000;">'</span><span style="color: #000000;">, </span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">
</span><span style="color: #0000FF;">GO</span><span style="color: #000000;">
</span><span style="color: #0000FF;">RECONFIGURE</span><span style="color: #000000;"> </span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>Há alguns casos que não é possível executar o RECONFIGURE diretamente (sem entrar nos méritos)<br />
  <br />Executar então: RECONFIGURE WITH OVERRIDE </p>
<p>Espero que seja útil para você, acredito que sim, pois muitos me pedem! </p>
<p>Grande abraço!<br />
  <br />Thiago Zavaschi</p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2009/06/repostagem-database-mail-configurao-atravs-de-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Repostagem &#8211; Tutorial: Configurando o Database Mail</title>
		<link>http://zavaschi.com/index.php/2009/06/repostagem-tutorial-configurando-o-database-mail/</link>
		<comments>http://zavaschi.com/index.php/2009/06/repostagem-tutorial-configurando-o-database-mail/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 22:25:00 +0000</pubDate>
		<dc:creator>Thiago Zavaschi</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Database Mail]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLMail]]></category>

		<guid isPermaLink="false">http://zavaschi.com/?p=31</guid>
		<description><![CDATA[Então pessoal, sei que prometi o artigo de PowerPivot, mas estou finalizando-o ainda. Enquanto isso farei a repostagem de alguns posts do antigo blog que não vieram no processo de importação (não serão muitos).
Tutorial: Configurando o DatabaseMail
O Database Mail é a evolução do SQL Mail (método marcado como obsoleto e fadado a ser removido do [...]]]></description>
			<content:encoded><![CDATA[<p>Então pessoal, sei que prometi o artigo de PowerPivot, mas estou finalizando-o ainda. Enquanto isso farei a repostagem de alguns posts do antigo blog que não vieram no processo de importação (não serão muitos).</p>
<h6>Tutorial: Configurando o DatabaseMail</h6>
<p>O Database Mail é a evolução do SQL Mail (método marcado como obsoleto e fadado a ser removido do SQL Server em uma próxima versão) com melhorias. Se você por alguma razão utiliza o SQLMail com o SQL Server 2005 ou 2008, considere a mudança imediata. </p>
<p>O objetivo deste artigo é mostrar o wizard de configuração do DatabaseMail e demonstrar como enviar emails através do T-SQL, além de como verificar o status dos emails enviados. </p>
<p>A base deste tutorial é o novo SQL Server 2008, porém os passos são muito similares no SQL Server 2005. </p>
<p><strong>Configurando o Database Mail</strong></p>
<p>Abra a instância desejada, abra a janela Object Explorer, abra a pasta Management e clique duas vezes no “Database Mail” para abrir a seguinte janela: </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pkI8Ju4xmvZWkLK34H2eBSuLTySJrj94uuqlKluq4bZtZoA4lOfa2kG7pEUk3I4_dnt3AjYcezZ9Vim4LgoO92lpMZezXN5Z0/1.jpg" width="545" height="475" /></p>
<p>Iniciaomente somos deparados com a tela de boas vindas do wizard de configuração. Não há muito oq ue fazer aqui, podemos marcar para não ser exibida novamente e clicar em Next para prosseguir. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pkI8Ju4xmvZUEbcuMfea2SDWtM-2dcvRw3GN-7tUb2gm_GsXof4inDUMOO-GmFaokBf-l4uFfWEY1j0wz8F2u8yZAuCDcss1Z/2.jpg" width="547" height="477" /></p>
<p>Marque a opção “Set up Database Mail by performing the following tasks:” e clique em next. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pJHluSz34JUKCP5JLuakxJvnsfrPg3Hyj2-4GDgDdbVGj27ILkQqZEIpr_P-Xo2441dZEdsCS-iVuNsXqnLvN-Iva12nTVrj9/3.jpg" width="548" height="122" /></p>
<p>Caso o Database Mail não esteja habilitado você será indagado a habilitá-lo. Clique em Yes para ativar. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pJHluSz34JUJjHZI-mfS30_aElu37JwYvK0Ui_8pzHCH542p2xWvG4IiwlnDAhDJTD1llxOofind8LsN1_xhBKfHTHgMuMXxg/4.jpg" width="550" height="479" /></p>
<p>Dê um nome e uma descrição a conta. Após isto clique em “Add”. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pA8tj-i46Zj6kF4-TTS2uvfRRwqYr4VC5-FhNrBh-V4BbTLp7UEwLpMkOpy-s5uEn4Gd7LlvwqrutRmjqT-2_P0jQCEIZHCsI/5.jpg" width="551" height="471" /></p>
<p>Configure os dados pedidos: Nome, descrição, endereço de email, servidor smtp, e assim por diante. Clique em Ok quando terminar. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pAXvcwLfoqCGuLF4YpT6ARAOJ7bnGXMv5byCKZSD_jcvDkSPajqcmPj7FCSzV1r9j7_fsIwyqLjneN8Ox6KNX6RW2i5q7QBs0/7.jpg" width="551" height="480" /></p>
<p>Clique em next para prosseguir. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1p-A-eYryOfXiUjF_ajwCDWmO2GC-PvOXFiIstQ7O4lla3SLyIBUHuKoAjgdCulAEnQCwwyV_tLEXjK6v64fZdcjUzOmq7HePy/8.jpg" width="548" height="477" /></p>
<p>Aqui estou tornando essa configuração pública (marcando a checkbox “public”) e tornando o perfil padrão. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pyz_Ux97q3EDgRN98m-ofigs2YSRG0zUQHeit0WAIEU8ix9-GDFq-dmbViJhNEsQ7KZjkyOzzVVnhob3klonVwZz9TyrIfLoA/9.jpg" width="545" height="475" /></p>
<p>Agora é a hora de configurar alguns parâmetros de sistema, como por exemplo, a extensão de arquivos que não podem ser enviados ao utilizar o database mail.    <br />Após configurar como desejar, clique em next. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pyz_Ux97q3EC-w5--0A4y7NVhyGy9F-_QhHv7Nghmait3_U3wBVQW88rMDJ2M33cuSx9H2mqzZhQPVCOW6jLt8ty30AZkkC_-/10.jpg" width="548" height="477" /></p>
<p>Clique em finish para encerrar o wizard e terminar de configurar a sua conta. </p>
<p><img src="http://a5ceig.blu.livefilestore.com/y1pJEvYfQNCBvcfH8Sz2vqByXkWNiFGMkoBHPVdpIEVYyX_Z3eGZgqg4GxvJXBNxL8S76boCmg7FB3oj9zKc8QpZMoW4Ta0GHjC/11.jpg" width="548" height="477" /></p>
<p>Esta tela mostra o progresso da configuração. Repare na coluna status, pois ela fornece a informação de se a tarefa foi bem sucedida ou não. Clique em close para encerrar. </p>
<p><strong>Enviando emails</strong></p>
<p>Para enviar emails através do DatabaseMail é bastante simples. </p>
<p>É necessário primeiramente executar a seguinte configuração para garantir que não haverá problemas: </p>
<p><strong>sp_configure 'show advanced', 1      <br />GO       <br />RECONFIGURE       <br />GO       <br />sp_configure 'Database Mail XPs', 1       <br />GO       <br />RECONFIGURE       <br />GO</strong></p>
<p>Na sequência podemos utilizar a stored procedure de sistema denominada: <em>sp_send_dbmail</em>, cuja sintaxe é mostrada a seguir (para mais detalhes consulte o books online):</p>
<pre><b>sp_send_dbmail</b> [ [ <b>@profile_name</b> <b>=</b> ] <b>'</b><i>profile_name</i><b>'</b> ]
    [ <b>,</b> [ <b>@recipients</b> <b>=</b> ] <b>'</b><i>recipients</i> [ <i>;</i> <i>...n </i>]<b>'</b> ]
    [ <b>,</b> [ <b>@copy_recipients</b> <b>=</b> ] <b>'</b><i>copy_recipient</i> [ <i>; ...n </i>]<b>'</b> ]
    [ <b>,</b> [ <b>@blind_copy_recipients</b> = ] '<i>blind_copy_recipient</i> [ <i>; ...n </i>]<b>'</b> ]
    [ <b>,</b> [ <b>@subject</b> <b>=</b> ] <b>'</b><i>subject</i><b>'</b> ]
    [ <b>,</b> [ <b>@body</b> <b>=</b> ] <b>'</b><i>body</i><b>'</b> ]
    [ <b>,</b> [ <b>@body_format</b> <b>=</b> ] <b>'</b><i>body_format</i><b>'</b> ]
    [ <b>,</b> [ <b>@importance</b> <b>=</b> ] <b>'</b><i>importance</i><b>'</b> ]
    [ <b>,</b> [ <b>@sensitivity</b> <b>=</b> ] <b>'</b><i>sensitivity</i><b>'</b> ]
    [ <b>,</b> [ <b>@file_attachments</b> <b>=</b> ] <b>'</b><i>attachment</i> [ <i>; ...n </i>]<b>'</b> ]
    [ <b>,</b> [ <b>@query</b> <b>=</b> ] '<i>query</i>' ]
    [ <b>,</b> [ <b>@execute_query_database</b> <b>=</b> ] <b>'</b><i>execute_query_database</i><b>'</b> ]
    [ <b>,</b> [ <b>@attach_query_result_as_file</b> <b>=</b> ] <i>attach_query_result_as_file</i> ]
    [ <b>,</b> [ <b>@query_attachment_filename</b> <b>=</b> ] <i>query_attachment_filename</i> ]
    [ <b>,</b> [ <b>@query_result_header</b> <b>=</b> ] <i>query_result_header</i> ]
    [ <b>,</b> [ <b>@query_result_width</b> <b>=</b> ] <i>query_result_width</i> ]
    [ <b>,</b> [ <b>@query_result_separator</b> <b>=</b> ] '<i>query_result_separator</i>' ]
    [ <b>,</b> [ <b>@exclude_query_output</b> <b>=</b> ] <i>exclude_query_output</i> ]
    [ <b>,</b> [ <b>@append_query_error</b> <b>=</b> ] append<i>_query_error</i> ]
    [ <b>,</b> [ <b>@query_no_truncate</b> <b>=</b> ] <i>query_no_truncate</i> ]
    [ <b>,</b> [ <b>@mailitem_id</b> <b>=</b> ] <i>mailitem_id</i> ] [ OUTPUT ]</pre>
<pre>Segue um exemplo prático de envio de email:</pre>
<p><strong>USE msdb<br />
    <br />GO</strong></p>
<blockquote>
<p><strong>EXEC sp_send_dbmail @profile_name='Zavaschi', -– Coloque o profile desejado.<br />
      <br />@recipients='thiagoh@techresult.com.br', – Coloque os receptores da mensagem. </p>
<p>@subject='Título da Mensagem', </p>
<p>@body='Corpo da mensagem. </p>
<p>E-mail recebido através do database mail do SQL Server!!!!'</strong></p>
</blockquote>
<p>Note que o envio não é disparado necessariamente na hora, ele é posto numa fila e o envio dependerá das condições da rede e de conectividade. </p>
<p>Podemos analisar as mensagens e o status do envio das mesmas, através dos seguintes comandos de seleção: </p>
<p><strong>SELECT * FROM sysmail_mailitems<br />
    <br />GO </p>
<p>SELECT * FROM sysmail_log </p>
<p>GO</strong></p>
<p>É isso, abraços pessoal!<br />
  <br />Thiago Zavaschi</p>
]]></content:encoded>
			<wfw:commentRss>http://zavaschi.com/index.php/2009/06/repostagem-tutorial-configurando-o-database-mail/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

