I have a classic ASP page that gets POSTed to. The data gets POSTed as UTF-8 (I can see this in Fiddler). I then open an ADODB connection to a database and store the data in a VARCHAR field. If the data can be represented by 8859-1 (e.g. iñtërnâtiônàlizætiøn) it is stored correctly in the varchar field. If I try strings that can't be mapped to 8859 (e.g. Здравствуйте!) I get ????????????!. This all makes sense as the varchar field cannot hold unicode. I also understand the using an nvarchar field should enable me to store utf-8 strings.
My question is this. What settings in SQL Server or in the ADODB object control how the strings are converted from UTF-8 to 8859-1? Does VBScript (ASP) send the strings to ADODB.Connection.Execute as UTF-8 (or what I think it is actually doing - UTF-16) and the database itself handles the conversion? Is this controlled by the collation of the database (SQL_Latin1_General_CP1_CI_AS in this case)?
If you switch to using NVARCHAR instead then you'll need to remember to use the N specifier in your SQL commands like so whenever you use a string which is Unicode
INSERT INTO SOME_TABLE (someField) VALUES (N'Some Unicode Text')
SELECT * FROM SOME_TABLE WHERE someField=N'Some Unicode Text'
If you don't do this then the strings won't get treated as Unicode and your data will be silently converted to Latin1 or whatever the default character set for the relevant database/table/field even if that field is a NVARCHAR
You are correct.
VBScript and ADODB only know strings as Unicode (or UTF-16 as its sometimes refered to).
Its part of the DBs collation settings that determine how the VARCHAR fields are encoded.
In SQL_Latin1_General_CP1_CI_AS its really the CP1 bit which is determining the CodePage to use. In this case 1 is a legacy reference to Windows-1252 which is a superset of ISO-8859-1.
Related
We are currently extracting several Teradata .TPT files that we will upload to AWS S3, however the files are coming with ANSI encode
I need them to come with encode UTF-8
You must specify the character set in your TPT script. At the top add:
USING CHARACTER SET UTF8
The tricky part is that UTF8 here has 3 bytes per character, so in your DEFINE SCHEMA you must triple the size of each field.
For example if your schema looks like:
DEFINE SCHEMA s_some_export
(
status VARCHAR(20),
userid VARCHAR(20),
firstname VARCHAR(64),
);
You'll have to triple the values to accommodate your UTF8 characters:
DEFINE SCHEMA s_some_export
(
status VARCHAR(60),
userid VARCHAR(60),
firstname VARCHAR(192),
);
Sometimes, because I'm lazy, I define my TPT with USING CHARACTER SET UTF16 so that I only need double each field size (the math is easier). BUT it means I have to convert it to UTF8 after extraction. In Linux this would just be iconv -f UTF-16LE -t UTF-8 myoutputfile.csv > myoutputfile.utf8.csv
Some caveats:
If your table's field is defined as CHAR and CHARACTER SET LATIN then you may run into column size issues with your schema. see here
Dates and Timestamps can get wierd as they don't need to be doubled so defining them as VARCHAR in your schema can get you into trouble. You may have to fuss around a bit here. My suggestion would be to change the view from which you are selecting the data for you TPT and CAST(yourdate AS VARCHAR(10)) as yourdate and then use VARCHAR(30) in your schema so you don't have to think about the field types while defining your schema. This means extra CPU overhead in your extraction, but unless you are running tight on resources I think it's worth it. I'm also very lazy that way and always happy to just get the damned TPT to extract data without much debugging.
I'm using java swing application which needs unicode string to drag into jtable.Is it possible to store unicode data in SQLITE database? If so,which SQLite does support unicode..I need free sqlite not the premium..
SQLite always stores text data as Unicode, using the Unicode encoding specified when the database was created. The database driver itself takes care to return the data as the Unicode string in the encoding used by your language/platform.
If you have conversion problems, either your application tried to store an ASCII string without converting it to Unicode, or you tried to read one value and force a conversion on it.
SQLite uses a kind of dynamic typing, where each value is stored using a specific storage class. A column's type specifies the affinity or how the value is treated. For example:
A column with NUMERIC affinity may contain values using all five storage classes. When text data is inserted into a NUMERIC column, the storage class of the text is converted to INTEGER or REAL
There are five storage classes, NULL, INTEGER, REAL, TEXT, BLOB. TEXT stores string data using the Unicode encoding specified for the database (UTF-8, UTF-16BE or UTF-16LE).
What specific problem are you facing, or is this a general question?
SQLite always uses Unicode strings.
sqlite3 doesn't fully support UNICODE. There is a wrapper class called CppSQLite3 which fully supports UNICODE>
If i use the htmlEncode method on all strings before i write them to my database, will that remove the need to store string data as the nvarchar datatype?
ie. do all characters which do not exist in the varchar datatype have an encoding value that can be stored within the varchar datatype?
Most likely your SQL server is using Windows-1252 encoding for char and varchar.
If the character is not in Windows-1252 then it is stored as ? mark in char and varchar.
Windows-1252
test by inserting
values (nchar(10000)), ('?')
HtmlEncode(nchar(1000)) is nchar(1000) and if you store it in varchar it will be stored as ?.
So the direct answer to your question is yes there is an varchar encoded value for every Unicode (nvarchar).
But that does not mean that it will decode back to the original value.
I'm looking to encode and store Unicode in a Sqlite database. Is there any way to raw encode a UTF-8 (unicode) string literal in a sql query.
I'm looking for something similar to java where I can toss a \u00E9 into a string and have it automagically upconvert to Unicode.
What language are you using? SQLite handles Unicode just fine, creating the literals in your hosting language is less obvious.
$ sqlite3 junk.sqlite
SQLite version 3.6.22
sqlite> create table names (id integer primary key, name string);
sqlite> insert into names values (null,
'î℉ yõù g𐌹ѷЄ ΣϘГくטƏ UTF-8, it stores it');
sqlite> select * from names;
1|î℉ yõù g𐌹ѷЄ ΣϘГくטƏ UTF-8, it stores it
SQLite doesn't have escape sequences. But your programming language probably does.
# in Python
db.execute("INSERT INTO MyTable(MyColumn) VALUES('\u00E9')")
or
db.execute("INSERT INTO MyTable(MyColumn) VALUES(?)", ['\u00E9'])
If for some reason you have to write a UTF-8 literal in pure SQL, you can do something like:
sqlite> SELECT CAST(X'C3A9' AS TEXT);
é
Edit: Since this answer was originally written, a CHAR function has been added to SQLite. So now, you could write
INSERT INTO MyTable(MyColumn) VALUES(CHAR(233))
If your problem is reinterpretation of escape sequences in sqlite you can (ab)use json_extract eg.
UPDATE `tableToFix` SET `columnToFix` = json_extract('"' || `columnToFix` || '"', '$');
INSERT INTO test VALUE (json_extract('"P\u0159\u00edli\u0161 \u017elu\u0165ou\u010dk\u00fd k\u016f\u0148 \u00fap\u011bl \u010f\u00e1belsk\u00e9 \u00f3dy."', '$'));
Notice: quotes handling. Valid json string starts and ends with " so you must add them before use of json_extract
If you configure your database to use UTF-8 (I believe this is default for many installations; do PRAGMA encoding="UTF-8"; at schema creation time to be certain), this shouldn't be an issue.
If you send SQLite3 a set of characters encoded in UTF-8, it should have no problem dealing with it.
If Java has the ability to allow you to "toss a \u0039 into a string", I'd just use that, and ensure that when you try to place the string into the database, that you have the string convert to a UTF-8 byte encoding using whatever mechanism Java provides. I do not believe SQLite provides or needs to provide this for you.
I have my form set in french as well, and it automatically changes the text format to use ','. However When I try to insert my values into the database it says cannot convert nvarchar to decimal?
Worst case, Is there a way I can disable the numbers from changing to use ',' and just use '.' always regardless what language it is?
My working language is vb.net
Thanks,
Robert
If you're passing the values down to the database as nvarchar then you'll need to have converted this to a string using yourDecimalValue.ToString(Globalization.CultureInfo.InvariantCulture) or similar. SQL Server will always expect a decimal to be in 1.23 format - you can imagine the trouble that would result if queries including WHERE myvalue IN (1,25, 1,33, 1,45) were submitted!