Varchar ve nvarchar arasındaki fark nedir?


1354

Sadece çok nvarcharbaytlı karakterleri mi destekliyor? Durum buysa, depolama endişelerinin dışında gerçekten kullanmanın bir anlamı var varcharsmı?


6
Ben incomudro'nun noktasını seviyorum, ilk etapta varchar ve nvarchar arasındaki fark hakkında kazı yapmamı sağlayan şey buydu. Bir SQL Server db'ye karşı Java uygulamamız, dizeleri varsayılan olarak nvarchar olarak gönderen myBatis'i kullanıyor (yine de nasıl (veya geçersiz kılınabiliyorsa) emin değilim). Basit bir sorgu, nvarchar yerine varchar olarak seçtiği sütunu tanımladığım için büyük bir performans sorunu olarak gösteriliyordu ve sütundaki dizini yok sayıyordu.
Sean

Yanıtlar:


1652

Bir nvarcharsütun herhangi bir Unicode verisini saklayabilir. Bir varcharsütun 8 bit kod sayfasıyla sınırlıdır. Bazı insanlar bunun varchardaha az yer kapladığı için kullanılması gerektiğini düşünüyor . Bunun doğru cevap olmadığına inanıyorum. Kod sayfası uyumsuzlukları bir acıdır ve Unicode kod sayfası sorunlarının tedavisidir. Günümüzde ucuz disk ve bellek ile, artık kod sayfaları ile uğraşarak zaman kaybetmek için hiçbir neden yoktur.

Tüm modern işletim sistemleri ve geliştirme platformları dahili olarak Unicode kullanır. Bunun nvarcharyerine varchar, veritabanından her okuduğunuzda veya veritabanına yazdığınızda kodlama dönüşümleri yapmaktan kaçınabilirsiniz. Dönüşümler zaman alır ve hatalara eğilimlidir. Ve dönüştürme hatalarından kurtulmak önemsiz bir sorundur.

Yalnızca ASCII kullanan bir uygulama ile arabirim oluşturuyorsanız, yine de veritabanında Unicode kullanmanızı öneririm. İşletim sistemi ve veritabanı harmanlama algoritmaları Unicode ile daha iyi çalışacaktır. Unicode, diğer sistemlerle arayüz oluştururken dönüştürme problemlerinden kaçınır . Ve geleceğe hazırlanacaksınız. Tam Unicode depolamanın bazı avantajlarından yararlanırken bile, korumak istediğiniz eski sistem için verilerinizin 7 bit ASCII ile sınırlı olduğunu her zaman doğrulayabilirsiniz.


8
Bu sahip olmak için harika bir bilgi. Yani seçimin sonuçta hangi kaynaklardan biri haline geldiğine karar verirseniz bunu doğru anlıyorum: işlemci + geliştirme yükü veya depolama?
Matt Cashatt

141
@MatthewPatrickCashatt - Bu şekilde görebiliyordunuz. Ancak, tüm metin verilerinin Unicode'da olduğu görkemli bir dünya hayal ediyorsanız ve geliştiriciler, bir şeyin kodlanmasının ne olduğunu düşünmek zorunda kalmazlar ve tüm hata sınıflarının asla gerçekleşmediğini görebilirsiniz. gerçekten başka seçenek yok.
Jeffrey L Whitledge


8
@Martin Smith - Bu durumlarda, varchar'ın sağladığı küçük avantaj (kompakt depolama) ortadan kalkar. Sanırım varchar düşündüğümden bile daha kötü!
Jeffrey L Whitledge

9
@PeterAllenWebb - UTF-16'daki vekil çiftler sanki karaktermiş gibi UCS-2'de saklanabileceğinden, herhangi bir Unicode verisini “saklayabilirsiniz”. Bu, veri depolama ve alma için şeffaf bir şekilde çalışacaktır. Şimdi, yapamayacağınız şey BMP dışında güvenilir vaka dönüşümleri ve karşılaştırmalar elde etmek, ancak bununla ilgili herhangi bir iddiada bulunmadım. Bu nedenle, üzerinde işlem yapmak istediğiniz çok fazla Desseret metniniz varsa, bunu veritabanının dışında yapmak en iyisi olacaktır. Ama orada saklamakta fayda var. (Tabii ki, varchar da sana yardım etmeyecek!)
Jeffrey L Whitledge

259

varchar : Değişken uzunlukta, Unicode olmayan karakter verileri. Veritabanı harmanlama, verilerin hangi kod sayfasını kullanarak saklandığını belirler.

nvarchar : Değişken uzunlukta Unicode karakter verileri. Karşılaştırmalar için veritabanı harmanlamasına bağlıdır.

Bu bilgiyle donanmış olarak, giriş verilerinizle hangisini eşleştiriyorsa kullanın (ASCII / Unicode).


5
Varchar Unicode verilerini depolayamıyor gibi bir kısıtlama var mı? Tüm 1'ler ve 0'lar. Çince içeriği varchar olarak benim DB iyi kaydedebilirsiniz. Ben sadece onun UTF-8 belirtin. O halde bu nasıl çalışıyor ?
Nishant

3
@Nishant geç cevap : elbette UTF-8'i varchar içinde saklayabilirsiniz, ancak SQL Server dize işlevlerini bozacaktır . Uygulamanızdaki tüm aramaları / dönüşümleri gerçekleştirirseniz, evet, bunu yapabilirsiniz (ancak faydası nedir?). Yalnızca SS tarafından desteklenen Unicode kodlaması UCS-2'dir (evet, SS2k16'dan önce UTF-16 değil) ve dize işlevleri yalnızca bu kodlamayla çalışır. BTW endeksler ne olacak? Rasgele verileri saklamak istiyorsanız bunun yerine ikili dosya kullanmanız daha iyi olur.
Adriano Repetti

Evet, Dize Arama İşlevlerini kırar.
Nishant

8
Yani, biliyorsun ... "iţe yaramaz". Bu, a'yı depolamak ve "ondalık sayıların kaybolduğundan emin olmak" gibi floatbir intşey. Sadece yapma.
user7116

70

Nvarchar'ı her zaman kullandığım her şeye attığım verilere dayanmasına izin verdiği için kullanıyorum. CMS sistemim yanlışlıkla Çince yapıyor, çünkü nvarchar kullandım. Bu günlerde, herhangi bir yeni başvuru gerçekten gerekli alan miktarıyla ilgilenmemelidir.


25
Yeni uygulamaların alan kısıtlamalarıyla ilgilenmemesi gerektiği fikri biraz kısa görüşlüdür ve orta ve büyük ölçekli kurumsal düzeyde veritabanlarıyla ilgilenen herkes size tamamen yanlıştır.
Frater

60
Etiketleri2k'nin ağzına kelime koyma özgürlüğünü almak için, daha doğru bir ifade, 'herhangi bir yeni uygulamanın, gerekli alan hakkında uluslararasılaşma ve diğer karakter seti sorunları hakkında olması gerekenden daha fazla endişelenmesi' olası olmadığını düşünüyorum.
Cowan

1
"Bu günlerde, herhangi bir yeni uygulama gerçekten gerekli alan miktarıyla ilgilenmemelidir." - Ücretli planın $ olarak göze çarpan bir atlama olduğu ücretsiz bulut depolama alanı kullanmıyorsanız (bkz. AppHarbor SQL Server paylaşılan planları).
14'te

3
@ganders Howl! Tam oradasınız. Genelleştirilmiş ifadeler en iyi ihtimalle yalnızca geçici olarak doğrudur. Bilgi işlem kesinlikle bir salıncak ve dolambaçlı bir oyundur. Kesinlikle Windows Azure CCP'de ne kadar alan kullandığımla ilgileniyorum. Ben nvarchar üzerinde varchar "asla" kullanmak söyledi. Ooo kendimle çeliştim mi?
rism

1
@rism, "never"en azından teknik olarak , tırnak kullanımınızla ilgili herhangi bir çelişki riskini ortadan kaldırdığınıza inanıyorum .
Smandoli

30

Oracle'ın nasıl kurulduğuna bağlıdır. Yükleme işlemi sırasında NLS_CHARACTERSET seçeneği ayarlanır. Sorgu ile bulabilirsiniz SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

NLS_CHARACTERSET'iniz UTF8 gibi bir Unicode kodlamasıysa harika. VARCHAR ve NVARCHAR kullanımı hemen hemen aynıdır. Şimdi okumayı bırak, sadece devam et. Aksi takdirde veya Oracle karakter kümesi üzerinde kontrolünüz yoksa okumaya devam edin.

VARCHAR - Veriler NLS_CHARACTERSET kodlamasında saklanır. Aynı sunucuda başka veritabanı örnekleri varsa, bunlar tarafından kısıtlanmış olabilirsiniz; ve bunun tersi de geçerlidir, çünkü ayarı paylaşmanız gerekir. Böyle bir alan, bu karakter seti kullanılarak kodlanabilen herhangi bir veriyi saklayabilir ve başka hiçbir şey depolayamaz . Örneğin, karakter seti MS-1252 ise, yalnızca İngilizce harfler, bir avuç aksanlı harf ve birkaçı (€ ve - gibi) gibi karakterleri saklayabilirsiniz. Başvurunuz, dünyanın başka hiçbir yerinde çalışamayan yalnızca birkaç yerel ayar için yararlı olacaktır. Bu nedenle, Kötü Bir Fikir olarak kabul edilir.

NVARCHAR - Veriler bir Unicode kodlamasında saklanır. Her dil desteklenmektedir. İyi bir fikir.

Depolama alanı ne olacak? VARCHAR genellikle etkilidir, çünkü karakter seti / kodlama belirli bir yerel ayar için özel olarak tasarlanmıştır. NVARCHAR alanları, NLS ayarına dayanarak ironik bir şekilde UTF-8 veya UTF-16 kodlamasında saklanır. UTF-8, Asya dillerini desteklerken "Batı" dilleri için çok etkilidir. UTF-16 Asya dilleri için çok etkilidir, yine de "Batı" dillerini desteklemektedir. Depolama alanı ile ilgili endişeleriniz varsa, Oracle'ın uygun şekilde UTF-8 veya UTF-16 kullanmasını sağlamak için bir NLS ayarı seçin.

İşlem hızı ne olacak? Çoğu yeni kodlama platformu Unicode'u yerel olarak kullanır (Java, .NET, hatta C ++ std :: wstring yıllar önce!) Bu nedenle veritabanı alanı VARCHAR ise Oracle'ı her okuma veya yazmadaki karakter kümeleri arasında dönüştürme yapmaya zorlar, o kadar iyi değil. NVARCHAR kullanmak dönüşümden kaçınır.

Alt satır: NVARCHAR kullanın! Sınırlamaları ve bağımlılıkları önler, depolama alanı için iyidir ve genellikle performans için de en iyisidir.


42
Bu gerçekten iyi bir cevap, ancak sorunun sql-server ile ilgili olması dışında.
Ekim'i

21

nvarchar verileri Unicode olarak depolar, bu nedenle, çok dilli verileri (birden fazla dil) bir veri sütununda depolayacaksanız, N değişkenine ihtiyacınız vardır.


16

Benim görüşüm

  1. Doğru veri türlerini kullanmadığınızda dizinler başarısız olabilir:
    SQL Server'da: Bir VARCHAR sütunu üzerinde bir dizininiz varsa ve bunu bir Unicode Dizesi sunduğunuzda, SQL Server dizini kullanmaz. SmallInt içeren dizinlenmiş bir sütuna bir BigInt sunduğunuzda da aynı şey olur. BigInt, SmallInt olacak kadar küçük olsa bile, SQL Server dizini kullanamaz. Etrafınızdaki diğer yol bu soruna sahip değildir (dizinlenmiş bir BigInt ot NVARCHAR sütununa SmallInt veya Ansi-Kodu sağlarken).

  2. Veri
    türleri farklı DBMS'ler (Veri Tabanı Yönetim Sistemi) arasında değişiklik gösterebilir: Her veritabanının biraz farklı veri türlerine sahip olduğunu ve VARCHAR'ın her yerde aynı anlama gelmediğini bilin. SQL Server VARCHAR ve NVARCHAR'a sahipken, Apache / Derby veritabanı sadece VARCHAR'a sahiptir ve VARCHAR Unicode'dadır.


Ancak kodunuzu düzgün bir şekilde yazıyorsanız (yani parametrelenmiş sorgular vb. Kullanarak) 1. nokta daha az risk taşır.
Paul

14

Temelde nvarchar , Unicode karakterleri ve varchar, Unicode olmayan karakterleri depolar.

"Unicodes", Arapça, İbranice, Çince, Japonca gibi diğer dillerdeki karakterlerin tek bir karakter kümesinde kodlanmasına olanak sağlayan 16 bit karakter kodlama şeması anlamına gelir.

Diğer bir deyişle, unicodes depolamak için karakter başına 2 bayt, unicodes olmayanlar depolamak için karakter başına yalnızca bir bayt kullanır. Bu, unicodes'lerin unicode olmayanlara kıyasla iki kat daha fazla kapasiteye ihtiyacı olduğu anlamına gelir.


10

Haklısın. Tek baytlık karakter verilerini nvarchardepolarken Unicode verilerini varchardepolar. Depolama farklılıklardan başka ( nvarchariki kat depolama alanı gerektirir varcharzaten bahsedildiği,), en önemli etmen olarak nvarcharüzerinde varchar(diğer dillerde yani depolama dizeleri) uluslararasılaşma olurdu.


10

Ben söyleyebilirim, duruma göre değişir.

İşletim sisteminin Unicode'da (mevcut tüm Windows sistemleri gibi) çalıştığı ve dilin yerel olarak Unicode'u (varsayılan dizeler Unicode, Java veya C # gibi) desteklediği bir masaüstü uygulaması geliştirirseniz, nvarchar'a gidin.

Dizelerin UTF-8 olarak geldiği ve dilin hala Unicode'u yerel olarak (5.x sürümlerinde) desteklemeyen PHP olduğu bir web uygulaması geliştirirseniz, varchar muhtemelen daha iyi bir seçim olacaktır.


9

Her ne kadar NVARCHARsaklar Unicode, ayrıca kullanabilirsiniz harmanlama yardımıyla düşünmelisiniz VARCHARve yerel dillerin sizin verileri kaydetmek.

Aşağıdaki senaryoyu düşünün.

DB'nizin harmanlama Farsça ve VARCHAR(10)veri türünde 'علی' (Ali Farsça yazma) gibi bir değer kaydedin . Sorun yoktur ve DBMS, saklamak için yalnızca üç bayt kullanır.

Ancak, verilerinizi başka bir veritabanına aktarmak ve doğru sonucu görmek istiyorsanız, hedef veritabanınızın bu örnekte Farsça olan hedefle aynı harmanlamaya sahip olması gerekir.

Hedef harmanlamanız farklıysa, hedef veritabanında bazı soru işaretleri (?) Görürsünüz.

Son olarak, yerel dilinizin kullanımı için büyük bir veritabanı kullanıyorsanız, çok fazla alan kullanmak yerine konum kullanmanızı tavsiye ederim.

Tasarımın farklı olabileceğine inanıyorum. Üzerinde çalıştığınız ortama bağlıdır.


8

Ben yanıtlara bir göz vardı ve birçok kullanımı tavsiye görünüyor nvarcharüzerinde varcharboşluk bir sorun artık olmadığı için, çok az ekstra depolama için Unicode sağlayan bir zarar yoktur. Sütununuza bir dizin uygulamak istediğinizde bu her zaman doğru değildir. SQL Server, dizinleyebileceğiniz alanın boyutunda 900 bayt sınırına sahiptir. Eğer varsa varchar(900), yine de dizine alabilirsiniz, ama değil varchar(901). İle nvarchar, karakter sayısı yarıya indirilir, böylece en fazla dizine ekleyebilirsiniz nvarchar(450). Yani ihtiyacınız olmadığından eminseniz, nvarcharkullanmanızı önermiyorum.

Genel olarak, veritabanlarında, ihtiyacınız olan boyuta sadık kalmanızı öneririm, çünkü her zaman genişleyebilirsiniz. Örneğin, çalışan bir meslektaş, bir keresinde nvarchar(max)bir depolama alanı ile ilgili hiçbir sorunumuz olmadığından, bir sütun için kullanımın bir zararı olmadığını düşündü . Daha sonra, bu sütun üzerinde bir dizin uygulamaya çalıştığımızda, SQL Server bunu reddetti. Bununla birlikte, hatta başlamış olsaydı, varchar(5)daha sonra bu sorunu çözmek için bir alan geçiş planı yapmamızı gerektirecek böyle bir sorun olmadan ihtiyacımız olan şeye genişletebilirdik.


7

nVarchar, Unicode karakterleri saklamanıza yardımcı olacaktır. Yerelleştirilmiş verileri depolamak istiyorsanız bu yöntem de kullanılabilir.


7

Bir karakteri saklamak için tek bir bayt kullanılırsa, 256 olası kombinasyon vardır ve böylece 256 farklı karakter kaydedebilirsiniz. Harmanlama, karakterleri ve bunların karşılaştırıldığı ve sıralandığı kuralları tanımlayan kalıptır.

En yaygın olanı Latin1 (ANSI) olan 1252'dir. Tek baytlık karakter setleri de birçok dil tarafından kullanılan tüm karakterleri saklamak için yetersizdir. Örneğin, bazı Asya dillerinde binlerce karakter vardır, bu nedenle karakter başına iki bayt kullanmalıdırlar.

Unicode standardı

Bir ağda birden fazla kod sayfası kullanan sistemler kullanıldığında, iletişimi yönetmek zorlaşır. Şeyleri standardize etmek için, ISO ve Unicode konsorsiyumu tanıtıldı Unicode . Unicode her karakteri depolamak için iki bayt kullanır. Yani 65.536 farklı karakter tanımlanabilir, böylece neredeyse tüm karakterler Unicode ile kaplanabilir. İki bilgisayar Unicode kullanıyorsa, her sembol aynı şekilde temsil edilir ve dönüştürme gerekmez - bu Unicode'un arkasındaki fikirdir.

SQL Server'ın iki karakter veri türü kategorisi vardır:

  • Unicode olmayan (char, varchar ve metin)
  • Unicode (nchar, nvarchar ve ntext)

Karakter verilerini birden fazla ülkeden kaydetmemiz gerekiyorsa, daima Unicode kullanın.


6

Burada söylemeliyim (muhtemelen bir tokatlamaya kendimi açacağımın farkındayım!), Ama NVARCHARaslında tüm harmanlamaların hepsinden daha yararlı olduğu tek zaman ( daha fazlasını fark et !) VARCHARbağımlı sistemlerin ve veritabanı içinde aynı ...? Değilse, harmanlama dönüşümü yine de gerçekleşmelidir ve bu yüzden VARCHARolduğu kadar uygulanabilir hale getirir NVARCHAR.

Buna eklemek için, SQL Server (2012'den önce) gibi bazı veritabanı sistemlerinin sayfa boyutu yakl. 8K. Yani, bir alan TEXTveya NTEXTalan gibi bir şeyde tutulmayan aranabilir verileri depolamak istiyorsanız, o zaman sadece VARCHAR8k değerinde tam alan sağlarken, NVARCHARsadece 4k sağlar (iki kat bayt, iki kat boşluk).

Özetlemek gerekirse, ikisinden birinin kullanımı şunlara bağlıdır:

  • Proje veya bağlam
  • altyapı
  • Veritabanı sistemi

6

Sql Server VARCHAR ve NVARCHAR Veri Türü Arasındaki Farkı Takip Edin . Burada çok açıklayıcı bir şekilde görebilirsiniz.

Genelde, varchar verileri Unicode olarak depolar, bu nedenle, çok dilli verileri (birden fazla dil) bir veri sütununda depolayacaksanız, N değişkenine ihtiyacınız vardır.


Bu çok yararlı bir bağlantı, ancak cevabınız bundan çok daha fazla değil: bir bağlantı.
RubberDuck

ckuhn203, bunu görmeni söylemeyeceğim
Pradeep Kesharwani

6

Arasındaki temel fark Varchar(n)ve nvarchar(n)geçerli: resim açıklamasını buraya girin

Varchar(Değişken uzunluklu, Unicode olmayan karakter verisi) boyutu 8000'e kadar. 1. Değişken uzunluklu bir veri türüdür

  1. Unicode olmayan karakterleri depolamak için kullanılır

  2. Her karakter için 1 bayt alan kaplar

resim açıklamasını buraya girin

Nvarchar: Değişken uzunlukta Unicode karakter verileri.

Değişken uzunlukta bir veri türüdür

2. Unicode karakterleri saklamak için kullanılır.

  1. Veriler bir Unicode kodlamasında saklanır. Her dil desteklenmektedir. (örneğin Arapça, Almanca, Hintçe, vb. diller)

6

~ 47000 itibar puanı olan Jeffrey L Whitledge, nvarchar'ın kullanılmasını önerir

Solomon Rutzky with ~ 33200 itibar puanıyla tavsiye eder: Her zaman NVARCHAR KULLANMAYIN. Bu çok tehlikeli ve genellikle maliyetli bir tutum / yaklaşımdır.

Varchar ve nvarchar SQL Server veri türleri arasındaki temel performans farkları nelerdir?

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

Böyle yüksek bir itibar iki kişi, bir öğrenme sql sunucusu veritabanı geliştiricisi ne seçiyor?

Seçeneklerde tutarlı değilseniz, performans sorunlarıyla ilgili yanıtlarda ve yorumlarda birçok uyarı vardır.

Performans için pro / con nvarchar yorum var.

Performans için pro / con varchar yorumları var.

Kendi içinde muhtemelen olağandışı olan yüzlerce sütun içeren bir tablo için özel bir gereksinimim var?

SQL * Server 2012 8060 bayt tablo kayıt boyutu sınırına yakın önlemek için varchar seçiyorum.

Benim için nvarchar kullanımı bu 8060 bayt sınırını aşıyor.

Ayrıca birincil kod ortalamasının veri türlerine ilgili kod tablolarının veri türlerini eşleşmesi gerektiğini düşünüyorum.

Bu iş yerinde varchar sütununun, Güney Avustralya Hükümeti'nin, daha önceki deneyimli veritabanı geliştiricileri tarafından, tablo satır sayısının birkaç milyon veya daha fazla olacağı (ve varsa, çok az sayıda nvarchar sütununun) kullanıldığını gördüm tablolar), dolayısıyla beklenen veri satırı hacimleri bu kararın bir parçası olabilir.


1

nvarcharUnicode karakterlere de izin verdiğinden varcharkod hatasız (tip uyuşmazlığı) yapmak için karşılaştırıldığında kullanımı güvenlidir nvarchar. whereSQL Server sorgusunda koşulu kullandığımızda ve =işleci kullandığımızda , bazı durumlarda hata verir. Bunun olası nedeni, haritalama sütunumuzun farklılaştırılmasıdır varchar. Eğer bunu nvarcharbu problemde tanımlasaydık olmaz. Yine de varcharbu soruna sadık kalıyoruz ve bundan kaçınmak LIKEyerine anahtar kelimeyi kullanmalıyız =.

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.