How to script tables in SSMS that contain non-unicode text - sql-server

I'm working with some tables in SQL Server that store text using 8-bit characters rather than unicode -- varchar rather than nvarchar. A certain amount of the text contains characters with values outside the ASCII range, for example curly quotes, em-dashes, and international characters such as ñ. Presumably this works because all our PCs and servers use the same code page.
However, when I use the Task > Generate Scripts scripting tool in SSMS to script such a table, the resulting script translates the special characters in such a way that if I use the script to reconstruct the table, the special characters are corrupted. For example "cañon" becomes "ca±on." I can see this in the INSERT statements that the script contains, where "cañon" from the database appears as "ca±on" in the INSERT statement.
In SSMS, how do I script a table that contains varchar data outside the ASCII range so that round-tripping will work?

In the Script Wizard's Output Option, you need to save as ANSI text, if you want to script extended ASCII data in CHAR and VARCHAR fields correctly.

Related

TSQL FOR XML Exporting ACTUAL UTF-8 Encoded data

We have a process that writes XML (Using SQL's FOR XML). When it was executed via SQLCMD in a batch file the output was in UTF-8 format (specifically 8-bit ascii characters become 2 byte).
When I do the same thing through Execute SQL Command in SSIS it's not UTF-8 encoded.
Here's a simple example. The ® should become 2 bytes:
SELECT 'Diversity® Certified' as fldAgentLastName
FOR XML PATH('agent'), ELEMENTS, TYPE, ROOT('agents')
The output is: Diversity® Certified
it SHOULD be: Diversity® Certified
and was using SQLCMD. I understand that internally XML is stored as UCS-2(?), but I need a way to get the output as UTF-8 encoded data (not just 8-bit).
I also cannot use the BCP trick I've seen mentioned.
I don't want to use the CDATA tag because that would entail recreating a giant ugly query.
Everything I've found on the web doesn't encode the high ascii characters.
This is running on SQL Server 2008 R2.
I guess all I had to do was ask, and then I'd find my own answer: The problem wasn't with SQL, it was downstream in SSIS. I changed the codepage for a CONVERT as well as the final Text file to 65001 based on this answer in another thread:
...The workaround is simple albeit counterintuitive - add a Data Conversion Transformation step between the OLE DB Source and the Flat-File Destination that converts your input "Dat" column from DT_NTEXT to DT_TEXT with a codepage of 65001. Then you feed the newly transformed column directly to the output column in your flat-file dest. ... Regards, Jacob
http://www.sqlservercentral.com/Forums/Topic719421-149-1.aspx

Microsoft SQL Server database character conversion

I have a database imported that contains Arabic characters but are displayed as question marks. Through some searching I found that the column data types should be nvarchar to support unicode (they were varchar). I changed one of the columns that contains those characters to nvarchar but the data is still displayed as "??". How can I change the existing values to become unicode and display correctly?
You cannot just simply change the datatype to nvarchar - that won't bring back the data since it's already been "destroyed" by having been converted to a non-Unicode format.
You need to use nvarchar and then you need to insert (or update) the data in such a way that doesn't convert it back to ANSI codes.
If you use T-SQL to insert that Unicode code, make sure to use the N'...' prefix:
INSERT INTO dbo.YourTable(NvarcharCol)
VALUES (N'nvarchar-value')
From a front-end language like C# or PHP or Ruby, make sure to use Unicode strings - .NET (C# and VB.NET) does that automatically. When using queries with parameters, make sure to specify Unicode string types for those relevant parameters.
You need different collation.
Read more here: https://msdn.microsoft.com/en-us/library/ms143508.aspx

Japanese Character in Oracle Database not displayed properly

I recently created an Oracle DB with JA16SJIS Character Set.
And then I try to insert some data include Japanese characters using SQL*Plus running an external SQL file. The file is encoded in Shift-JIS (and I can see Japanese characters properly in the file using notepad++).
Inserting was success but when I select the data (using SQL*Plus), Japanese characters are not displayed properly (like some alphabet characters with some question marks).
Even when I use SQL Developer to view the data, Japanese characters still unreadable.
And I'm using Window 7 Professional SP1, Oracle Database 11g R2, system locale set to Japan as well.
First, you should try to insert some text directly from SQLDeveloper data view. That should work no matter what, so you can use it to check your imports.
Then before you connect with SQL*Plus you must specify what you're going to send by setting or changing the value of environment variable NLS_LANG.
NSL_LANG=ENGLISH_FRANCE.JA16SJIS
The syntax will depend on your OS. The only important part is the last one JA16SJIS which means Shift-Jis as you already know.
You can then connect with SQL*Plus and import your file.
Note that the encoding that you specify must match the encoding of your file but not necessarily the encoding of the base as Oracle will do a conversion if necessary. So you could have your base in UTF8 and it would still work (because UTF8 can hold japanese characters).
In these cases the first thing I do is to have a look at what byte values are stored in the database. You can use the dump function for that.
select dump(<column>) from <table>
If you know what byte values your characters should have you can check if the correct values are in your table.

Unicode conversion, database woes (Delphi 2007 to XE2)

Currently, I am in the process of updating all of our Delphi 2007 code base to Delphi XE2. The biggest consideration is the ANSI to Unicode conversion, which we've dealt with by re-defining all base types (char/string) to ANSI types (ansichar/ansistring). This has worked in many of our programs, until I started working with the database.
The problem started when I converted a program that stores information read from a file into an SQL Server 2008 database. Suddenly simple queries that used a string to locate data would fail, such as:
SELECT id FROM table WHERE name = 'something'
The name field is a varchar. I found that I was able to complete the query successfully by prefixing the string name with an N. I was under the impression that varchar could only store ANSI characters, but it appears to be storing Unicode?
Some more information: the name field in Delphi is string[13], but I've tried dropping the [13]. The database collation is SQL_Latin1_General_CP1_CI_AS. We use ADO to interface with the database. The connection information is stored in the ODBC Administrator.
NOTE: I've solved my actual problem thanks to a bit of direction from Panagiotis. The name we read from our map file is an array[1..24] of AnsiChar. This value was being implicitly converted to string[13], which was including null characters. So a name with 5 characters was really being stored as the 5 characters + 8 null characters in the database.
varchar fields do NOT store Unicode characters. They store ASCII values in the codepage specified by the field's collation. SQL Server will try to convert characters to the correct codepage when you try to store Unicode or data from a different codepage. You can disable this feature but the best option is to avoid the whole mess by using nvarchar fields and UnicodeString in your application.
You mention that you changes all character types to ANSI, not UNICODE types in your application. If you want to use UNICODE you should be using a UNICODE type like UnicodeString. Otherwise your values will be converted to ANSI when they are sent to your server. This conversion is done by your code when you create the AnsiString that is sent to the server.
BTW, your select statement stores an ASCII value in the field. You have to prepend the value with N if you want to store it as a unicode value, eg.g
SELECT id FROM table WHERE name = N'something'
Even this will not guarantee that your data will reach the server in a Unicode form. If you store the statement in an AnsiString the entire statement is converted to ANSI before it is sent to the server. If your app makes a wrong conversion, you will end up with mangled data on the server.
The solution is very simple, just use parameterized statements to pass unicode values as unicode parameters and store them in NVarchar fields. It is much faster, avoids all conversion errors and prevents SQL injection attacks.

How can I recover Unicode data which displays in SQL Server as?

I have a database in SQL Server containing a column which needs to contain Unicode data (it contains user's addresses from all over the world e.g. القاهرة‎ for Cairo)
This column is an nvarchar column with a collation of database default (Latin1_General_CI_AS), but I've noticed data inserted into it via SQL statements containing non English characters and displays as ?????.
The solution seems to be that I wasn't using the n prefix e.g.
INSERT INTO table (address) VALUES ('القاهرة')
Instead of:
INSERT INTO table (address) VALUES (n'القاهرة')
I was under the impression that Unicode would automatically be converted for nvarchar columns and I didn't need this prefix, but this appears to be incorrect.
The problem is I still have some data in this column which appears as ????? in SQL Server Management Studio and I don't know what it is!
Is the data still there but in an incorrect character encoding preventing it from displaying but still salvageable (and if so how can I recover it?), or is it gone for good?
Thanks,
Tom
To find out what SQL Server really stores, use
SELECT CONVERT(VARBINARY(MAX), 'some text')
I just tried this with umlauted characters and Arabic (copied from Wikipedia, I have no idea) both as plain strings and as N'' Unicode strings.
The results are that Arabic non-Unicode strings really end up as question marks (0x3F) in the conversion to VARCHAR.
SSMS sometimes won't display all characters, I just tried what you had and it worked for me, copy and paste it into Word and it might display it corectly
Usually if SSMS can't display it it should be boxes not ?
Try to write a small client that will retrieve these data to a file or web page. Check ALL your code if there are no other inserts or updates that might convertthe data to varchar before storing them in tables.

Resources