Friday, July 27, 2007

SQL: Actualizar um campo do tipo Text ou NText

Um campo Text ou NText é tratado de forma um pouco diferente dos datatypes mais habituais do SQL (os int, varchar, char, etc...). Uma das diferenças é precisamente na forma como são feitas actualizaçãoes dos conteúdos de campos deste tipo.

O exemplo seguinte mostra um replace sobre um campo do tipo varchar:

create table #minhatabela (meucampo varchar(50))

insert #minhatabela values('meu teste')
select * from #minhatabela


update #minhatabela set meucampo = replace(meucampo, 'meu ', 'meu novo ')
select * from #minhatabela


drop table #minhatabela

No entanto, fazer a mesma coisa sobre um campo do tipo Text ou Ntext retorna um erro, como mostra o exemplo seguinte:

create table #minhatabela (meucampo text)

insert #minhatabela values('meu teste')
select * from #minhatabela

update #minhatabela set meucampo = replace(meucampo, 'meu ', 'meu novo ')
select * from #minhatabela

drop table #minhatabela

Este pequeno script SQL retorn o seguinte erro:

Msg 8116, Level 16, State 1, Line 6
Argument data type text is invalid for argument 1 of replace function.


Actualizar o campo do tipo Text ou NText

Então para actualizar um campo do tipo Text ou NText, é necessário utilizar um apontador para o campo a actualizar. Esse apontador deverá ser do tipo binary.
É ainda necessário identificar a posição a partir da qual se pretende actualizar.
Depois, identificando a tabela a actualizar, o apontador, a posição inicial, e o que se pretende fazer, utilizamos a instrução UPDATETEXT.

A instrução UPDATETEXT pode ser utilizada de diferentes formas: para inserir caracteres no inicio, no meio, no fim do campo, ou simplesmente para eliminar dados.

Segue-se um exemplo que inclui as diferentes utilizações da instrução UPDATETEXT:

create table #minhatabela (meucampo ntext)

insert #minhatabela values('bd')

DECLARE @ptrval binary(16), @i int

SELECT @ptrval = TEXTPTR(meucampo) FROM #minhatabela

-- Insere o caracter 'a' no inicio do conteudo do campo
UPDATETEXT #minhatabela.meucampo @ptrval 0 0 'a'
select * from #minhatabela

-- Insere o caracter 'c' no meio do conteudo do campo
UPDATETEXT #minhatabela.meucampo @ptrval 2 0 'c'
select * from #minhatabela

-- Insere o caracter 'e' no fim do conteudo do campo
set @i=(select DATALENGTH(meucampo) from #minhatabela)/2 -- Utilizar 2 apenas se se tratar de um campo do tipo NText (2 bytes/character)
UPDATETEXT #minhatabela.meucampo @ptrval @i 0 'e'
select * from #minhatabela

-- Elimina o primeiro caracter do conteudo do campo
UPDATETEXT #minhatabela.meucampo @ptrval 0 1
select * from #minhatabela

drop table #minhatabela

Length de campos Text ou NText

Apenas uma nota final. Mais uma das diferenças no tratamento deste tipo de datatypes é na utilização de instruções que permitam obter o tamanho do conteudo do campo. Usualmente é utilizada a instrução LEN, mas com campos do tipo Text e NText, a utilização desta instrução devolve um erro. Assim, a instrução a utilizar para obter o tamanho do conteúdo de um campo do tipo Text ou NText é a instrução DATALENGTH, de resto já utilizada nos exemplos acima.


E pronto! Estas foram algumas considerações sobre a manipulação de campos do tipo Text ou NText.
Um site que contém mais informação sobre a manipulação de campos deste tipo é este: http://msdn2.microsoft.com/en-us/library/aa175795(sql.80).aspx

Have fun! :)

Monday, June 4, 2007

DTS no SQL Server 2005

Para quem ainda não "domina" a construção de DTS com o SQL Server 2005, aqui ficam uns links que podem ser úteis.

Creating your first DTS Project:
http://www.extremeexperts.com/sql/Yukon/YukonDTS.aspx

Introduction to DTS in SQL Server 2005:
http://www.sqlservercentral.com/columnists/vkumar/introductiontodtsinsqlserver2005.asp

E já agora, por curiosidade...

O Yukon:
http://www.codeproject.com/useritems/Features_of_Yukon.asp

Divirtam-se! ;)

Tuesday, May 22, 2007

O protocolo HTTP - um pequeno review...

O protocolo HTTP disponibiliza dois tipos de operações:

- HTTP Requests
- HTTP Responses

Em que consistem? Ora então, muito resumidadmente...

HTTP Requests
Um HTTP Request consiste num request method, um request URL, header fields, e um body.

O HTTP 1.1 define os seguintes request methods:
GET: Devolve o recurso identificado pelo request URL
HEAD: Devolve os headers identificados pelo request URL
POST: Envia dados de tamanho ilimitado para o Web Server
PUT: Armazena um recurso sob o request URL
DELETE: Remove o recurso identificado pelo request URL
OPTIONS: Devolve os HTTP methods que o servidor suporta
TRACE: Devolve os header fields enviados com o TRACE request

O HTTP 1.0 inclui apenas os seguintes request methods: GET, HEAD e POST.

HTTP Responses
Um HTTP response contém um result code, header fields e um body.

O protocolo HTTP espera que o result code e todos os header fields sejam devolvidos antes de qualquer conteúdo do body.

Alguns dos status code mais usados incluem:
404: O recurso solicitado não está disponivel
401: O request exige HTTP authentication
500: Ocorreu um erro no HTTP server que impediu que este respondesse ao request
503: O HTTP server está temporariamente overloaded e indisponivel para atender o request

Uma pequena aplicação bastante útil para ver (entre outras coisas) o tráfego HTTP é o Fiddler (http://www.fiddlertool.com/fiddler/). Sugiro que façam o download e experimentem! É freeware!

E pronto!

Divirtam-se! ;)

Tuesday, May 15, 2007

Programação Orientada ao Negócio (PON)?

Sim, fui eu que inventei o termo! :) (Se bem que já espreitei este tema na net e acho que o termo não é lá muito original :))

Também podia ser BOP (Business Oriented Programming), p'ra dar um ar mais académico à coisa! :))

O que é?

Esta estratégia de desenho/implementação parece estar a ganhar cada vez mais força. Trata-se de pensar num sistema pensando primariamente nas necessidades de negócio, ie, nas necessidades dos clientes (utilizadores) do sistema.

Não é fácil! Muda um pouco (muito!) o algoritmo mental, habituado a pensar mais em pormenores técnicos do que na vertente de negócio.

Li uma noticia na net sobre um empresário da Escandinávia que reformulou uma companhia aérea, focando a estratégia da organização nos passageiros, e não tanto nos aviões, nas infraestruturas e outros factores que para o cliente não interessam primariamente.

Cito: "Hoje, nas reuniões de planeamento de sites, felizmente vejo uma preocupação maior em servir o usuário. Antes, as reuniões eram sobre o servidor X ou tecnologia Y. Por que hão-de o servidor X e a Tecnologia Y ter impacto na satisfação do meu utilizador?"
http://webinsider.uol.com.br/index.php/2007/05/14/web-20-oferece-momento-unico-a-cada-acesso

Como é que isso afecta a minha forma de programar?

Bem, são inúmeras as coisas que 'mudam' ao adoptar esta abordagem. Eu própria ainda ando a descobrir algumas! :)

Mas aqui ficam já algumas dicas.

- Nomes dos objectos:
. Os nomes que damos aos objectos devem reflectir aquilo que eles de facto são. Por exemplo, o objecto Produto diz-nos que a sua responsabilidade é lidar com as funcionalidades de manipulação de Produtos.

- Nomes dos métodos:
. Os métodos devem ter nomes significativos para o negócio, nao para o código! Por exemplo, nomes como somarValores(), ou adicionarLinha() não dizem muito sobre o negócio. Mas por exemplo, nomes como calcularPreco() ou adicionarProduto() são já mais elucidativos.

- Trabalhar a partir do Domain Model, não das Vistas:
. Aprendi da pior forma que esta é a abordagem correcta! :) Lembram-se do MVC (alguns posts atrás)? Pois então! A vista é manipulada pelo Controlador, com base no Modelo. Não o contrário! Há alguns dias tive de implementar uma alteração (de negócio!) a um sistema, e comecei por onde? Pela Vista... Pois! Devia ter começado pelo Modelo, porque se o tivesse feito iria perceber que as horas que perdi a mexer na Vista quase não teriam sido necessárias, já que se tratava de uma alteração ao Modelo, que iria afectar a Vista. Não o contrário!

Estas são apenas algumas dicas, de entre muitas.

O cerne da questão é a orientação ao negócio como ponto de partida. Ao pensar assim, o passo seguinte é olhar para o Modelo, que, precisamente(!), modela o negócio. Tudo o resto acaba depois por fluir.

Não é muito fácil, porque é acima de tudo uma mudança de mentalidade. Mas compensa!

Divirtam-se! ;)

Monday, May 14, 2007

"Tecnicisses" ou "Tecnicices"?

Pois é... Mudei de endereço...

O "Tecnicisses" não me soava nada bem. Este já me parece melhor! :))

Bem vindos!! (outra vez... :))

Friday, May 11, 2007

Google-it!!

Os senhores da Google realmente não param de surpreender!

Agora é possivel personalizar a página inicial do Google, fazendo o acesso pela conta do GMail.
Conseguimos ter na página inicial as ultimas noticias, o tempo, as horas, conseguimos monitorizar a mailbox do GMail, e tudo de forma muito facilmente configurável! É só fazer drag-and-drop e já está!

Cá fica o link: http://www.google.pt/ig

Divirtam-se! ;)

Monday, May 7, 2007

SQL - Que colunas devo indexar? (Optimização de Indexes)

Uma das dificuldades com que os programadores de bases de dados se deparam é saber escolher quais as colunas de uma tabela que devo escolher para indexar de forma a conseguir optimizações de performance quando a query é executada.

Espreitei um site que tem alguns guidelines que podem ajudar, e que aqui enumero resumidamente.

- Antes de começar a indexar tabelas, perceber os tipos de queries que serão executadas sobre elas.

Como identificar as queries mais frequentes: correr um Profiler sobre a Base de Dados
Após identificar as queries principias, como decidir quais os melhores indexes a criar: correr cada query no Query Analizer, examinando o seu Execution Plan.

Quando os indexes necessários tiverem sido identificados, então começar a indexar!

- Cada tabela deve ter, pelo menos, um clustered index.

O clustered index deve ser construido sobre uma coluna cujos valores se autoincrementam e são unicos. Regra geral, as chaves primárias são ideais para isso.

- Deve considerar-se a hipotese de indexar todas as colunas que sejam acedidas através de WHERE, ORDER BY, GROUP BY, TOP, e DISTINCT.

Sem um index, estas colunas são potenciais alvos de table scans, que afectam a performance. No entanto, há que ter em atenção diferentes queries que utilizam as mesmas colunas. Um index para uma query pode não ser o melhor index para outra query. É necessário algum bom senso.

- Indexes que podem não ser optimizados.

Há diferentes formas de indexar colunas: clustered, non-clustered, indexes compostos por várias colunas, definição do FILLFACTOR (parâmetro que define a percentagem de ocupação de cada 'página' do index), definição do PAD_INDEX (parâmetro que define quanto espaço livre é deixado em cada 'página' do index). Não há uma resposta fácil para decidir qual o melhor método, pelo que o ideal é fazer várias tentativas, e perceber qual o index mais optimizado.

- Criar apenas os indexes necessários.

Criar apenas os indexes que serão de facto utilizados nas queries de que estas tabelas serão alvo.

- Tabelas estáticas.

As tabelas que praticamente não são mexidas (por exemplo, as tabelas de metadados) podem ser alvo de mais indexes, o que não quer dizer que se indexem todas as colunas! Devem ser criados apenas os indexes necessários, porque cada index que é adicionado aumenta o tempo de execução de operações como INSERTs, UPDATES e DELETES. Estas tabelas devem ser criadas com um FILLFACTOR de 100, para garantir que não há desperdício de espaço.

- Não adicionar o mesmo index duas vezes.

Acontece, por exemplo, quando criamos uma chave primária, que automaticamente cria um index para essa coluna. Ao criar um novo index que inclui a mesma coluna, estamos a duplicar o index, já que o SQL permite ter indexes 'repetidos', desde que o nome dos indexes seja diferente.

- Eliminar indexes que não são utilizados.

Porque:
. Atrasam as operações de alteração de dados
. Causam acessos desnecessários ao disco
. Desperdiçam espaço na base de dados
. Aumentam o tempo de backup e restore de base de dados

E ainda, uma sugerida por um colega de trabalho:

- Indexar colunas com maior numero de valores diferentes.

Dentre as colunas existentes na instrução de SELECT, verificar as que apresentam maior disparidade de valores, e indexá-las.

E pronto!

Estas e outras guidelines em:
http://www.sql-server-performance.com/optimizing_indexes.asp

Divirtam-se ;)