Να επαναλάβω, ότι δεν υπάρχει θέμα Unicode στον SQL Server ούτε στο .NET Τα strings του .NET είναι ΠΑΝΤΑ Unicode. Ό,τι αποθηκεύεται σε πεδίο nvarchar είναι εξ ορισμού Unicode. Unicode σημαίνει 2 bytes ανά γράμμα. Αν θέλεις, ο SQL Server χρησιμοποιεί UTF16 και πιο συγκεκριμένα το υποσύνολο UCS2. Το UTF8 από την άλλη χρησιμοποιεί 1 byte για λατινικούς και 2-3 bytes για άλλους χαρακτήρες. Οι τύποι nchar, nvarchar, ntext χρησιμοποιούνε 2 bytes για να αποθηκεύσουν ό,τι τους δώσεις ως Unicode. O SQL Server δεν υποστηρίζει UTF8 οπότε ό,τι προσπαθήσεις να αποθηκεύσεις σε αυτή τη μορφή θα βγει περίεργο (και για το επίσημο του θέματος, δες το Description of Storing UTF8 data in SQL Server). Ο λόγος που αυτό δεν είναι θέμα σε περιβάλλον Windows είναι ότι τόσο το λειτουργικό όσο και οι γλώσσες (C++, .NET, ακόμα και VΒ6) χρησιμοποιούνε πάντα UTF16.
Αν αυτό που τους δώσεις είναι Unicode θα αποθηκευθεί ως έχει. Επιπλέον, το Management Studio χρησιμοποιεί Unicode γραμματοσειρές out-of-the-box οπότε δεν υπάρχει θέμα να σου δείξει λάθος τους Unicode χαρακτήρες. Αν βλέπεις περίεργους χαρακτήρες ή δεν δουλεύεις με nvarchar ή αποθήκευσες χαλασμένα δεδομένα σε nvarchar πεδίο.
Υποψιάζομαι ότι προσπάθησες να αποθηκεύσεις UTF8 χαρακτήρες είτε σε nvarchar είτε σε varchar πεδίο. Επίσης υποψιάζομαι ότι η βιβλιοθήκη που χρησιμοποίησες για την αποθήκευση ή δεν καταλαβαίνει από μετατροπές μεταξύ codepage ή έκανε λάθος μετατροπή. Για παράδειγμα, το OLEDB και το ADO.NET λαμβάνουν υπόψη το codepage τόσο του server όσο και του client για να μετατρέψoyn non-unicode χαρακτήρες στην αντίστοιχη unicode μορφή όταν εκτελείς ένα statement με παραμέτρους, αλλά και να σου επιστρέψουν τα strings στο σωστό codepage αν η εφαρμογή δεν καταλαβαίνει από Unicode. Άλλες βιβλιοθήκες δεν κάνουν σωστά τις μετατροπές των codepages.
Για παράδειγμα, η PHP δεν καταλαβαίνει καν από παραμέτρους οπότε και δεν μπορεί να κάνει καμμία μετατροπή. Για να αποθηκεύσεις σωστά unicode δεδομένα μέσω PHP θα πρέπει να φτιάξεις το σωστό statement, π.χ INSERT INTO MY TABLE (Col1, Col2) VALUES (1, Ν'Το κείμενο μου'). Το έντονο N σημαίνει ότι αυτό που ακολουθεί θα πρέπει να μεταφραστεί ως Unicode. Και φυσικά, για να μεταφραστεί αυτό που ακολουθεί ως Unicode θα πρέπει να ΕΙΝΑΙ Unicode. Αν π.χ. σώσεις το source code σου με ρουμανικό codepage, μην περιμένεις να καταλάβει ο SQL Server ότι εννοούσες να δώσεις ελληνική τιμή. Όταν γίνει compile ο κώδικας ο compiler θα χρησιμοποιήσει το encoding του αρχείου για να καταλάβει ποιό string έδωσες, όχι αυτό που εννοούσες εσύ αλλά δεν προσδιόρισες.
Στα πρακτικά τώρα. Θεωρώντας ότι όντως χρησιμοποιείς nvarchar πεδία, έχεις να λύσεις δύο προβλήματα:
- Αποθηκεύεις δεδομένα σε non-Unicode μορφή. Εδώ υπάρχει μόνο μία λύση, η εφαρμογή σου θα πρέπει να αλλάξει για να αποθηκεύσει σωστά Unicode δεδομένα, σε UTF16.
- Έχεις ήδη αποθηκευμένα δεδομένα σε χαλασμένη μορφή. Είτε θα πρέπει να τα πετάξεις και να τα ξαναεισάγεις, ή θα πρέπει να γράψεις κώδικα για να μετατρέψει τους χαρακτήρες από UTF8 σε UTF16 εφόσον δεν έχουν καταστραφεί κάποιοι χαρακτήρες (π.χ. αντικαταστάθηκαν με κουτάκια ή ? λόγω αδυναμίας μετατροπής κατά την αποθήκευση).
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos