Qual é a diferença entre o tipo de dados CHAR e o tipo de dados VARCHAR? E o NCHAR e o NVARCHAR?

Uma dúvida comum no desenvolvimento com SQL Server é acerca dos campos String. Encontrei um excelente artigo falando sobre isso: Qual é a diferença entre o tipo de dados CHAR e o tipo de dados VARCHAR? E o NCHAR e o NVARCHAR?.

Primeiro vou explicar a diferença entre o CHAR e o VARCHAR:

* CHAR: Este tipo de dados sofre a ação da collation escolhida para o banco de dados em que foi criado (ou uma collation que pode ter sido especificada na criação da tabela) e armazena a mesma quantidade de caracteres que foram especificados na sua criação, preenchendo com espaços em branco casa haja necessidade. Por exemplo:

CREATE TABLE TB_STRING
(
CAMPO1 CHAR(10)
)

Se fizermos o seguinte INSERT:

INSERT TB_STRING('A')

O campo vai armazenar o valor ‘A’ e também vai armazenar mais nove espaços em branco depois. Por causa desta característica o tipo de dados CHAR é chamado de tipo de dados com tamanho fixo.

* VARCHAR: Este tipo de dados também sobre a ação da collation para o banco de dados em que foi criado (ou uma collation que pode ter sido especificada na criação da tabela) e armazena SOMENTE a quantidade de caracteres que foram especificados na sua criação . Por exemplo:

CREATE TABLE TB_STRING1
(
CAMPO1 VARCHAR(10)
)

Se fizermos o seguinte insert:

INSERT TB_STRING1('A')

O campo vai armazenar o valor ‘A’ SOMENTE, sem colocar espaços em branco depois. Por causa desta característica o tipo de dados VARCHAR é chamado de tipo de dados com tamanho variável.

Uma outra pergunta que sempre me fazem é: quando devo utilizar o CHAR ao invés do VARCHAR uma vez que o CHAR ocupa mais espaço ? A resposta é simples: o tipo CHAR deve ser utilizado quando sabemos de antemão que todos os dados inseridos em determinada coluna não são variáveis como, por exemplo, uma coluna que armazena um código de peça que sempre precisa ter 5 dígitos. Outro fator a ser considerado são as pesquisas feitas utilizando o operador =.

Já o VARCHAR deve ser utilizado quando não sabemos o que vamos armazenar. Um exemplo pode ser o nome do cliente ou razão social que sempre acaba variando.

Quanto ao desempenho é provável que os tipo de dados VARCHAR apresentem uma pequena diferença em relação ao tipo de dados CHAR, principalmente em operações que leiam muitos registros como a criação de índice. Porém esta diferença só é perceptível quando a quantidade de dados é grande e estamos fazendo uma medição correta.

Já os tipos de dados NCHAR e NVARCHAR são análogos aos tipos de dados CHAR e VARCHAR, respectivamente, porém com uma pequena diferença: os tipos de dados NCHAR e NVARCHAR não sofrem ação da collation e sempre gastam dois bytes para armazenar cada caractere.

Comentarios

Caminho físico x caminho virtual para BD Access

Um erro relativamente comum por parte de desenvolvedores ainda sem muita experiênia, e que os leva frequentemente a achar que existe algum problema no servidor, é o caminho de Bancos de Dados Access.

Comumente o usuário tem, em sua máquina local, um banco no caminho…

c:\inetpub\wwwroot\bd\meubanco.mdb

Funciona em sua máquina local, e quando a página que usa o banco é enviada para o servidor… “A página não pode ser exibida”. A conclusão precipitada, muitas vezes, é que “há um problema no servidor, porque a página está correta, e roda em minha máquina“.

O desenvolvedor deve usar sempre um Caminho Virtual para não ter problemas se houver alguma mudança na configuração do servidor, ou se mudar de provedor e ainda para manter a compatibilidade, usando o mesmo código em seu servidor local e no servidor do produção (o do provedor). Se criou uma pasta “/data” e para lá enviou “meubanco.mdb” deverá usar, como caminho…

Server.MapPath("\data\meubanco.mdb")

A função Server.MapPath retorna (ou ‘traduz’) o caminho físico correspondente ao caminho virtual informado. No servidor local, como exempleficado, um…

Response.Write Server.Mappath("\") vai gerar…

c:\inetpub\wwwroot\

… e provavelmente será diferente no servidor do provedor. Assim é mantida a compatibilidade, não sendo necessário alterar o código para fazer o ‘upload’.

Comentario (1)

Modelagem de dados – exemplo simples

Em Noções básicas de modelagem de dados apresentei questões teóricas apenas, sem nenhum exemplo prático, já que considerei que aqueles 3 erros comuns devem, primeiro, ser superados. Creio que podemos, agora, partir para um exemplo mais prático.

Uma boa modelagem de banco de dados é de grande valia no desenvolvimento de um site profissional, e essa modelagem não é algo exatamente simples. Muitos acabam modelando razoavelmente bem os bancos de dados simples por algo que poderíamos chamar de ‘talento natural’. Aqui eu pretendo dar um exemplo básico, onde alguns têm acertado, mas a grande maioria realmente erra. Esse errar não significa, necessariamente, que o site não vá funcionar. Nesse caso específico, e realmente muito comum, gera um desperdício de espaço, e até mesmo dificuldade na manutenção. Passemos, então ao exemplo, a partir do cadastro de usuários gratuitos do ASPECTO.Net.

Considerando apenas o ID e os campos preenchidos pelo usuário, e deixando de fora os campos com fins de estatísticas e os campos de controle temos o seguinte:

  • ID
  • Username
  • E-mail
  • Senha
  • Nome
  • País
  • Cidade
  • Idade
  • Sexo
  • Lista de discussão
  • Fala inglês?

O campo ID é gerado automaticamente, e não há nada especial sobre os campos username, email, senha e nome, que são campos texto. O campo sexo, que é uma seleção, oferece as opções ‘Masculino’ e ‘Feminino’. O que é armazenado, no entanto, é o valor ‘1′ ou ‘2′, que ocupa apenas uma posição. Não faria sentido criar um campo com 9 posições (tamanho da palavra ‘Masculino’) se somente 2 opções são possíveis. Na opção ‘altera cadastro’ o conteúdo é verificado, e se for ‘1′ já seleciona ‘Masculino’. No caso de ‘2′ seleciona ‘Feminino’. Algo parecido acontece com o campo ‘idade’ (faixa etária, na verdade), com a diferença que são 7 as opções e não apenas duas. Os campos ‘Lista de discussão’ e ‘Fala inglês’ também oferecem apenas 2 opções, mas são do tipo ‘checkbox’ porque são lógicos. O usuário fará parte da lista de discussão, ou não. O usuário fala inglês, ou não.

O campo ‘país’ segue o exemplo de ‘idade’, só que com um número de opções ainda maior, mas ainda assim limitado. Na dinâmica de nosso mundo, hoje, a qualquer momento pode surgir um novo país, e acontecendo isso o seu nome será incluído na lista de seleção. Já o campo ‘cidade’ considera algo ainda mais importante na modelagem, e é esse o ponto em que muitos ‘erram’, no sentido de não otimizar os recursos da máquina, como o espaço em disco.

O número de opções para Cidade, ainda que não infinito, é bastante grande. Considerando que existem usuários em muitos países, não podemos oferecer uma lista com opções. Criar um campo texto, de tamanho 30 (ou mais) para armazenar a cidade seria um desperdício de espaço, e é ponto em que muitos ‘erram’. Teríamos muitos registros com o campo cidade preenchido com ‘Rio de Janeiro’, ‘São Paulo’, ‘Porto Alegre’, ‘Belo Horizonte’, ‘Beijing’ (Pequim), ‘London’, ‘New York’, entre outras. O que fazemos, nesse caso, é criar uma tabela com um campo numérico (ID) e um campo texto (30 posições, no nosso caso). No momento em que um usuário se cadastra a cidade que ele informou é procurada nessa tabela. No caso de ser encontrada, o ID dela será lançado no campo cidade (numérico) da tabela de usuários. Caso não seja encontrada ela será incluída e seu ID será lançado na tabela de usuários, uma vez que passou a existir. Dessa forma, estaremos utilizando um campo numérico, poupando muitos bytes, porque temos cada cidade registrada uma única vez em uma tabela e o seu ID utilizado quantas vezes forem necessárias, em um campo da tabela principal. Para a alteração do cadastro fazemos o inverso: procuramos a cidade cujo ID está na tabela de usuários, e lançamos o seu nome no campo texto próprio.

Vamos dar uma olhada, agora, em como ficaria a sintaxe da consulta, uma vez que a modelagem acima esteja sendo utilizada. Nesse caso vamos considerar que a tabela cidades tenha os seguintes campos:

  • ID
  • cidade

Na tabela cidades, se o registro cujo ID for 1 tiver, como conteúdo do campo cidade, ‘Rio de Janeiro’, os usuários do Rio de Janeiro terão 1 no campo cidade da tabela usuarios. Para selecionarmos todos os usuários da cidade do Rio de Janeiro a sintaxe seria a seguinte:

“SELECT * FROM usuarios INNER JOIN cidades ON usuarios.Cidade = cidades.ID WHERE cidades.cidade = ‘Rio de Janeiro’”

Em um site realmente dinâmico, a expressão ‘Rio de Janeiro’ não estaria no código, mas seria o conteúdo de uma variável. Algo como…

“SELECT * FROM usuarios INNER JOIN cidades ON usuarios.Cidade = cidades.ID WHERE cidades.cidade = ‘” & strCidade & “‘”

Nesse exemplo selecionamos todos os campos de todos os registros da tabela usuarios cujo campo Cidade tenha o mesmo valor do campo ID do registro cujo conteúdo do campo Cidade seja ‘Rio de Janeiro’, na tabela cidades. Ainda não selecionamos campos de duas tabelas, mas apenas usamos a segunda tabela (cidades) para estabelecer um critério de busca.

Comentarios

Consultas case-insensitive e accent-insensitive no MySQL

Uma necessidade comum com dados em língua portuguesa são as buscas no bancos de dados insensível a caso e insensível a acentos.No MySQL, até a versão 4.0, as consultas eram por padrão insensível ao caso (case insensitive) e insensível ao acento (accent insensitive). Isso mudou, porém, a partir da versão 4.1, que introduziu um suporte melhorado a comparações (collations) e definições de caracteres (charsets). Alguns desenvolvedores devem ter ficado surpresos com suas buscas que antes ignoravam acentos e maiúsculas e agora já exigiam que se colocasse.A partir dessa versão, a sintaxe para uma consulta que ignora acentos e o caso seria a seguinte:

SELECT *
FROM `tab_municipios`
WHERE `NomeMunic` = _utf8 ‘SAO PAULO’ COLLATE utf8_unicode_ci

Fonte: http://rafael.bernard-araujo.com/?p=5

Comentarios