@gbn ইতিমধ্যে মূল কারণ এবং সংশোধন ব্যাখ্যা করেছে, তবে আপনি যে আচরণটি দেখছেন তার সুনির্দিষ্ট কারণ হ'ল:
- আপনি
VARCHAR
আক্ষরিক ( N
উপসর্গের NVARCHAR
সাথে স্ট্রিং ) পরিবর্তে আক্ষরিক (কোনও উপসর্গ নেই) ব্যবহার করছেন N
, সুতরাং ইউনিকোড অক্ষর রূপান্তরিত হবে VARCHAR
।
VARCHAR
একটি 8-বিট এনকোডিং যা বেশিরভাগ ক্ষেত্রে চরিত্র অনুসারে একটি বাইট হয় তবে প্রতিটি চরিত্রে দুটি বাইটও হতে পারে। অন্যদিকে, NVARCHAR
একটি 16-বিট এনকোডিং (ইউটিএফ -16 লিটল এন্ডিয়ান) যা চরিত্র অনুসারে দুটি বাইট বা চার বাইট হয়।
- ম্যাপিং অক্ষরের জন্য ব্যবহারযোগ্য উপলভ্য বাইটের সংখ্যার পার্থক্যের কারণে, 8 টি বিট এনকোডিংগুলি তাদের প্রকৃতি অনুসারে ম্যাপ করা যায় এমন অক্ষরের সংখ্যায় আরও সীমিত।
VARCHAR
একক-বাইট চরিত্রের সেটগুলি (তাদের বেশিরভাগের) জন্য 256 টি অক্ষর এবং ডাবল-বাইট চরিত্রের সেটগুলির জন্য 65,536 টি পর্যন্ত অক্ষর (এর মধ্যে কেবল কয়েকটি)। অন্যদিকে, NVARCHAR
ডেটা কেবলমাত্র 1.1 মিলিয়ন ইউনিকোড অক্ষরগুলি ম্যাপ করতে পারে (যদিও বর্তমানে 250 মাইলের অধীনে ম্যাপ করা আছে)।
- 8-বিট /
VARCHAR
ডেটা দিয়ে করা যায় এমন ম্যাপিংয়ের সীমিত সংখ্যার কারণে , অক্ষরের বিভিন্ন গোষ্ঠীকরণ (ভাষা / সংস্কৃতির উপর ভিত্তি করে) একাধিক "কোড পৃষ্ঠাগুলি" (অর্থাত অক্ষরের সেট) জুড়ে ছড়িয়ে পড়েছে
- প্রতিটি কোলিশন নির্দিষ্ট করে যে কোড পৃষ্ঠাটি, যদি কোনও হয় তবে
VARCHAR
ডেটার জন্য ব্যবহার করতে হবে ( NVARCHAR
সমস্ত অক্ষর রয়েছে)
- স্ট্রিংকে আক্ষরিক বা চলকটি
NVARCHAR
(যেমন ইউনিকোড / ইউটিএফ -১ 16 / সমস্ত অক্ষর) থেকে রূপান্তরিত করার সময় VARCHAR
(কোড পৃষ্ঠার উপর ভিত্তি করে অক্ষর সেট যা বেশিরভাগ কোলিশনে উল্লিখিত হয়), ডাটাবেসের ডিফল্ট কোলেশন ব্যবহৃত হয়
- রূপান্তরকরণের জন্য ব্যবহৃত কল্যাশনের কোড পৃষ্ঠাতে যদি একই চরিত্রটি না থাকে তবে এতে একটি "সেরা ফিট" ম্যাপিং থাকে তবে "সেরা ফিট" ম্যাপিংটি ব্যবহৃত হবে।
- রূপান্তরকরণের জন্য ব্যবহৃত কল্যাশনের কোড পৃষ্ঠাতে যদি একই চরিত্র না থাকে বা একটি "সেরা ফিট" ম্যাপিং থাকে না, তবে ডিফল্ট "প্রতিস্থাপন" অক্ষর ব্যবহার করা হবে (সর্বাধিক সাধারণভাবে
?
)।
সুতরাং, আপনি দেখতে পান একটি হল NVARCHAR
থেকে VARCHAR
হারিয়ে যাওয়ার কারণে রূপান্তর N
স্ট্রিং আক্ষরিক উপর উপসর্গ। এবং, ডেটাবেসের জন্য ডিফল্ট কোলিশনের কোড পৃষ্ঠাতে হুবহু একই চরিত্রটি থাকে না, তবে একটি "সেরা ফিট" ম্যাপিং পাওয়া গেছে, যার কারণে আপনি একটি এর 2
পরিবর্তে পাচ্ছেন ?
।
নিম্নলিখিত সাধারণ পরীক্ষা করে আপনি এই প্রভাবটি দেখতে পারেন:
SELECT '₂', N'₂';
রিটার্নস:
2 ₂
স্পষ্টতই, যদি ডেটাবেসের জন্য ডিফল্ট কোলিশনের কোড পৃষ্ঠাতে হুবহু একই চরিত্রটি উপস্থিত থাকে, তবে এটি সেই কোড পৃষ্ঠাতে একই অক্ষরটিতে অনুবাদিত হত। এবং, আপনার ক্ষেত্রে, যেহেতু আপনি একটি NVARCHAR
কলামে সংরক্ষণ করছেন , এটি আবার ইউনিকোডের মূল অক্ষরে অনুবাদ করে। নীচের চূড়ান্ত উদাহরণটি এই আচরণটি দেখায়।
গুরুত্বপূর্ণ: দয়া করে সচেতন হন যে স্ট্রিং আক্ষরিক ব্যাখ্যা করা হচ্ছে রূপান্তরটি ঘটে যা এটি কলামে সংরক্ষণের আগে before এর অর্থ হ'ল এমনকি কলামটি সেই অক্ষরটি ধরে রাখতে পারে, এটি ইতিমধ্যে ডেটাবেসের ডিফল্ট কলেশনের ভিত্তিতে, অন্য কিছুতে রূপান্তরিত হয়ে গেছে, সমস্ত কিছু N
সেই স্ট্রিং আক্ষরিকের উপসর্গটি ছেড়ে যাওয়ার কারণে । এবং এটি হ'ল আপনি যা যা করছেন (বা ছিলেন)।
উদাহরণস্বরূপ, যদি আপনার ডেটাবেসটির ডিফল্ট কোলিশন কোরিয়ান কোলিশনের একটি হয়ে ওঠে (চারটি ডাবল-বাইট চরিত্রের একটির মধ্যে একটি), তবে আপনি এই সমস্যাটি দেখতে পেতেন না কারণ "সাবস্ক্রিপ্ট 2" অক্ষরটি সেই অক্ষরটিতে উপলব্ধ would সেট (কোড পৃষ্ঠা 949)। নিম্নলিখিত পরীক্ষাটি দেখতে চেষ্টা করুন (এটি দেখানো আরও সহজ যেহেতু এটি ডেটাবেসের ডিফল্ট কলেশনের পরিবর্তে কলামের কোলেশন ব্যবহার করে):
CREATE TABLE #TestChar
(
[8bit_Latin1_General-1252] VARCHAR(2) COLLATE Latin1_General_100_CI_AS_SC,
[8bit_Korean-949] VARCHAR(2) COLLATE Korean_100_CI_AS_SC,
[UTF16LE_Latin1_General-1252] NVARCHAR(2) COLLATE Latin1_General_100_CI_AS_SC
);
INSERT INTO #TestChar VALUES (N'₂', N'₂', N'₂');
SELECT * FROM #TestChar;
রিটার্নস:
8bit_Latin1_General-1252 8bit_Korean-949 UTF16LE_Latin1_General-1252
2 ₂ ₂
আপনি দেখতে পাচ্ছেন যে ল্যাটিন 1_ জেনারেল কোলিশেশন, যা ডেটা কোডের জন্য কোড পৃষ্ঠা 1252 (একই কোড পৃষ্ঠাগুলি Modern_Spanish
ব্যবহার করে) ব্যবহার VARCHAR
করে, এর কোনও সঠিক মিল নেই, তবে তাদের একটি "সেরা ফিট" ম্যাপিং রয়েছে (যা আপনি দেখছেন )। বাট, কোরিয়ান কোলিশানগুলি, যা VARCHAR
ডেটার জন্য কোড পৃষ্ঠা 949 ব্যবহার করে, এর মধ্যে "সাবস্ক্রিপ্ট 2" চরিত্রের সাথে সঠিক মিল রয়েছে।
আরও চিত্রিত করার জন্য, আমরা কোরিয়ান কোলেশনগুলির মধ্যে একটির ডিফল্ট কোলেশন সহ একটি নতুন ডাটাবেস তৈরি করতে পারি এবং তারপরে প্রশ্নের মধ্যে থাকা সঠিক এসকিউএল চালাতে পারি:
CREATE DATABASE [TestKorean-949] COLLATE Korean_100_CI_AS_KS_WS_SC;
ALTER DATABASE [TestKorean-949] SET RECOVERY SIMPLE;
GO
USE [TestKorean-949];
CREATE TABLE test (
id INT NOT NULL,
description NVARCHAR(100) COLLATE Modern_Spanish_CI_AS NOT NULL
);
INSERT INTO test (id, description) VALUES (1, 'CO2');
SELECT * FROM test WHERE id = 1;
UPDATE test SET description = 'CO₂' WHERE id = 1;
SELECT * FROM test WHERE id = 1;
রিটার্নস:
id description
1 CO2
id description
1 CO₂
হালনাগাদ
যে কেউ এখানে ঠিক কী চলছে (সেগুলি সম্পর্কে উদঘাটিত সমস্ত বিবরণ) সম্পর্কে আরও সন্ধান করতে আগ্রহী , দয়া করে আমি সবে পোস্ট করা দ্বি-তদন্ত তদন্তটি দেখুন: