সারণি সারিতে "CO2" থেকে "CO₂" তে আপডেট করা যায় না


19

এই টেবিল দেওয়া:

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

(1 affected rows)

(1 affected rows)

id          description
----------- -----------
1           CO2

(1 affected rows)

এটি এসকিউএল সার্ভার নির্ধারণ করে যে, যেহেতু ly স্পষ্টত মাত্র একটি ক্ষুদ্র 2 , চূড়ান্ত মান পরিবর্তন হবে না তাই এটি পরিবর্তন করার উপযুক্ত নয়।

কেউ কি এ বিষয়ে কিছু আলোকপাত করতে পারে এবং সম্ভবত কোনও কাজের প্রস্তাব দিতে পারে (কোনও মধ্যস্থ মানের সাথে আপডেট করার পরিবর্তে)?


1
আলভারো: আপনি যদি এই আচরণ সম্পর্কে আরও জানতে চান তবে কেন এটি হচ্ছে তা আরও ভালভাবে বুঝতে, দয়া করে আমার উত্তরের নীচে আমি দুটি লিঙ্ক যুক্ত করেছি।
সলোমন রুটজকি

উত্তর:


29

সাবস্ক্রিপ্ট 2 বর্ণচরিত্রের অক্ষরের সেট নয় (কোনও জোটে, কেবল আধুনিক_পেনিশ নয়)। সুতরাং এটি একটি nvarchar ধ্রুবক করুন:

UPDATE test SET description = N'CO₂' WHERE id = 1;

1
আমি কেবল মানটি স্থির করেছি না, আমি বুঝতে পেরেছি যে এটি কীভাবে প্রথম স্থানে এসেছিল। ধন্যবাদ!
vlvaro González

2
@ VlvaroGonzález এবং gbn: স্পষ্ট করে বলার জন্য, "সাবস্ক্রিপ্ট 2" প্রশ্নযুক্ত ডেটাবেসের ডিফল্ট কল্যানেশন দ্বারা নির্দিষ্ট কোড পৃষ্ঠাতে পাওয়া যায় না, এটি স্ট্রিং লিটারেল এবং ভেরিয়েবলের জন্য ব্যবহৃত কোলেশন, কলামের সমষ্টি নয় (যদিও উভয়ই) একই কোড পৃষ্ঠা ব্যবহার করা যেতে পারে)। তবে, "সাবস্ক্রিপ্ট 2" কোরিয়ান কোলিশানগুলির মাধ্যমে কোড পৃষ্ঠা 949 এ উপলব্ধ। এটি এখানে সহায়তা করবে না, তবে কেবল FYI I আমার উত্তরে আমার কাছে বিশদ এবং উদাহরণ রয়েছে ।
সলোমন রুটজকি

21

@gbn ইতিমধ্যে মূল কারণ এবং সংশোধন ব্যাখ্যা করেছে, তবে আপনি যে আচরণটি দেখছেন তার সুনির্দিষ্ট কারণ হ'ল:

  1. আপনি VARCHARআক্ষরিক ( Nউপসর্গের NVARCHARসাথে স্ট্রিং ) পরিবর্তে আক্ষরিক (কোনও উপসর্গ নেই) ব্যবহার করছেন N, সুতরাং ইউনিকোড অক্ষর রূপান্তরিত হবে VARCHAR
  2. VARCHARএকটি 8-বিট এনকোডিং যা বেশিরভাগ ক্ষেত্রে চরিত্র অনুসারে একটি বাইট হয় তবে প্রতিটি চরিত্রে দুটি বাইটও হতে পারে। অন্যদিকে, NVARCHARএকটি 16-বিট এনকোডিং (ইউটিএফ -16 লিটল এন্ডিয়ান) যা চরিত্র অনুসারে দুটি বাইট বা চার বাইট হয়।
  3. ম্যাপিং অক্ষরের জন্য ব্যবহারযোগ্য উপলভ্য বাইটের সংখ্যার পার্থক্যের কারণে, 8 টি বিট এনকোডিংগুলি তাদের প্রকৃতি অনুসারে ম্যাপ করা যায় এমন অক্ষরের সংখ্যায় আরও সীমিত। VARCHARএকক-বাইট চরিত্রের সেটগুলি (তাদের বেশিরভাগের) জন্য 256 টি অক্ষর এবং ডাবল-বাইট চরিত্রের সেটগুলির জন্য 65,536 টি পর্যন্ত অক্ষর (এর মধ্যে কেবল কয়েকটি)। অন্যদিকে, NVARCHARডেটা কেবলমাত্র 1.1 মিলিয়ন ইউনিকোড অক্ষরগুলি ম্যাপ করতে পারে (যদিও বর্তমানে 250 মাইলের অধীনে ম্যাপ করা আছে)।
  4. 8-বিট / VARCHARডেটা দিয়ে করা যায় এমন ম্যাপিংয়ের সীমিত সংখ্যার কারণে , অক্ষরের বিভিন্ন গোষ্ঠীকরণ (ভাষা / সংস্কৃতির উপর ভিত্তি করে) একাধিক "কোড পৃষ্ঠাগুলি" (অর্থাত অক্ষরের সেট) জুড়ে ছড়িয়ে পড়েছে
  5. প্রতিটি কোলিশন নির্দিষ্ট করে যে কোড পৃষ্ঠাটি, যদি কোনও হয় তবে VARCHARডেটার জন্য ব্যবহার করতে হবে ( NVARCHARসমস্ত অক্ষর রয়েছে)
  6. স্ট্রিংকে আক্ষরিক বা চলকটি NVARCHAR(যেমন ইউনিকোড / ইউটিএফ -১ 16 / সমস্ত অক্ষর) থেকে রূপান্তরিত করার সময় VARCHAR(কোড পৃষ্ঠার উপর ভিত্তি করে অক্ষর সেট যা বেশিরভাগ কোলিশনে উল্লিখিত হয়), ডাটাবেসের ডিফল্ট কোলেশন ব্যবহৃত হয়
  7. রূপান্তরকরণের জন্য ব্যবহৃত কল্যাশনের কোড পৃষ্ঠাতে যদি একই চরিত্রটি না থাকে তবে এতে একটি "সেরা ফিট" ম্যাপিং থাকে তবে "সেরা ফিট" ম্যাপিংটি ব্যবহৃত হবে।
  8. রূপান্তরকরণের জন্য ব্যবহৃত কল্যাশনের কোড পৃষ্ঠাতে যদি একই চরিত্র না থাকে বা একটি "সেরা ফিট" ম্যাপিং থাকে না, তবে ডিফল্ট "প্রতিস্থাপন" অক্ষর ব্যবহার করা হবে (সর্বাধিক সাধারণভাবে ?)।

সুতরাং, আপনি দেখতে পান একটি হল 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₂

হালনাগাদ

যে কেউ এখানে ঠিক কী চলছে (সেগুলি সম্পর্কে উদঘাটিত সমস্ত বিবরণ) সম্পর্কে আরও সন্ধান করতে আগ্রহী , দয়া করে আমি সবে পোস্ট করা দ্বি-তদন্ত তদন্তটি দেখুন:

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.