As well as CHAR
(CHARACTER)
and VARCHAR
(CHARACTER VARYING)
, SQL offers an NCHAR
(NATIONAL CHARACTER)
and NVARCHAR
(NATIONAL CHARACTER VARYING)
type. In some databases, this is the better datatype to use for character (non-binary) strings:
In SQL Server, NCHAR
is stored as UTF-16LE and is the only way to reliably store non-ASCII characters, CHAR
being a single-byte codepage only;
In Oracle, NVARCHAR
may be stored as UTF-16 or UTF-8 rather than a single-byte collation;
But in MySQL, NVARCHAR
is VARCHAR
, so it makes no difference, either type can be stored with UTF-8 or any other collation.
So, what does NATIONAL
actually conceptually mean, if anything? The vendors' docs only tell you about what character sets their own DBMSs use, rather than the actual rationale. Meanwhile the SQL92 standard explains the feature even less helpfully, stating only that NATIONAL CHARACTER
is stored in an implementation-defined character set. As opposed to a mere CHARACTER
, which is stored in an implementation-defined character set. Which might be a different implementation-defined character set. Or not.
Thanks, ANSI. Thansi.
Should one use NVARCHAR
for all character (non-binary) storage purposes? Are there currently-popular DBMSs in which it will do something undesirable, or which just don't recognise the keyword (or N''
literals)?
"NATIONAL" in this case means characters specific to different nationalities. Far east languages especially have so many characters that one byte is not enough space to distinguish them all. So if you have an english(ascii)-only app or an english-only field, you can get away using the older CHAR and VARCHAR types, which only allow one byte per character.
That said, most of the time you should use NCHAR/NVARCHAR. Even if you don't think you need to support (or potentially support) multiple languages in your data, even english-only apps need to be able to sensibly handle security attacks using foreign-language characters.
In my opinion, about the only place where the older CHAR/VARCHAR types are still preferred is for frequently-referenced ascii-only internal codes and data on platforms like Sql Server that support the distinction — data that would be the equivalent of an enum
in a client language like C++ or C#.