Qual é a diferença entre varchar e nvarchar?

1354

É apenas que nvarcharsuporta caracteres multibyte? Se for esse o caso, existe realmente algum ponto, além das preocupações de armazenamento, para usar varchars?

caules
fonte
6
Eu gosto do argumento de incomudro, foi o que me levou a investigar a diferença entre varchar e nvarchar em primeiro lugar. Nosso aplicativo Java em um banco de dados SQL Server usa myBatis, que parece enviar seqüências de caracteres como nvarchar por padrão (ainda não sabemos como (ou se) isso é substituível). Uma consulta simples estava aparecendo como um enorme problema de desempenho, porque eu defini a coluna que selecionaria como varchar, não nvarchar, e estava ignorando o índice na coluna.
Sean Leia

Respostas:

1652

Uma nvarcharcoluna pode armazenar qualquer dado Unicode. Uma varcharcoluna é restrita a uma página de código de 8 bits. Algumas pessoas pensam que isso varchardeve ser usado porque ocupa menos espaço. Eu acredito que esta não é a resposta correta. As incompatibilidades da página de código são um problema e o Unicode é a solução para problemas de página de código. Hoje em dia, com disco e memória baratos, não há realmente nenhuma razão para perder mais tempo com páginas de código.

Todos os sistemas operacionais e plataformas de desenvolvimento modernos usam Unicode internamente. Ao usar, em nvarcharvez de varchar, você pode evitar conversões de codificação sempre que ler ou gravar no banco de dados. As conversões levam tempo e são propensas a erros. E a recuperação de erros de conversão é um problema não trivial.

Se você estiver fazendo interface com um aplicativo que usa apenas ASCII, eu ainda recomendaria o uso de Unicode no banco de dados. Os algoritmos de agrupamento de SO e banco de dados funcionarão melhor com Unicode. O Unicode evita problemas de conversão ao fazer interface com outros sistemas. E você estará se preparando para o futuro. E você sempre pode validar que seus dados estão restritos ao ASCII de 7 bits para qualquer sistema legado que você esteja mantendo, mesmo enquanto desfruta de alguns dos benefícios do armazenamento Unicode completo.

Jeffrey L Whitledge
fonte
8
Esta é uma ótima informação para ter. Então, estou entendendo isso corretamente se deduzir que a escolha acaba se tornando uma das - qual recurso é mais barato: processador + sobrecarga de desenvolvimento ou armazenamento?
Matt Cashatt
141
@MatthewPatrickCashatt - Você pode ver dessa maneira. Mas se você imagina um mundo glorioso no qual todos os dados de texto estão em Unicode, e os desenvolvedores simplesmente não precisam pensar em que codificação está algo, e toda uma classe de erros simplesmente nunca ocorre, então você pode ver que há realmente nenhuma escolha.
Jeffrey L Whitledge
8
@ Martin Smith - Nesses casos, a pequena vantagem que o varchar confere (armazenamento compacto) desaparece. Eu acho que varchar é ainda pior do que eu pensava!
Jeffrey L Whitledge
9
@ PeterAllenWebb - Você pode “armazenar” qualquer dado Unicode, porque os pares substitutos no UTF-16 podem ser armazenados no UCS-2 como se fossem caracteres. Isso funcionará de forma transparente para armazenamento e recuperação de dados. Agora, o que você não pode fazer é obter transformações e comparações confiáveis ​​de casos fora do BMP, mas não fiz nenhuma reivindicação sobre isso. Portanto, se você tiver muito texto do Desseret no qual deseja processar, seria melhor fazê-lo fora do banco de dados. Mas é bom armazená-lo lá. (Claro, varchar não vai ajudá-lo lá também!)
Jeffrey L Whitledge
259

varchar : dados de caracteres não Unicode de comprimento variável. O agrupamento do banco de dados determina qual página de código os dados são armazenados.

nvarchar : dados de caracteres Unicode de comprimento variável. Depende do agrupamento do banco de dados para comparações.

Armado com esse conhecimento, use o que corresponder aos seus dados de entrada (ASCII v. Unicode).

user7116
fonte
5
Existe uma restrição como o varchar não pode armazenar dados Unicode? São todos os 1 e 0. Eu sou capaz de salvar o conteúdo chinês como varchar muito bem para o meu banco de dados. Apenas especifique seu UTF-8. Como funciona isso então ?
Nishant
3
@ Resposta tardia do comerciante : é claro que você pode armazenar UTF-8 no varchar, mas isso interromperá as funções de string do SQL Server. Se você executar todas as pesquisas / transformações em seu aplicativo, sim, poderá fazê-lo (mas qual é o benefício?). Somente a codificação Unicode suportada pelo SS é UCS-2 (sim, não o UTF-16 antes do SS2k16) e suas funções de string funcionam apenas com essa codificação. BTW e os índices? Se você deseja armazenar dados arbitrários, é melhor usar o binário.
Adriano Repetti
Sim, apenas quebra as funções de pesquisa de strings.
Nishant
8
Então, você sabe ... isso não "funciona". É como armazenar um floatem um inte dizer "bem, com certeza as casas decimais desaparecem". Apenas não.
User7116
70

Eu sempre uso o nvarchar, pois permite que tudo o que estou construindo possa suportar praticamente qualquer dado que eu jogue nele. Meu sistema CMS faz chinês por acidente, porque usei nvarchar. Atualmente, novos aplicativos não devem se preocupar com a quantidade de espaço necessária.

tags2k
fonte
25
A idéia de que os novos aplicativos não devem se preocupar com restrições de espaço é um pouco míope, e qualquer pessoa que tenha lidado com bancos de dados no nível corporativo de médio a grande ficará feliz em lhe dizer, completamente incorreta.
Frater 21/07
60
Para ter a liberdade de colocar palavras na boca do tags2k, acho que uma afirmação mais precisa pode ser 'é cada vez mais improvável que qualquer novo aplicativo se preocupe mais com o espaço necessário do que com a internacionalização e outros problemas do conjunto de caracteres'.
Cowan
1
"Atualmente, novos aplicativos não devem se preocupar com a quantidade de espaço necessária." - A menos que você esteja usando armazenamento em nuvem gratuito, em que o plano pago é um salto CONSIDERÁVEL em $ (consulte os planos compartilhados do AppHarbor SQL Server).
Ganders
3
@ganders Howl! Você está aí. Declarações generalizadas só estão temporariamente corretas na melhor das hipóteses. A computação é definitivamente um jogo de balanço e rotatória. Definitivamente, estou preocupado com a quantidade de espaço que estou usando no Windows Azure CCP. Dito isto, eu "nunca" usaria varchar sobre nvarchar. Ooo, acabei de me contradizer?
RISM
1
@rism, acredito que você removeu qualquer risco de contradição com o uso de citações "never", pelo menos tecnicamente.
Smandoli
30

Depende de como o Oracle foi instalado. Durante o processo de instalação, a opção NLS_CHARACTERSET é configurada. Você pode encontrá-lo com a consulta SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Se o seu NLS_CHARACTERSET é uma codificação Unicode como UTF8, ótimo. Usando VARCHAR e NVARCHAR são praticamente idênticos. Pare de ler agora, apenas vá em frente. Caso contrário, ou se você não tiver controle sobre o conjunto de caracteres Oracle, continue lendo.

VARCHAR - Os dados são armazenados na codificação NLS_CHARACTERSET. Se houver outras instâncias de banco de dados no mesmo servidor, você poderá ser restringido por elas; e vice-versa, já que você precisa compartilhar a configuração. Esse campo pode armazenar qualquer dado que possa ser codificado usando esse conjunto de caracteres e nada mais . Por exemplo, se o conjunto de caracteres for MS-1252, você poderá armazenar apenas caracteres como letras em inglês, um punhado de letras acentuadas e alguns outros (como € e -). Seu aplicativo seria útil apenas para algumas localidades, incapaz de operar em qualquer outro lugar do mundo. Por esse motivo, é considerado uma má idéia.

NVARCHAR - Os dados são armazenados em uma codificação Unicode. Todo idioma é suportado. Uma boa ideia.

E quanto ao espaço de armazenamento? O VARCHAR geralmente é eficiente, pois o conjunto de caracteres / codificação foi projetado de forma personalizada para um código de idioma específico. Os campos NVARCHAR armazenam na codificação UTF-8 ou UTF-16, com base na configuração NLS ironicamente. O UTF-8 é muito eficiente para idiomas "ocidentais", enquanto ainda suporta idiomas asiáticos. O UTF-16 é muito eficiente para idiomas asiáticos, enquanto ainda suporta idiomas "ocidentais". Se estiver preocupado com o espaço de armazenamento, escolha uma configuração NLS para fazer com que o Oracle use UTF-8 ou UTF-16 conforme apropriado.

E a velocidade de processamento? A maioria das novas plataformas de codificação usa Unicode nativamente (Java, .NET e até C ++ std :: wstring de anos atrás!). Portanto, se o campo do banco de dados for VARCHAR, ele força o Oracle a converter entre conjuntos de caracteres em cada leitura ou gravação, não tão bom. O uso do NVARCHAR evita a conversão.

Conclusão: use NVARCHAR! Evita limitações e dependências, é bom para espaço de armazenamento e geralmente é melhor também para desempenho.

Jeremy Frank
fonte
42
Esta é uma resposta muito boa, exceto que a pergunta é sobre o sql-server.
Stimms 7/10/10
21

O nvarchar armazena dados como Unicode; portanto, se você deseja armazenar dados multilíngues (mais de um idioma) em uma coluna de dados, precisa da variante N.

Albertein
fonte
16

Meus dois centavos

  1. Os índices podem falhar ao não usar os tipos de dados corretos:
    No SQL Server: quando você tem um índice em uma coluna VARCHAR e apresenta uma String Unicode, o SQL Server não utiliza o índice. O mesmo acontece quando você apresenta um BigInt em uma coluna indexada que contém SmallInt. Mesmo se o BigInt for pequeno o suficiente para ser um SmallInt, o SQL Server não poderá usar o índice. Por outro lado, você não tem esse problema (ao fornecer SmallInt ou Ansi-Code a uma coluna BigInt ou NVARCHAR indexada).

  2. Os tipos de dados podem variar entre diferentes DBMSs (Sistema de Gerenciamento de Banco de Dados):
    Saiba que todo banco de dados tem tipos de dados ligeiramente diferentes e o VARCHAR não significa o mesmo em todos os lugares. Enquanto o SQL Server possui VARCHAR e NVARCHAR, um banco de dados Apache / Derby possui apenas VARCHAR e o VARCHAR está no Unicode.

incomudro
fonte
Mas certamente, se você estiver escrevendo seu código corretamente (por exemplo, usando consultas parametrizadas etc.), o ponto 1 é menos arriscado.
Paul
14

Principalmente nvarchar armazena caracteres Unicode e varchar armazena caracteres não Unicode.

"Unicodes" significa um esquema de codificação de caracteres de 16 bits que permite que caracteres de vários outros idiomas, como árabe, hebraico, chinês e japonês, sejam codificados em um único conjunto de caracteres.

Isso significa que os unicodes estão usando 2 bytes por caractere para armazenar e os não-unicodes usam apenas um byte por caractere para armazenar. O que significa que os unicodes precisam de capacidade dupla para armazenar em comparação com os não unicodes.

ranjit pawar
fonte
10

Você está certo. nvarchararmazena dados Unicode enquanto varchararmazena dados de caracteres de byte único. Além das diferenças de armazenamento ( nvarcharrequer o dobro do espaço de armazenamento varchar), que você já mencionou, o principal motivo para preferir a nvarcharsubstituição varcharseria a internacionalização (por exemplo, armazenar seqüências de caracteres em outros idiomas).

Mike Spross
fonte
10

Eu diria que depende.

Se você desenvolver um aplicativo de desktop, em que o sistema operacional funcione em Unicode (como todos os sistemas atuais do Windows) e o idioma ofereça suporte nativo a Unicode (as strings padrão são Unicode, como em Java ou C #), vá para nvarchar.

Se você desenvolver um aplicativo da Web, onde as strings aparecem como UTF-8, e a linguagem é PHP, que ainda não suporta Unicode nativamente (nas versões 5.x), o varchar provavelmente será uma escolha melhor.

sleepy012
fonte
9

Embora NVARCHARarmazene o Unicode, você deve considerar, com a ajuda do agrupamento, que também pode usar VARCHARe salvar seus dados nos idiomas locais.

Imagine o seguinte cenário.

O agrupamento do seu banco de dados é persa e você salva um valor como 'علی' (gravação persa de Ali) no VARCHAR(10)tipo de dados. Não há problema e o DBMS usa apenas três bytes para armazená-lo.

No entanto, se você deseja transferir seus dados para outro banco de dados e ver o resultado correto, o banco de dados de destino deve ter o mesmo agrupamento que o destino que é persa neste exemplo.

Se o agrupamento de destino for diferente, você verá alguns pontos de interrogação (?) No banco de dados de destino.

Por fim, lembre-se, se você estiver usando um banco de dados enorme que é usado no idioma local, recomendo usar o local em vez de usar muitos espaços.

Eu acredito que o design pode ser diferente. Depende do ambiente em que você trabalha.

Ali Elmi
fonte
8

Eu dei uma olhada nas respostas e muitas parecem recomendar o uso nvarcharexcessivo varchar, porque o espaço não é mais um problema, por isso não há mal algum em ativar o Unicode para pouco armazenamento extra. Bem, isso nem sempre é verdade quando você deseja aplicar um índice sobre sua coluna. O SQL Server tem um limite de 900 bytes no tamanho do campo que você pode indexar. Portanto, se você tiver um, varchar(900)ainda poderá indexá-lo, mas não varchar(901). Com nvarchar, o número de caracteres é dividido pela metade, para que você possa indexar até nvarchar(450). Portanto, se você tem certeza de que não precisa nvarchar, não recomendo usá-lo.

Em geral, nos bancos de dados, eu recomendo manter o tamanho necessário, porque você sempre pode expandir. Por exemplo, um colega de trabalho pensou que não havia mal em usar nvarchar(max)para uma coluna, pois não temos nenhum problema com o armazenamento. Posteriormente, quando tentamos aplicar um índice nessa coluna, o SQL Server rejeitou isso. Se, no entanto, ele começou com o even varchar(5), poderíamos simplesmente expandi-lo mais tarde para o que precisamos, sem um problema que exija que façamos um plano de migração de campo para corrigir esse problema.

Rafid
fonte
7

O nVarchar ajudará você a armazenar caracteres Unicode. É o caminho a seguir se você deseja armazenar dados localizados.

Vijesh VP
fonte
7

Se um único byte for usado para armazenar um caractere, existem 256 combinações possíveis e, portanto, você pode salvar 256 caracteres diferentes. Agrupamento é o padrão que define os caracteres e as regras pelas quais eles são comparados e classificados.

1252, que é o Latin1 (ANSI), é o mais comum. Os conjuntos de caracteres de byte único também são inadequados para armazenar todos os caracteres usados ​​por vários idiomas. Por exemplo, alguns idiomas asiáticos têm milhares de caracteres, portanto, eles devem usar dois bytes por caractere.

Padrão Unicode

Quando sistemas que usam várias páginas de código são usados ​​em uma rede, torna-se difícil gerenciar a comunicação. Para padronizar as coisas, o consórcio ISO e Unicode apresentou o Unicode . Unicode usa dois bytes para armazenar cada caractere. Ou seja, 65.536 caracteres diferentes podem ser definidos, portanto quase todos os caracteres podem ser cobertos com Unicode. Se dois computadores usam Unicode, todos os símbolos serão representados da mesma maneira e nenhuma conversão é necessária - essa é a ideia por trás do Unicode.

O SQL Server possui duas categorias de tipos de dados de caracteres:

  • não Unicode (char, varchar e texto)
  • Unicode (nchar, nvarchar e ntext)

Se precisarmos salvar dados de caracteres de vários países, sempre use Unicode.

Jithin Shaji
fonte
6

Eu tenho que dizer aqui (eu percebo que provavelmente vou me abrir para uma lista!), Mas certamente a única vez em que NVARCHARserá realmente mais útil (observe mais aqui!) Do que VARCHARquando todos os agrupamentos de todas dos sistemas dependentes e dentro do próprio banco de dados são os mesmos ...? Caso contrário, a conversão de agrupamento deve ocorrer de qualquer maneira e, portanto, torna-se VARCHARtão viável quanto NVARCHAR.

Para adicionar isso, alguns sistemas de banco de dados, como o SQL Server (antes de 2012), têm um tamanho de página de aprox. 8K. Portanto, se você estiver olhando para o armazenamento de dados pesquisáveis ​​que não são mantidos em algo como um campo TEXTou NTEXT, então VARCHARfornece o valor total de 8k de espaço, enquanto NVARCHARapenas fornece 4k (o dobro dos bytes, o dobro do espaço).

Suponho, para resumir, o uso de qualquer um depende de:

  • Projeto ou contexto
  • A infraestrutura
  • Sistema de banco de dados
Paulo
fonte
6

Siga a diferença entre o Sql Server VARCHAR e o NVARCHAR Data Type . Aqui você pode ver de uma maneira muito descritiva.

Em geral, o varchar armazena dados como Unicode, portanto, se você deseja armazenar dados multilíngues (mais de um idioma) em uma coluna de dados, precisa da variante N.

Pradeep Kesharwani
fonte
Este é um link muito útil, mas sua resposta não chega a muito mais do que isso: um link.
RubberDuck
ckuhn203, eu não vou dizer para você ver este
Pradeep Kesharwani
6

A principal diferença entre Varchar(n)e nvarchar(n)é: insira a descrição da imagem aqui

Varchar(Dados de caracteres não Unicode de comprimento variável) é de até 8000. 1.É um tipo de dados de comprimento variável

  1. Usado para armazenar caracteres não Unicode

  2. Ocupa 1 byte de espaço para cada personagem

insira a descrição da imagem aqui

Nvarchar: Dados de caracteres Unicode de comprimento variável.

1.É um tipo de dados de comprimento variável

2.Usado para armazenar caracteres Unicode.

  1. Os dados são armazenados em uma codificação Unicode. Todo idioma é suportado. (por exemplo, os idiomas árabe, alemão, hindi etc.)
Debendra Dash
fonte
6

Jeffrey L Whitledge com ~ 47000 pontos de reputação recomenda o uso de nvarchar

Solomon Rutzky com ~ 33200 pontos de reputação recomenda: NÃO sempre use NVARCHAR. Essa é uma atitude / abordagem muito perigosa e muitas vezes dispendiosa.

Quais são as principais diferenças de desempenho entre os tipos de dados SQL Server varchar e nvarchar?

https://www.sqlservercentral.com/articles/disk-is-cheap-orly-4

Ambas as pessoas com uma reputação tão alta, o que um desenvolvedor de banco de dados de servidor sql para aprendizado escolhe?

Existem muitos avisos nas respostas e comentários sobre problemas de desempenho, se você não for consistente nas escolhas.

Existem comentários pro / con nvarchar for performance.

Existem comentários pro / con varchar para desempenho.

Eu tenho um requisito específico para uma tabela com muitas centenas de colunas, o que por si só é provavelmente incomum?

Estou escolhendo o varchar para evitar chegar perto do limite de tamanho de registro da tabela de 8060 bytes do SQL * server 2012.

O uso de nvarchar, para mim, ultrapassa esse limite de 8060 bytes.

Também estou pensando que devo corresponder os tipos de dados das tabelas de códigos relacionadas aos tipos de dados da tabela central primária.

Eu já vi o uso da coluna varchar neste local de trabalho, o governo da Austrália do Sul, por desenvolvedores de banco de dados experientes anteriores, em que a contagem de linhas da tabela será de vários milhões ou mais (e muito poucas colunas nvarchar, se houver, nessas áreas muito grandes tabelas), portanto, talvez os volumes esperados da linha de dados se tornem parte dessa decisão.

Allan F
fonte
1

nvarcharé seguro de usar em comparação com varchar, a fim de tornar nosso código livre de erros (incompatibilidade de tipo) porque também nvarcharpermite caracteres unicode. Quando usamos a wherecondição na consulta do SQL Server e se estamos usando o =operador, ele gera um erro algumas vezes. O motivo provável disso é que nossa coluna de mapeamento será diferenciada varchar. Se o definíssemos nvarcharneste problema, não aconteceria. Ainda nos mantemos varchare evitamos esse problema, é melhor usarmos a LIKEpalavra-chave do que =.

Rinoy Ashokan
fonte