Apa perbedaan antara varchar dan nvarchar?

1354

Apakah hanya itu yang nvarcharmendukung karakter multibyte? Jika itu masalahnya, apakah benar-benar ada gunanya, selain masalah penyimpanan, untuk digunakan varchars?

rangsangan
sumber
6
Saya suka poin incomudro, itulah yang membuat saya menggali tentang perbedaan antara varchar & nvarchar. Aplikasi Java kami terhadap SQL Server db menggunakan myBatis, yang tampaknya mengirim string sebagai nvarchar secara default (masih tidak yakin bagaimana (atau jika) itu dapat ditimpa). Kueri sederhana muncul sebagai masalah kinerja yang sangat besar karena saya telah mendefinisikan kolom yang dipilihnya sebagai varchar, bukan nvarchar, dan mengabaikan indeks pada kolom.
Sean Read

Jawaban:

1652

Sebuah nvarcharkolom dapat menyimpan data Unicode. Sebuah varcharkolom dibatasi untuk 8-bit codepage. Beberapa orang berpikir bahwa itu varcharharus digunakan karena memakan lebih sedikit ruang. Saya percaya ini bukan jawaban yang benar. Ketidakcocokan codepage sangat menyakitkan, dan Unicode adalah obat untuk masalah codepage. Dengan disk dan memori yang murah saat ini, benar-benar tidak ada alasan untuk membuang waktu mucking dengan halaman kode lagi.

Semua sistem operasi modern dan platform pengembangan menggunakan Unicode secara internal. Dengan menggunakan nvarchardaripada varchar, Anda dapat menghindari melakukan konversi pengkodean setiap kali Anda membaca dari atau menulis ke database. Konversi membutuhkan waktu, dan rentan terhadap kesalahan. Dan pemulihan dari kesalahan konversi bukanlah masalah sepele.

Jika Anda berinteraksi dengan aplikasi yang hanya menggunakan ASCII, saya masih akan merekomendasikan menggunakan Unicode dalam database. Algoritma collation OS dan basis data akan bekerja lebih baik dengan Unicode. Unicode menghindari masalah konversi ketika berinteraksi dengan sistem lain . Dan Anda akan mempersiapkan masa depan. Dan Anda selalu dapat memvalidasi bahwa data Anda terbatas pada ASCII 7-bit untuk sistem warisan apa pun yang harus Anda pertahankan, bahkan sambil menikmati beberapa manfaat penyimpanan Unicode penuh.

Jeffrey L Whitledge
sumber
8
Ini adalah info hebat untuk dimiliki. Jadi, apakah saya memahami ini dengan benar jika saya menyimpulkan bahwa pilihan pada akhirnya menjadi salah satu - sumber daya mana yang lebih murah: prosesor atau pengembangan overhead atau penyimpanan?
Matt Cashatt
141
@ MatthewPatrickCashatt - Anda bisa melihatnya seperti itu. Tetapi jika Anda membayangkan dunia yang mulia di mana semua data teks berada di Unicode, dan pengembang tidak perlu berpikir tentang apa pengkodean sesuatu di dalamnya , dan seluruh kelas kesalahan tidak pernah terjadi, maka Anda dapat melihat bahwa ada benar-benar tidak ada pilihan sama sekali.
Jeffrey L Whitledge
8
@ Martin Smith - Dalam kasus itu, keuntungan kecil yang diberikan varchar (penyimpanan kompak) menghilang. Saya kira varchar bahkan lebih buruk dari yang saya kira!
Jeffrey L Whitledge
9
@PeterAllenWebb - Anda dapat "menyimpan" data Unicode, karena pasangan pengganti dalam UTF-16 dapat disimpan dalam UCS-2 seolah-olah mereka adalah karakter. Itu akan bekerja secara transparan untuk penyimpanan dan pengambilan data. Sekarang, yang tidak bisa Anda lakukan adalah mendapatkan transformasi dan perbandingan kasus yang andal di luar BMP, tapi saya tidak membuat klaim tentang itu. Jadi jika Anda memiliki banyak teks Desseret yang ingin Anda lakukan pemrosesan, akan lebih baik melakukannya di luar basis data. Tapi tidak apa-apa untuk menyimpannya di sana. (Tentu saja, varchar juga tidak akan membantu Anda di sana!)
Jeffrey L Whitledge
259

varchar : Variabel-panjang, data karakter non-Unicode. Basis data basis data menentukan halaman kode mana data disimpan menggunakan.

nvarchar : Data karakter Unicode-panjang variabel. Bergantung pada pemeriksaan basis data untuk perbandingan.

Berbekal pengetahuan ini, gunakan mana yang cocok dengan data input Anda (ASCII v. Unicode).

pengguna7116
sumber
5
Apakah ada batasan seperti varchar yang tidak bisa menyimpan data Unicode? Semuanya 1 dan 0. Saya dapat menyimpan konten berbahasa Mandarin sebagai varchar, cukup baik untuk DB saya. Saya hanya menentukan UTF-8. Bagaimana cara kerjanya?
Nishant
3
@Nantant terlambat menjawab : tentu saja Anda dapat menyimpan UTF-8 di varchar tetapi itu akan merusak fungsi string SQL Server. Jika Anda melakukan semua pencarian / transformasi dalam aplikasi Anda maka ya, Anda dapat melakukannya (tapi apa untungnya?). Hanya penyandian Unicode yang didukung oleh SS adalah UCS-2 (ya, bukan UTF-16 sebelum SS2k16) dan fungsi stringnya hanya berfungsi dengan penyandian itu. BTW bagaimana dengan indeks? Jika Anda ingin menyimpan data arbitrer, Anda sebaiknya menggunakan biner.
Adriano Repetti
Ya itu hanya merusak Fungsi Pencarian String.
Nishant
8
Jadi, Anda tahu ... itu tidak "berhasil". Itu seperti menyimpan floatke dalam intdan pergi, "tentu saja desimalnya hilang." Hanya saja, jangan.
user7116
70

Saya selalu menggunakan nvarchar karena memungkinkan apa pun yang saya bangun untuk menahan hampir semua data yang saya lemparkan padanya. Sistem CMS saya melakukan bahasa Mandarin secara tidak sengaja, karena saya menggunakan nvarchar. Saat ini, setiap aplikasi baru seharusnya tidak benar-benar peduli dengan jumlah ruang yang dibutuhkan.

tags2k
sumber
25
Gagasan bahwa aplikasi baru seharusnya tidak peduli dengan pembatasan ruang agak picik, dan siapa pun yang telah berurusan dengan basis data di tingkat perusahaan menengah hingga besar akan dengan senang hati memberi tahu Anda, sepenuhnya salah.
Frater
60
Untuk mengambil kebebasan menempatkan kata-kata di mulut tag2k, saya pikir pernyataan yang lebih akurat mungkin 'semakin tidak mungkin bahwa aplikasi baru harus lebih peduli tentang ruang yang diperlukan daripada harus tentang internasionalisasi dan masalah set karakter lainnya'.
Cowan
1
"Saat ini, semua aplikasi baru seharusnya tidak benar-benar peduli dengan jumlah ruang yang dibutuhkan." - Kecuali Anda menggunakan penyimpanan cloud gratis, di mana paket berbayar adalah lompatan PERTIMBANGAN $ (lihat paket bersama AppHarbor SQL Server).
ganders
3
@ pedagang Howl! Anda di sana. Pernyataan yang digeneralisasi hanya benar sementara untuk yang terbaik. Komputasi jelas merupakan permainan ayunan dan putaran. Saya pasti peduli dengan berapa banyak ruang yang saya gunakan pada Windows Azure CCP. Yang mengatakan saya akan "tidak pernah" menggunakan varchar di atas nvarchar. Ooo, apakah saya baru saja berkontradiksi dengan diri saya sendiri?
rism
1
@rism, saya yakin Anda telah menghapus risiko kontradiksi dengan penggunaan tanda kutip "never", setidaknya secara teknis.
Smandoli
30

Itu tergantung pada bagaimana Oracle diinstal. Selama proses instalasi, opsi NLS_CHARACTERSET diatur. Anda mungkin dapat menemukannya dengan kueri SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Jika NLS_CHARACTERSET Anda adalah penyandian Unicode seperti UTF8, hebat. Menggunakan VARCHAR dan NVARCHAR cukup mirip. Berhenti membaca sekarang, lakukan saja. Jika tidak, atau jika Anda tidak memiliki kendali atas set karakter Oracle, baca terus.

VARCHAR - Data disimpan dalam pengkodean NLS_CHARACTERSET. Jika ada contoh database lain di server yang sama, Anda mungkin dibatasi oleh mereka; dan sebaliknya, karena Anda harus berbagi pengaturan. Bidang seperti itu dapat menyimpan data apa pun yang dapat dikodekan menggunakan set karakter itu, dan tidak ada yang lain . Jadi misalnya jika rangkaian karakter adalah MS-1252, Anda hanya dapat menyimpan karakter seperti huruf bahasa Inggris, beberapa huruf beraksen, dan beberapa lainnya (seperti € dan -). Aplikasi Anda akan berguna hanya untuk beberapa lokal, tidak dapat beroperasi di tempat lain di dunia. Untuk alasan ini, itu dianggap sebagai Ide Buruk.

NVARCHAR - Data disimpan dalam pengkodean Unicode. Setiap bahasa didukung. Sebuah ide bagus.

Bagaimana dengan ruang penyimpanan? VARCHAR umumnya efisien, karena set karakter / pengodean dirancang khusus untuk lokal tertentu. Bidang NVARCHAR disimpan baik dalam pengkodean UTF-8 atau UTF-16, berdasarkan pada pengaturan NLS yang cukup ironis. UTF-8 sangat efisien untuk bahasa "Barat", sementara masih mendukung bahasa Asia. UTF-16 sangat efisien untuk bahasa Asia, sementara masih mendukung bahasa "Barat". Jika khawatir tentang ruang penyimpanan, pilih pengaturan NLS untuk menyebabkan Oracle menggunakan UTF-8 atau UTF-16 yang sesuai.

Bagaimana dengan kecepatan pemrosesan? Kebanyakan platform pengkodean baru menggunakan Unicode secara native (Java, .NET, bahkan C ++ std :: wstring dari tahun yang lalu!) Jadi jika bidang basis data adalah VARCHAR, ia akan memaksa Oracle untuk mengonversi antar set karakter pada setiap baca atau tulis, tidak begitu baik. Menggunakan NVARCHAR menghindari konversi.

Intinya: Gunakan NVARCHAR! Ini menghindari batasan dan dependensi, baik untuk ruang penyimpanan, dan biasanya paling baik untuk kinerja juga.

Jeremy Frank
sumber
42
Ini adalah jawaban yang sangat bagus, kecuali bahwa pertanyaannya adalah tentang sql-server.
merangsang
21

nvarchar menyimpan data sebagai Unicode, jadi, jika Anda akan menyimpan data multibahasa (lebih dari satu bahasa) di kolom data, Anda memerlukan varian N.

albertein
sumber
16

Dua sen saya

  1. Indeks dapat gagal saat tidak menggunakan tipe data yang benar:
    Di SQL Server: Ketika Anda memiliki indeks di atas kolom VARCHAR dan menyajikannya sebagai String Unicode, SQL Server tidak menggunakan indeks. Hal yang sama terjadi ketika Anda menyajikan BigInt ke kolom diindeks yang berisi SmallInt. Bahkan jika BigInt cukup kecil untuk menjadi SmallInt, SQL Server tidak dapat menggunakan indeks. Sebaliknya Anda tidak memiliki masalah ini (saat memberikan SmallInt atau Ansi-Code ke BigInt ot indexed NVARCHAR kolom).

  2. Datatypes dapat bervariasi antara DBMS (Sistem Manajemen DataBase) yang berbeda:
    Ketahuilah bahwa setiap database memiliki tipe data yang sedikit berbeda dan VARCHAR tidak berarti sama di mana-mana. Sementara SQL Server memiliki VARCHAR dan NVARCHAR, database Apache / Derby hanya memiliki VARCHAR dan ada VARCHAR di Unicode.

incomudro
sumber
Tapi tentu saja jika Anda menulis kode Anda dengan benar (yaitu menggunakan query parameterised dll) maka poin 1 lebih kecil risikonya.
Paul
14

Terutama nvarchar menyimpan karakter Unicode dan varchar menyimpan karakter non-Unicode.

"Unicodes" berarti skema pengkodean karakter 16-bit yang memungkinkan karakter dari banyak bahasa lain seperti Arab, Ibrani, Cina, Jepang, dikodekan dalam satu set karakter tunggal.

Itu berarti unicodes menggunakan 2 byte per karakter untuk menyimpan dan nonunicodes hanya menggunakan satu byte per karakter untuk menyimpan. Yang berarti unicodes membutuhkan kapasitas ganda untuk menyimpan dibandingkan dengan non-unicodes.

ranjit pawar
sumber
10

Kamu benar. nvarcharmenyimpan data Unicode sambil varcharmenyimpan data karakter bita tunggal. Selain perbedaan penyimpanan ( nvarcharmemerlukan ruang penyimpanan dua kali lipat varchar), yang telah Anda sebutkan, alasan utama untuk memilih nvarcharlebih varcharadalah internasionalisasi (mis. Menyimpan string dalam bahasa lain).

Mike Spross
sumber
10

Saya akan mengatakan, itu tergantung.

Jika Anda mengembangkan aplikasi desktop, di mana OS bekerja di Unicode (seperti semua sistem Windows saat ini) dan bahasa tidak mendukung Unicode (string default adalah Unicode, seperti di Jawa atau C #), kemudian buka nvarchar.

Jika Anda mengembangkan aplikasi web, dengan string sebagai UTF-8, dan bahasa adalah PHP, yang masih tidak mendukung Unicode secara asli (dalam versi 5.x), maka varchar mungkin akan menjadi pilihan yang lebih baik.

sleepy012
sumber
9

Meskipun NVARCHARmenyimpan Unicode, Anda harus mempertimbangkan dengan bantuan kolasi juga Anda dapat menggunakan VARCHARdan menyimpan data bahasa lokal Anda.

Bayangkan saja skenario berikut.

Susunan DB Anda adalah Persia dan Anda menyimpan nilai seperti 'علی' (tulisan Ali dari Persia) di dalam VARCHAR(10)datatype. Tidak ada masalah dan DBMS hanya menggunakan tiga byte untuk menyimpannya.

Namun, jika Anda ingin mentransfer data Anda ke database lain dan melihat hasil yang benar, database tujuan Anda harus memiliki susunan yang sama dengan target yang Persia dalam contoh ini.

Jika pengumpulan target Anda berbeda, Anda melihat beberapa tanda tanya (?) Di database target.

Akhirnya, ingat jika Anda menggunakan basis data besar yang untuk penggunaan bahasa lokal Anda, saya akan merekomendasikan untuk menggunakan lokasi daripada menggunakan terlalu banyak ruang.

Saya percaya desainnya bisa berbeda. Itu tergantung pada lingkungan tempat Anda bekerja.

Ali Elmi
sumber
8

Saya telah melihat jawaban dan tampaknya banyak yang merekomendasikan untuk menggunakan nvarcharlebih varchar, karena ruang tidak menjadi masalah lagi, jadi tidak ada salahnya mengaktifkan Unicode untuk penyimpanan ekstra. Ya, ini tidak selalu benar ketika Anda ingin menerapkan indeks di atas kolom Anda. SQL Server memiliki batas 900 byte pada ukuran bidang yang dapat Anda indeks. Jadi jika Anda punya, varchar(900)Anda masih bisa mengindeksnya, tetapi tidak varchar(901). Dengan nvarchar, jumlah karakter dibelah dua, sehingga Anda dapat mengindeks hingga nvarchar(450). Jadi, jika Anda yakin tidak perlu nvarchar, saya tidak menyarankan menggunakannya.

Secara umum, dalam database, saya sarankan tetap pada ukuran yang Anda butuhkan, karena Anda selalu dapat memperluas. Misalnya, seorang kolega di tempat kerja pernah berpikir bahwa tidak ada salahnya menggunakan nvarchar(max)untuk kolom, karena kami tidak punya masalah dengan penyimpanan sama sekali. Kemudian, ketika kami mencoba menerapkan indeks di atas kolom ini, SQL Server menolak ini. Namun, jika dia mulai dengan genap varchar(5), kita bisa saja mengembangkannya nanti untuk apa yang kita butuhkan tanpa masalah yang mengharuskan kita melakukan rencana migrasi lapangan untuk memperbaiki masalah ini.

Rafid
sumber
7

nVarchar akan membantu Anda menyimpan karakter Unicode. Ini adalah cara untuk pergi jika Anda ingin menyimpan data yang dilokalkan.

Vijesh VP
sumber
7

Jika satu byte digunakan untuk menyimpan karakter, ada 256 kemungkinan kombinasi, dan dengan demikian Anda dapat menyimpan 256 karakter berbeda. Kolasi adalah pola yang mendefinisikan karakter dan aturan yang digunakan untuk membandingkan dan mengurutkannya.

1252, yang merupakan Latin1 (ANSI), adalah yang paling umum. Set karakter byte tunggal juga tidak memadai untuk menyimpan semua karakter yang digunakan oleh banyak bahasa. Sebagai contoh, beberapa bahasa Asia memiliki ribuan karakter, jadi mereka harus menggunakan dua byte per karakter.

Standar Unicode

Ketika sistem menggunakan beberapa halaman kode digunakan dalam jaringan, menjadi sulit untuk mengelola komunikasi. Untuk membakukan berbagai hal, konsorsium ISO dan Unicode memperkenalkan Unicode . Unicode menggunakan dua byte untuk menyimpan setiap karakter. Itu adalah 65.536 karakter yang berbeda dapat didefinisikan, sehingga hampir semua karakter dapat ditutupi dengan Unicode. Jika dua komputer menggunakan Unicode, setiap simbol akan diwakili dengan cara yang sama dan tidak ada konversi yang diperlukan - ini adalah ide di balik Unicode.

SQL Server memiliki dua kategori tipe data:

  • non-Unicode (char, varchar, dan teks)
  • Unicode (nchar, nvarchar, dan ntext)

Jika kita perlu menyimpan data karakter dari berbagai negara, selalu gunakan Unicode.

Jithin Shaji
sumber
6

Saya harus katakan di sini (saya menyadari bahwa saya mungkin akan membuka diri untuk slating!), Tapi pasti satu-satunya waktu ketika NVARCHARsebenarnya lebih berguna (perhatikan lebih banyak di sana!) Daripada VARCHARketika semua pemeriksaan pada semua dari sistem dependen dan dalam database itu sendiri sama ...? Jika tidak, maka konversi susunan harus tetap terjadi dan karenanya VARCHARlayak NVARCHAR.

Untuk menambah ini, beberapa sistem database, seperti SQL Server (sebelum 2012) memiliki ukuran halaman kira-kira. 8 rb Jadi, jika Anda ingin menyimpan data yang dapat ditelusuri yang tidak disimpan dalam bidang TEXTatau NTEXTbidang seperti itu VARCHAR, sediakan ruang seharga 8k penuh sedangkan NVARCHARhanya menyediakan 4k (gandakan byte, gandakan ruang).

Saya kira, untuk meringkas, penggunaan keduanya tergantung pada:

  • Proyek atau konteks
  • Infrastruktur
  • Sistem basis data
Paul
sumber
6

Ikuti Perbedaan Antara Sql Server VARCHAR dan Tipe Data NVARCHAR . Di sini Anda bisa melihat dengan cara yang sangat deskriptif.

Dalam generalnvarchar menyimpan data sebagai Unicode, jadi, jika Anda akan menyimpan data multibahasa (lebih dari satu bahasa) di kolom data, Anda memerlukan varian N.

Pradeep Kesharwani
sumber
Ini adalah tautan yang sangat berguna, tetapi jawaban Anda tidak lebih dari itu: sebuah tautan.
RubberDuck
ckuhn203, saya tidak akan memberitahu Anda untuk melihat yang ini
Pradeep Kesharwani
6

Perbedaan utama antara Varchar(n)dan nvarchar(n)adalah: masukkan deskripsi gambar di sini

Varchar(Variabel-panjang, data karakter non-Unicode) ukuran hingga 8000. 1. Ini adalah tipe data panjang variabel

  1. Digunakan untuk menyimpan karakter non-Unicode

  2. Menempati 1 byte ruang untuk setiap karakter

masukkan deskripsi gambar di sini

Nvarchar: Variabel-panjang data karakter Unicode.

1. Ini adalah tipe data panjang variabel

2. Digunakan untuk menyimpan karakter Unicode.

  1. Data disimpan dalam pengkodean Unicode. Setiap bahasa didukung. (misalnya bahasa Arab, Jerman, Hindi, dll dan sebagainya)
Debendra Dash
sumber
6

Jeffrey L Whitledge dengan ~ 47000 skor reputasi merekomendasikan penggunaan nvarchar

Solomon Rutzky dengan dengan ~ 33200 skor reputasi merekomendasikan: JANGAN selalu menggunakan NVARCHAR. Itu adalah sikap / pendekatan yang sangat berbahaya, dan seringkali mahal.

Apa perbedaan kinerja utama antara tipe data SQL Server varchar dan nvarchar?

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

Kedua orang dengan reputasi tinggi, apa yang dipilih oleh pengembang basis data server sql?

Ada banyak peringatan dalam jawaban dan komentar tentang masalah kinerja jika Anda tidak konsisten dalam pilihan.

Ada komentar pro / kontra nvarchar untuk kinerja.

Ada komentar pro / kontra varchar untuk kinerja.

Saya memiliki persyaratan khusus untuk tabel dengan ratusan kolom, yang dengan sendirinya mungkin tidak biasa?

Saya memilih varchar untuk menghindari mendekati batas ukuran catatan tabel 8060 byte dari SQL * server 2012.

Penggunaan nvarchar, bagi saya, melampaui batas 8060 byte ini.

Saya juga berpikir bahwa saya harus mencocokkan tipe data dari tabel kode terkait dengan tipe data dari tabel pusat primer.

Saya telah melihat penggunaan kolom varchar di tempat kerja ini, Pemerintah Australia Selatan, oleh pengembang database yang berpengalaman sebelumnya, di mana jumlah baris tabel akan menjadi beberapa juta atau lebih (dan sangat sedikit kolom nvarchar, jika ada, dalam jumlah yang sangat besar ini tabel), jadi mungkin volume baris data yang diharapkan menjadi bagian dari keputusan ini.

Allan F
sumber
1

nvarcharaman untuk digunakan dibandingkan dengan varcharuntuk membuat kesalahan kode kami gratis (ketik ketidakcocokan) karena nvarcharmemungkinkan karakter unicode juga. Ketika kami menggunakan wherekondisi dalam permintaan SQL Server dan jika kami menggunakan =operator, itu akan melemparkan kesalahan beberapa kali. Alasan yang mungkin untuk hal ini adalah kolom pemetaan kami akan difinalkan varchar. Jika kita mendefinisikannya dalam nvarcharmasalah ini, saya tidak akan terjadi. Masih kami menempel varchardan menghindari masalah ini kita lebih baik menggunakan LIKEkata kunci daripada =.

Rinoy Ashokan
sumber