SQL Server'da char, nchar, varchar ve nvarchar arasındaki fark nedir?


622

Ne anlama geliyor nvarchar?

Arasındaki fark nedir char, nchar, varchar, ve nvarcharSQL Server?

Yanıtlar:


856

Temizlemek için ... ya da özetlemek için ...

  • ncharve Unicode karakterleri nvarcharsaklayabilir .
  • charve Unicode karakterleri depolayamaz .varchar
  • charve ncharedilir uzunlukta sabit olacak depolama alanı rezerv tüm bu alanı kullanmak bile belirttiğiniz karakter sayısı için.
  • varcharve nvarcharolan değişken uzunlukta sadece saklamak karakterler için boşluk yukarı kullanacaktır. Bu gibi depolama ayırmaz charveyanchar .

ncharve nvarchariki kat daha fazla depolama alanı kaplayacağından, bunları yalnızca Unicode desteğine ihtiyacınız varsa kullanmak akıllıca olabilir .


15
char ve varchar, unicode'u depolamak için tasarlanmamıştır, ancak bazı ek kodlama hileleri ve ekstra mantıkla, unicode depolama için [var] char alanını kötüye kullanabilirsiniz.
On Brink'i


7
Depolama alanı ayırmanın avantajı nedir?
mlissner

4
Son noktada: Unicode nchar ve nvarchar kullanımı çoğu durumda hala daha iyidir, daha iyi harmanlama, kullanıcılar için esneklik, gelecekteki uyumluluk sorunlarını ortadan kaldırır. Bu arada depolama alanı bir sorun değildir, çünkü Unicode olmadan harmanlamayı kullanmak çok
zordur

6
@BenCaine char (20) 20 bayt kullanır (8 bit harmanlama varsayarak); varchar (20) len (veri) +2 bayt yani 20 bayt veri için 22, 10 bayt veri için sadece 12 kullanır. Fazladan iki bayt uzunluk kayıtlarıdır. Verileriniz her zaman tam uzunlukta olacaksa, yerden tasarruf sağladığı ve daha hızlı olabileceği için bir karakter kullanın. Lütfen asla bir varchar (1) veya gerçekten de varchar (4) 'ten daha küçük bir şey kullanmayın. Varchar biçimindeki tek bir karakter üç bayt kullanır, bu nedenle char (3) hiçbir zaman varchar (3) 'den daha fazla alan kullanmaz.
Richard Gadsden

95

Şimdiye kadar tüm cevaplar varchartek bayt, nvarchar çift ​​bayt olduğunu gösteriyor. Bunun ilk kısmı aslında aşağıda gösterildiği gibi harmanlamaya bağlıdır .

DECLARE @T TABLE
(
C1 VARCHAR(20) COLLATE Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS,
C2 NVARCHAR(20)COLLATE  Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS
)

INSERT INTO @T 
    VALUES (N'中华人民共和国',N'中华人民共和国'),
           (N'abc',N'abc');

SELECT C1,
       C2,
       LEN(C1)        AS [LEN(C1)],
       DATALENGTH(C1) AS [DATALENGTH(C1)],
       LEN(C2)        AS [LEN(C2)],
       DATALENGTH(C2) AS [DATALENGTH(C2)]
FROM   @T  

İadeler

resim açıklamasını buraya girin

Not ve karakterler hala temsil edilmemiştir VARCHARsürümü ve sessizce ile değiştirilmiştir ?.

Aslında bu harmanlamada tek bir bayt tarafından reddedilebilecek hiç Çince karakter yok. Tek baytlık karakterler, tipik batı ASCII kümesidir.

Bu nedenle, bir, bir insert mümkündür nvarchar(X), bir kolon varchar(X)sütun bir kesme hata ile başarısız (X her iki durumda da aynı olan bir sayıdır, q).

SQL Server 2012, destekleyen SC (Tamamlayıcı Karakter) harmanlamaları ekler UTF-16. Bu harmanlamalarda tek bir nvarcharkarakter 2 veya 4 bayt sürebilir.


4
Aradığım cevap türü. Ayrıca benim gibi zaman kazanmak için - İngilizce olmayan metin "Çin Halk Cumhuriyeti" anlamına gelir translate.google.com/#auto/en/…
Igand

34

nchar ve char, nvarchar ve varchar gibi hemen hemen aynı şekilde çalışır. Aralarındaki tek fark, nchar / nvarchar Unicode karakterlerini depolamasıdır (genişletilmiş karakter kümelerinin kullanılmasını gerektiriyorsa gereklidir), ancak varchar içermez.

Unicode karakterler daha fazla depolama alanı gerektirdiğinden, nchar / nvarchar alanları iki kat daha fazla yer kaplar (örneğin, SQL Server'ın önceki sürümlerinde nvarchar alanının maksimum boyutu 4000'dir).

Bu soru kopyası bu bir .


3
Bir şeyi unutursunuz: nchar sabit uzunluk kullanır, bu nedenle nchar (10) her zaman on karakter almalıdır. Ve varchar (10) gerçekten de Unicode'dur ve 10 karaktere kadar istediğiniz sayıda karakteri kabul eder. Ayrıca bkz. Msdn.microsoft.com/en-us/library/ms186939.aspx
Wim ten Brink

33

Sadece bir şey daha eklemek için: nchar - verilere sondaki boşlukları ekler. nvarchar - verilere sondaki boşluklar eklemez.

Bu nedenle, veri kümenizi bir 'nchar' alanına göre filtreleyecekseniz, boşlukları kaldırmak için RTRIM'i kullanmak isteyebilirsiniz. BRAND adı verilen nchar (10) alanı NIKE kelimesini saklar. Kelimenin sağına 6 boşluk ekler. Bu nedenle, filtrelerken ifade şöyle olmalıdır: RTRIM (Fields! BRAND.Value) = "NIKE"

Umarım buradaki birine yardımcı olur, çünkü şimdi onunla biraz uğraşıyordum!


24

Mevcut cevapları özetleme ve düzeltme girişimim:

İlk olarak, charve ncharbuna karşın her zaman, saklanmasına dize kullanılabilir alan daha küçük olduğunda bile, depolama alanı sabit bir miktar kullanacak varcharve nvarcharbu dizeyi (artı yükü iki bayt depolamak için gerekli olan kadar depolama alanı olarak yalnızca kullanacak, muhtemelen dize uzunluğunu saklamak için). Unutmayın, "var" değişken alanda olduğu gibi "değişken" anlamına gelir.

Anlamak için ikinci önemli nokta yani ncharve nvarcharkullanma mağaza dizeleri tam oysa, her karakter iki bayt charve varcharolacak harmanlama kod sayfası tarafından belirlenen bir kodlama kullanır genellikle (orada, istisnalar aşağıya bakınız rağmen) karakterinin başına tam bir byte olacak. Burada hatırlanması gereken temel şey, yani her karakter iki bayt kullanarak, karakterlerin çok geniş bir aralık, saklanabilir ncharve nvarcharsen muhtemelen bunu uluslararası destek, istediğinizde çok daha iyi bir seçim olma eğilimindedir.

Şimdi bazı daha ince noktalar için.

İlk olarak ncharve nvarcharsütunlar her zaman UCS-2 kullanarak veri depolar. Bu, karakter başına tam olarak iki bayt kullanılacağı ve Temel Çok Dilli Düzlemdeki (BMP) herhangi bir Unicode karakterin bir ncharveya nvarcharalan tarafından saklanabileceği anlamına gelir . Ancak, herhangi bir Unicode karakterinin saklanabileceği durum söz konusu değildir . Örneğin, Wikipedia'ya göre, Mısır hiyeroglifleri için kod noktaları BMP'nin dışında kalıyor. Bu nedenle, UTF-8'de temsil edilebilen Unicode dizeleri ve bir SQL Server ncharveya nvarcharalanda depolanamayan diğer gerçek Unicode kodlamaları vardır ve Mısır hiyerogliflerinde yazılmış dizeler bunlar arasında olacaktır. Neyse ki kullanıcılarınız muhtemelen bu senaryoda yazmazlar, ancak akılda tutulması gereken bir şeydir!

Başka kafa karıştırıcı ama diğer posterleri sermiştir ilginç nokta olduğunu charve varcharharmanlama kod sayfası gerektiriyorsa alanları belirli karakterler için karakter iki bayt kullanabilir. (Martin Smith, Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS'nin bu davranışı nasıl sergilediğini gösterdiği mükemmel bir örnek veriyor.

GÜNCELLEME: SQL Server 2012'den itibaren, UTF-16 için nihayet tüm Unicode aralığını gerçekten kapsayabilen Latin1_General_100_CI_AS_SC kod sayfaları vardır .


14
  • char: maksimum 8000 karakter uzunluğunda sabit uzunlukta karakter verileri.
  • nchar: maksimum 4000 karakter uzunluğunda sabit uzunluklu unicode veriler.
  • Char = 8 bit uzunluk
  • NChar = 16 bit uzunluk

char8 bit uzunluğa sahip olamazdı. Uzunluğu depolamak zorunda değildir ve sabit uzunluk 8000 karaktere kadar olabilir.
John B. Lambe

12

nchar[(n)] (Ulusal karakter)

  • Sabit uzunluklu Unicode dize verileri.
  • n dize uzunluğunu tanımlar ve 1 ile 4,000 arasında bir değer olmalıdır.
  • Depolama boyutu iki kat nbayttır.

nvarchar [(n | max)] (ulusal karakter değişiyor.)

  • Değişken uzunlukta Unicode dize verileri.
  • n dize uzunluğunu tanımlar ve 1 ile 4,000 arasında bir değer olabilir.
  • max maksimum depolama boyutunun 2 ^ 31-1 bayt (2 GB) olduğunu gösterir.
  • Bayt cinsinden depolama boyutu, girilen verilerin gerçek uzunluğunun iki katıdır + 2 bayt

char [(n)] (karakter)

  • Sabit uzunluklu non-Unicodedize verileri.
  • n dize uzunluğunu tanımlar ve 1 ile 8.000 arasında bir değer olmalıdır.
  • Depolama boyutu nbayttır.

varchar [(n | max)] (karakter değişiyor)

  • Değişken uzunlukta, Unicode olmayan dize verileri.
  • n dize uzunluğunu tanımlar ve 1 ile 8.000 arasında bir değer olabilir.
  • max maksimum depolama boyutunun 2 ^ 31-1 bayt (2 GB) olduğunu gösterir.
  • Depolama boyutu, girilen verinin gerçek uzunluğu + 2 bayt.

7

Farklılıklar :

  1. n [var] char unicode depolarken, [var] char sadece tek baytlık karakterleri saklar.
  2. [n] karakter, tam uzunlukta sabit sayıda karakter gerektirirken, [n] varchar tanımlanmış uzunlukta dahil olmak üzere değişken sayıda karakter kabul eder.

Başka bir fark uzunluktur. Hem nchar hem de nvarchar 4.000 karakter uzunluğunda olabilir. Ve char ve varchar 8000 karakter uzunluğunda olabilir. Ancak SQL Server için 2.147.483.648 karaktere kadar işleyebilen bir [n] varchar (max) da kullanabilirsiniz. (İki gigabayt, işaretli bir 4 bayt tam sayı.)


7

nchar, nvarchar'dan daha fazla alan gerektirir .

Örneğin,

Bir nchar (100), yalnızca 5 girseniz bile, her zaman 100 karakter depolar, kalan 95 karakter boşluklarla doldurulur. Bir nvarchar'da (100) 5 karakter depolamak 5 karakter kazandırır.


6
Tamamen doğru değil, çünkü bir karakteri (100) 100 karaktere kadar doldurmanız gerekiyor. Örneğin, telefon numaralarını veritabanınızda sakladığınızda veya sabit uzunlukta numaralar sipariş ettiğinizde kullanabilirsiniz. Alan uzunluğu sabit olduğundan, maksimum karakter sayısına kadar doldurma seçeneğiniz yoktur. Ancak tüm verileriniz kayıt başına 100 karakter olduğunda, bir char (100) bir varchartan (100) daha az depolama alır, çünkü uzunluk göstergesine ihtiyaç duymaz: her değer tam olarak 100 karakter olacaktır.
On Brink'i

5

nchar (10), 10 uzunlukta sabit uzunluklu bir Unicode dizgidir. nvarchar (10), maksimum 10 uzunluğu olan değişken uzunlukta bir Unicode dizgidir. Genellikle, tüm veri değerleri 10 karakter ve sonuncusu ise birincisini kullanırsınız. uzunluklar değişirse.


Yanlış karşılaştırma - soru nchar ve nvarchar ile değil, nchar ve varchar ile ilgilidir.
Luke Bennett

4
  • nchar sabit uzunluktadır ve unicode karakterleri tutabilir. karakter başına iki bayt depolama kullanır.

  • varchar değişken uzunluktadır ve unicode karakterleri tutamaz. karakter başına bir bayt depolama kullanır.


Yanlış. Unicode her karakter için 1 ila 4 bayt (genel olarak) kullanabilir. Ayrıca, bir varchar unicode tutabilir, ancak unicode olarak tanınmaz. Sonuç olarak, bir varchar unicode depolama için güvenilir değildir. (Özellikle alana erişen kodun alanı yanlış çevirmesi riski bulunduğundan.)
Wim ten Brink

@Alex: Bence fikrini dile getirdin ama hala sana katılmıyorum. Söylediğiniz şey, eğer uzun 2 ^ 32'den küçükse, bir int CAN'ın uzun süre beklemesidir. Bu sadece 'güvenilmez' değil, tüm değer aralığını kapsamayı imkansız kılan doğal bir sınırlamadır.
Manu

4
@ Atölye Alex: Yanlış. Unicode olarak kodlanmış UCS-2(SQL Server tarafından kullanılan kodlama olur ki) her karakteri depolayan tam iki bayt, bkz msdn.microsoft.com/en-us/library/bb330962%28v=sql.90%29.aspx : SQL Server stores Unicode in the UCS-2 encoding scheme... UCS-2 is a fixed-length encoding that represents all characters as a 16-bit value (2 bytes). SQL Server 2008 SCSU sıkıştırmasını kullanabilir, ancak yine de UCS-2 kodlu Unicode dizelerinin sıkıştırmasıdır: msdn.microsoft.com/en-us/library/ee240835.aspx
Remus Rusanu 18:10

2

NVARCHAR , Unicode karakterleri depolayabilir ve karakter başına 2 bayt alır.


1
YANLIŞ! Unicode karakter başına 1 ile 4 bayt kullanır! Birçok insan bunu unutuyor! UTF-16 kullanımı bile bazı karakterlerin 2 yerine 4 bayt almasına neden olabilir, ancak ortak uzunluk 2 bayt olacaktır. Unicode'un diğer bazı alt biçimleri 4 bayttan daha fazla sürebilir!
On Brink'i

7
@WimtenBrink - Soru SQL Server ile ilgilidir ve nvarcharher karakter için 2 bayt alır.
Martin Smith

@Wim, Unicode için farklı sayıda bayt üretebilen çeşitli kodlamalar olduğu doğrudur. Ancak SQL Server, Unicode kodlaması hakkında size bir seçenek sunmaz. SQL Server 2012'den önce sadece iki bayt genişliğinde UCS-2 kullandı, bu yüzden Martin cevabı yazdığı sırada doğruydu. Yukarıdaki diğer yanıtların söylediği gibi, SQL Server 2012 artık UTF-16 sağlar, bu nedenle birçok karakter için iki bayt (Unicode Temel Çok Dilde Düzlemde olanlar), diğerleri için dört bayt.
Beton Gannet
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.