সিটিইতে সারি সারিগুলি কেন একই বিবৃতিতে আপডেট করা যায় না?


13

PostgreSQL 9.5 এ, এর সাথে তৈরি করা একটি সাধারণ টেবিল দেওয়া হয়েছে:

create table tbl (
    id serial primary key,
    val integer
);

আমি এসকিউএল একটি মান লিখুন, তারপর একই বিবৃতিতে এটি আপডেট করুন:

WITH newval AS (
    INSERT INTO tbl(val) VALUES (1) RETURNING id
) UPDATE tbl SET val=2 FROM newval WHERE tbl.id=newval.id;

ফলস্বরূপ যে আপডেটটি উপেক্ষা করা হয়:

testdb=> select * from tbl;
┌────┬─────┐
 id  val 
├────┼─────┤
  1    1 
└────┴─────┘

কেন? এই সীমাবদ্ধতাটি কি এসকিউএল স্ট্যান্ডার্ডের (যেমন অন্যান্য ডাটাবেসে উপস্থিত), বা পোস্টগ্র্রেএসকিউএল এর সাথে নির্দিষ্ট কিছু যা ভবিষ্যতে ঠিক করা যেতে পারে? সঙ্গে প্রশ্নের ডকুমেন্টেশন বলছেন একাধিক আপডেট সমর্থিত নয়, কিন্তু টিপে এবং আপডেট উল্লেখ নেই।

উত্তর:


15

সিটিইতে সমস্ত বিবৃতি একই সাথে কার্যত ঘটে happen অর্থাৎ, তারা ডাটাবেসের একই স্ন্যাপশটের উপর ভিত্তি করে।

UPDATEযেমন অন্তর্নিহিত টেবিলের একই রাষ্ট্র দেখেন INSERTযা দিয়ে সারি মানে val = 1নেই, এখনো। ম্যানুয়ালটি এখানে স্পষ্ট করে:

সমস্ত বিবৃতি একই স্ন্যাপশটের সাথে কার্যকর করা হয় ( অধ্যায় 13 দেখুন ), সুতরাং তারা লক্ষ্য টেবিলগুলিতে একে অপরের প্রভাব "দেখতে" পারে না।

প্রতিটি বিবৃতি করতে দেখুন সেখানে কি অন্য কোটে দ্বারা ফিরে গেছে RETURNINGদফা। তবে অন্তর্নিহিত সারণীগুলি তাদের কাছে সমস্ত একই দেখাচ্ছে।

আপনি যা করার চেষ্টা করছেন তার জন্য আপনার দুটি বিবৃতি (একক লেনদেনে) প্রয়োজন হবে। প্রদত্ত উদাহরণটি INSERTশুরুতে কেবল একক হওয়া উচিত , তবে এটি সরল উদাহরণের কারণে হতে পারে।


15

এটি বাস্তবায়নের সিদ্ধান্ত। এটি পোস্টগ্রিস ডকুমেন্টেশন, WITHক্যোরিজ (সাধারণ টেবিল এক্সপ্রেশন) -এ বর্ণনা করা হয়েছে । বিষয়টি সম্পর্কিত দুটি অনুচ্ছেদ রয়েছে are

প্রথমত, পর্যবেক্ষণ আচরণের কারণ:

এর উপ-বিবৃতিগুলিWITH একে অপরের সাথে এবং মূল ক্যোয়ারির সাথে একযোগে কার্যকর করা হয় । সুতরাং, ডেটা-সংশোধনকারী বিবৃতিগুলিতে ব্যবহার WITHকরার সময়, নির্দিষ্ট আপডেটগুলি আসলে যে ক্রমে ঘটে তা অনাকাঙ্ক্ষিত। সমস্ত বিবৃতি একই স্ন্যাপশট দিয়ে চালিত হয় (অধ্যায় 13 দেখুন), তাই তারা লক্ষ্য সারণিতে একে অপরের প্রভাব "দেখতে" পারে না। এটি সারি আপডেটগুলির আসল ক্রমের অনিশ্চয়তার প্রভাবগুলি হ্রাস করে এবং এর অর্থ হ'ল RETURNINGডেটা হ'ল বিভিন্ন WITHউপ-বিবৃতি এবং মূল ক্যোয়ারির মধ্যে পরিবর্তনগুলি যোগাযোগ করার একমাত্র উপায় । এর উদাহরণ হ'ল ...

আমি পিগএসকিএল-ডক্সের সাথে একটি পরামর্শ পোস্ট করার পরে , মার্কো তিক্কাজা ব্যাখ্যা করেছিলেন (যা এরউইনের উত্তরের সাথে একমত):

সন্নিবেশ-আপডেট এবং সন্নিবেশ-মোছার কেসগুলি কার্যকর হয় না কারণ আপডেটগুলি এবং মোছার ক্ষেত্রে INSERT হওয়ার আগে স্ন্যাপশট নেওয়া হওয়ার কারণে INSERTed সারিগুলি দেখার কোনও উপায় নেই। এই দুটি মামলা নিয়ে অপ্রত্যাশিত কিছুই নেই।

সুতরাং আপনার বিবৃতিটি আপডেট না হওয়ার কারণটি উপরের প্রথম অনুচ্ছেদে (প্রায় "স্ন্যাপশট") দ্বারা ব্যাখ্যা করা যেতে পারে। আপনি যখন সিটিইগুলিকে সংশোধন করবেন তখন যা ঘটে তা হ'ল এগুলি এবং মূল ক্যোয়ারী কার্যকর করা হয় এবং ডেটা (টেবিল) এর একই স্ন্যাপশটটি "দেখুন", যেমন তারা বিবৃতি কার্যকর করার আগেই ছিল। সিটিইগুলি ক্লোজটি ব্যবহার করে তারা কীভাবে একে অপরকে সন্নিবেশিত / আপডেট / মুছে ফেলা হয়েছে তার তথ্য পাস করতে পারে RETURNINGতবে তারা টেবিলের পরিবর্তনগুলি সরাসরি দেখতে পাবে না। সুতরাং আসুন আপনার বিবৃতিতে কী ঘটে তা দেখতে দিন:

WITH newval AS (
    INSERT INTO tbl(val) VALUES (1) RETURNING id
) UPDATE tbl SET val=2 FROM newval WHERE tbl.id=newval.id;

আমাদের দুটি অংশ রয়েছে, সিটিই ( newval):

-- newval
     INSERT INTO tbl(val) VALUES (1) RETURNING id

এবং মূল প্রশ্ন:

-- main 
UPDATE tbl SET val=2 FROM newval WHERE tbl.id=newval.id

মৃত্যুদন্ড কার্যকর করার প্রবাহ এইরকম:

           initial data: tbl
                id  val 
                 (empty)
               /         \
              /           \
             /             \
    newval:                 \
       tbl (after newval)    \
           id  val           \
            1    1           |
                              |
    newval: returns           |
           id                 |
            1                 |
               \              |
                \             |
                 \            |
                    main query

ফলস্বরূপ, যখন প্রধান ক্যোয়ারী টেবিলের tblসাথে (স্ন্যাপশটে দেখা যায়) newvalযোগদান করে, এটি একটি 1-সারির টেবিলের সাথে খালি টেবিলে যোগ দেয়। স্পষ্টতই এটি 0 টি সারি আপডেট করে। সুতরাং বিবৃতিটি আসলে কখনই সন্নিবেশ করা সারিটি সংশোধন করতে আসেনি এবং এটিই আপনি দেখছেন।

আপনার ক্ষেত্রে সমাধানটি হ'ল হয় প্রথমে সঠিক মানগুলি সন্নিবেশ করানোর জন্য বিবৃতিটি পুনর্লিখন করা বা 2 টি স্টেটমেন্ট ব্যবহার করা। একটি যা সন্নিবেশ করায় এবং দ্বিতীয়টি আপডেট করতে।


অন্যান্য, অনুরূপ পরিস্থিতি রয়েছে, যেমন যদি বিবৃতিটির একই সারিগুলিতে একটি INSERTএবং তারপরে একটি DELETEথাকে। মুছে ফেলা ঠিক একই কারণে ব্যর্থ হবে।

আপডেট-আপডেট এবং আপডেট-ডিলিট সহ আরও কয়েকটি মামলা এবং তাদের আচরণ একই ডক্স পৃষ্ঠায় নিম্নলিখিত অনুচ্ছেদে বর্ণিত হয়েছে।

একক বিবৃতিতে একই সারিতে দুবার আপডেট করার চেষ্টা করা সমর্থনযোগ্য নয়। কেবলমাত্র একটি পরিবর্তন ঘটেছে, তবে কোনটি নির্ভরযোগ্যভাবে পূর্বাভাস দেওয়া সহজ (এবং কখনও কখনও সম্ভব নয়)। এটি একই বিবৃতিতে ইতিমধ্যে আপডেট হওয়া একটি সারি মুছে ফেলার ক্ষেত্রেও প্রযোজ্য: কেবলমাত্র আপডেটটি সম্পাদিত হয়। অতএব আপনার একক বিবৃতিতে সাধারণত একবারে একটি সারিতে সংশোধন করার চেষ্টা করা এড়ানো উচিত। বিশেষত উপ-বিবৃতিগুলি লিখে এড়িয়ে চলুন যা মূল বক্তব্য বা ভাইবোন সাব-স্টেটমেন্ট দ্বারা পরিবর্তিত একই সারিগুলিকে প্রভাবিত করতে পারে। এই জাতীয় বক্তব্যের প্রভাবগুলি অনুমানযোগ্য হবে না।

এবং মার্কো টিইককাজার উত্তরে:

আপডেটের-আপডেট এবং আপডেট-Delete ক্ষেত্রে স্পষ্টভাবে হয় না একই অন্তর্নিহিত বাস্তবায়ন বিস্তারিত (সন্নিবেশ-আপডেট এবং সন্নিবেশ-Delete ক্ষেত্রে হিসাবে) দ্বারা সৃষ্ট।
আপডেট-আপডেটের মামলাটি কার্যকর হয় না কারণ এটি অভ্যন্তরীণভাবে হ্যালোইন সমস্যার মতো দেখায় এবং পোস্টগ্রিসের জানার কোনও উপায় নেই যে কোন টিপলগুলি দু'বার আপডেট করা ঠিক হবে এবং কোনটি হ্যালোইন সমস্যার পুনঃপ্রবর্তন করতে পারে।

সুতরাং কারণটি একই (সিটিই কীভাবে পরিবর্তন করা হয় এবং প্রতিটি সিটিই একই স্ন্যাপশটটি কীভাবে দেখায়) তবে বিবরণগুলি এই 2 টি ক্ষেত্রে পৃথক, কারণ এটি আরও জটিল এবং ফলাফল আপডেট-আপডেটের ক্ষেত্রে অনাকাঙ্ক্ষিত হতে পারে।

সন্নিবেশ-আপডেটে (আপনার ক্ষেত্রে হিসাবে) এবং অনুরূপ সন্নিবেশ-মুছলে ফলাফল অনুমানযোগ্য। সদ্য সন্নিবেশ করা সারিগুলি দেখার এবং প্রভাবিত করার জন্য দ্বিতীয় ক্রিয়াকলাপের (আপডেট বা মুছুন) কোনও উপায় না থাকায় কেবল সন্নিবেশ ঘটে।


প্রস্তাবিত সমাধানটি সকল ক্ষেত্রে একইরূপে একই পাতাগুলিকে একাধিকবার সংশোধন করার চেষ্টা করে: এটি করবেন না। হয় বিবৃতি লিখুন যা প্রতিটি সারি একবারে সংশোধন করে অথবা পৃথক (2 বা আরও) বিবৃতি ব্যবহার করে।

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