Prof. Daniel Oliveira

03/10/2011

Notas de aula sobre modelagem de Banco de Dados

Segue o material com as notas de aula (resumão) sobre modelagem conceitural e lógico de banco de dados. Abordando normalização de banco de dados relacionais. Aqui

29/04/2010

SQL Server 2008 R2 launch

Filed under: Banco de Dados,SQL Server — danielbarbosa77 @ 7:31
Tags: ,

Tá aí a palestra que fiz para o evento de launch do SQL Server 2008 R2, na FAESA em Março.

SQL Server 2008 R2 .

16/07/2009

Fazendo upload de imagens no SQL Server 2005 com ASP.NET

Filed under: .NET,Banco de Dados,Desenvolvimento,SQL Server — danielbarbosa77 @ 13:57
Tags: , , ,

Até o Sql server 2000 tinha-se o tipo de dados image para o armazenamento de informações binárias de até 2Gb no banco de dados, mas, com o lançamento do SQL Server 2005 surgiu o tipo de dados varbinary(max), o tipo image ainda continua existindo apenas para compatibilidade com a versão anterior.

Então, qual ou quais diferenças entre o tipo novo varbinary(max) e o image? Este novo tipo tem funcionalidades similar a sua contraparte varbinary(n). Pode-se definir variáveis desse tipo, podendo armazenar nas mesma até 2Gb de informação (atitude não muito normal, mas…), ainda, podemos utilizar este novo tipo de dados em cursores, variáves, utilizando com funções e referenciando na clausula where de um select.

O nosso exemplo de utilização do ASP.NET para upload de imagens será constituído por uma página de upload (exemplificando a forma de carga), uma página para download da imagen armazenada e uma página contendo um grid exibindo o nome original do arquivo, uma opção para download do arquivo e um preview do arquivo no grid – todo este projeto foi desenvolvimento utilizando o Visual Studio 2008.

Inicialmente vamos criar a nossa tabela para conter os arquivos, segue o script de criação:


CREATE TABLE [dbo].[Objetos](

[CD_OBJETO] [int] IDENTITY(1,1) NOT NULL,

[OBJETO] [varbinary](max) NOT NULL,

[FileName] [nvarchar](300) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,

CONSTRAINT [PK_Objetos] PRIMARY KEY CLUSTERED ([CD_OBJETO] ASC)

)

Devido a facilidade para se armazenar estas informações no banco de dados o código para o upload é bem simples:


conn.ConnectionString = ConfigurationManager.ConnectionStrings["TesteDB"].ConnectionString.ToString();

SqlCommand comm = new SqlCommand("insert into objetos (objeto,filename) values(@objeto,@filename)", conn);

comm.Parameters.Add("@objeto", SqlDbType.Image);

comm.Parameters["@objeto"].Direction = ParameterDirection.Input;

comm.Parameters["@objeto"].Value = FileUpload1.FileBytes;

comm.Parameters.Add("@filename", SqlDbType.NVarChar, 300);

comm.Parameters["@filename"].Value = FileUpload1.FileName;

conn.Open();

comm.ExecuteNonQuery();

Aqui utilizei o componente FileUpload do ASP.NET e este componente me expõe o arquivo carregado através do atributo FileBytes, que é uma array de bytes. Para atribuir estes bytes ao parâmetro bastou passar estes valores para a propriedade value do parametro e mais nada. Ao executar o comando ExecuteNonQuery a informação é armazenada no banco de dados. No exemplo construído aborda outras informações podem ser obtidas do componente FileUpload.

Para a recuperação dessas informações do banco de dados utilizei o seguinte código:


conn.ConnectionString = ConfigurationManager.ConnectionStrings["TesteDB"].ConnectionString.ToString();

//Obter as informações do arquivo

SqlCommand comm = new SqlCommand("select filename,objeto from objetos where cd_objeto = @cd_objeto", conn);

comm.Parameters.Add("@cd_objeto", SqlDbType.Int);

comm.Parameters["@cd_objeto"].Value = mCodigo;

conn.Open();

SqlDataReader dr = comm.ExecuteReader();

dr.Read();

FileName = dr["filename"].ToString();

//Lê os dados binários

blob = new Byte[(dr.GetBytes(1, 0, null, 0, int.MaxValue))];

dr.GetBytes(1, 0, blob, 0, blob.Length);

dr.Close();

conn.Close();

//Response.TransmitFile

Response.ContentType = GetContentMimeType(FileName);

if(mDownload)

Response.AddHeader("content-disposition", "attachment;filename=" + FileName);

Response.OutputStream.Write(blob, 0, blob.Length);

Response.Flush();

É realizada um select na base de dados para recuperar um arquivo específico, e para a recuperação das informações binárias devemos utilizar o método GetBytes do DataReader passando para o mesmo a posição do campo a ter as informações binárias lidas e o um buffer para a recuperação da informação.

No projeto de exemplo pode-se utilizar a página de upload: upload.aspx para a cargas dos arquivos e a página ViewObjetos.aspx para a visualização de um grid contendo as imagens. A página ShowObjeto.aspx contém a rotina para recuperação de uma imagem no banco de dados e descarregá-la no stream http, esta técnica é muito utilizada para exibição de imagens em grids e outros componentes Dataware que suportem templates. Nesta página ainda podemos descarregar as informações diretamente no stream Response (as imagens são exibidas no navegador) ou podemos exibir a janela de download para que o usuario grave a imagem no disco diretamente (muito util para arquivos que não são imagens).  Isto é feito pela introdução do cabeçlho HTTP:

Response.AddHeader("content-disposition", "attachment;filename=" + FileName); 

Isto diz ao navegados que existe um anexo ao conteúdo HTTP. Podemos ainda introduzir nessa funcionalidade a geração de thumbnails de imgem (um bom próximo tópico no blog….). Outra coisa importante é configurar corretamente o Content-Type (é através dessa propriedade que navegador saberá qual o tipo de arquivo está anexado ao protocolo HTTP), no exemplo o content-type é determinado pela extensão do arquivo original.


private string GetContentMimeType(string FileName)

{

string ret = "application/octet-stream";

string extensao = System.IO.Path.GetExtension(FileName).ToUpper();

switch (extensao)

{

case ".HTML": ret = "text/html"; break;

case ".HTM": ret = "text/html"; break;

case ".DOC": ret = "application/msword"; break;

case ".DOCX": ret = "application/msword"; break;

case ".XLS": ret = "application/x-msexcel"; break;

case ".XLSX": ret = "application/x-msexcel"; break;

case ".ZIP": ret = "application/zip"; break;

}

return ret;

}

O arquivo do projeto pode ser baixado aqui.

T+

15/07/2009

Recurso de PIVOT no SQL Server

Filed under: Banco de Dados,SQL Server — danielbarbosa77 @ 18:56
Tags: , ,

É muito comum a necessidade da exibição de informações tabular aonde as colunas são valores contidos em registros, esta técnica é conhecida como pivoteamento. Vamos considerar o seguinte exemplo:

Cliente              Ano         Valor
——————– ———– ———————
João                 2004        1027,00
Pedro                2001        1111,00
João                 2005        1018,00
Pedro                2005        1031,00
Paulo                2002        1099,00
João                 2004        1084,00

……                               ……               …….

O problema ocorre quando queremos exibir as vendas por cliente e com o ano em colunas. Esta técnica é chamada de pivoteamento, pois, é necessário exibir um valor que naturalmente está em linha para uma posição em coluna. No Excel isto é uma moleza, mas, dentro de consultas SQL não é tão simples assim. Até o SQL Server 2000 utilizávamos uma combinação de instrução select e case para realizar esta tarefa. Um exemplo de SQL para esta tarefa seria:


select

Cliente,

sum(ano2001) as '2001',

sum(ano2002) as '2002',

sum(ano2003) as '2003'

from

(

select

cliente,

case

when (ano=2001) then valor

else 0.00 end as Ano2001,

case

when (ano=2002) then valor

else 0.00 end as Ano2002,

case

when (ano=2003) then valor

else 0.00 end as Ano2003

from lancamentos

) A

group by Cliente

Mas, com o SQL Server 2008 esta tarefa foi simplificada com a introdução do comando PIVOT:


select cliente,[2001] as '2001',[2002] as '2002',[2003] as '2003'

from (

select valor,cliente,ano

from lancamentos

) p

pivot

(

sum(valor)

for ano in ([2001],[2002],[2003])

) pvt

Tendo como resultado:

cliente              2001                  2002                  2003
——————– ——————— ——————— ———————
Pedro                59685,00              49346,00              52961,00
Daniel               44000,00              43456,00              59661,00
Paulo                52024,00              40261,00              41441,00
João                 45467,00              39211,00              45402,00

Este comando é bem legal, mas, temos uma questão. Reparem que foi fixado o número de anos, mas e no caso de novos serem acrescidos na base de dados? Teremos que alterar as nossas consultas!

Mas podemos desenvolver um código que dinamicamente introduz os novos valores de anos:


--Variável de tipo tabela para conter todos os anos

declare @tblAnos as table (y int not null primary key)

insert into @tblAnos

select distinct ano from lancamentos order by ano asc

declare @cols as nvarchar(max),@anos int

set @anos = (select min(y) from @tblAnos)

--Variável para conter a relação de anos

set @cols = N''

--Montagem da relação de anos

while (@anos is not null)

begin

set @cols = @cols+N',[' + cast(@anos as nvarchar(10))+ N']'

set @anos = (select min(y) from @tblanos where y > @anos)

end

set @cols = substring(@cols,2,len(@cols))

--Construção da query para execução

declare @sql as nvarchar(max)

set @sql = N'Select * from (select cliente,ano,valor from dbo.lancamentos) as p

pivot (sum(valor) for ano in (' + @cols + N')) as pv'

--Utilização do comando Execute para execução da query dinâmica

execute(@sql)

T+

Tema: Rubric. Blog no WordPress.com.

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Join 421 other followers