অন ​​কনফ্লিক্ট শৃঙ্খলে একাধিক দ্বন্দ্ব_মার্জ ব্যবহার করুন


101

আমি টেবিলে দুটি কলাম আছে col1, col2তারা উভয় অনন্য সূচীবদ্ধ (col1 অনন্য এবং তাই col2 যায়)।

আমার এই টেবিলটিতে atোকানো দরকার, ON CONFLICTসিনট্যাক্স ব্যবহার করুন এবং অন্যান্য কলামগুলি আপডেট করুন তবে আমি উভয় কলামটি conflict_targetধারাতে ব্যবহার করতে পারি না ।

এটি কাজ করে:

INSERT INTO table
...
ON CONFLICT ( col1 ) 
DO UPDATE 
SET 
-- update needed columns here

তবে বেশ কয়েকটি কলামের জন্য কীভাবে এটি করবেন, এরকম কিছু:

...
ON CONFLICT ( col1, col2 )
DO UPDATE 
SET 
....

4
"কল 1, কল 2, তারা উভয়ই অনন্য সূচকযুক্ত" " এর অর্থ কি কল 1 টি অনন্য এবং কল 2 টি অনন্য বা কোল 1, কোল 2 এর সংমিশ্রণগুলি কি অনন্য?
e4c5

4
তার মানে কি এই যে কোল 1 টি স্বতন্ত্র এবং কল 2 স্বতন্ত্রভাবে
ওটো শ্যাভাদজে

উত্তর:


49

একটি নমুনা টেবিল এবং ডেটা

CREATE TABLE dupes(col1 int primary key, col2 int, col3 text,
   CONSTRAINT col2_unique UNIQUE (col2)
);

INSERT INTO dupes values(1,1,'a'),(2,2,'b');

সমস্যা পুনরুত্পাদন

INSERT INTO dupes values(3,2,'c')
ON CONFLICT (col1) DO UPDATE SET col3 = 'c', col2 = 2

এই কিউ 1 কল করুন। ফলাফল হলো

ERROR:  duplicate key value violates unique constraint "col2_unique"
DETAIL:  Key (col2)=(2) already exists.

ডকুমেন্টেশন কি বলে

দ্বন্দ্ব_তারজিটি অনন্য সূচি অনুমান করতে পারে। অনুমান সম্পাদন করার সময়, এটিতে এক বা একাধিক সূচি_ কলাম_নাম কলাম এবং / অথবা সূচক_প্রকাশ এক্সপ্রেশন এবং একটি alচ্ছিক সূচক_প্রকাশ থাকে। অর্ডার বিবেচনা না করে, সমস্ত সারণী-নাম অনন্য সূচীগুলিতে ঠিক দ্বন্দ্ব_তার্গেট-নির্দিষ্ট কলাম / এক্সপ্রেশন থাকে সালিস সূচক হিসাবে অনুমান করা (নির্বাচিত)। যদি একটি সূচক_প্রেডিকেট নির্দিষ্ট করা থাকে তবে এটি অবশ্যই অনুমানের প্রয়োজন হিসাবে আরবিটার সূচকগুলি সন্তুষ্ট করতে হবে।

এটি এই ধারণাটি দেয় যে নিম্নলিখিত কোয়েরিতে কাজ করা উচিত, তবে এটি হ'ল না কারণ এটির জন্য আসলে কল 1 এবং কল 2 এ একসাথে অনন্য সূচক প্রয়োজন। তবে এই জাতীয় সূচক গ্যারান্টি দেয় না যে কল 1 এবং কল 2 স্বতন্ত্রভাবে অনন্য হবে যা অপের প্রয়োজনীয়তার একটি।

INSERT INTO dupes values(3,2,'c') 
ON CONFLICT (col1,col2) DO UPDATE SET col3 = 'c', col2 = 2

আসুন এই ক্যোয়ারী Q2 কল করুন (এটি একটি সিনট্যাক্স ত্রুটির সাথে ব্যর্থ হয়)

কেন?

পোস্টগ্র্যাস্কলটি এইভাবে আচরণ করে কারণ দ্বিতীয় কলামে যখন কোনও বিরোধ দেখা দেয় তখন কী হওয়া উচিত তা সঠিকভাবে সংজ্ঞায়িত হয় না। সম্ভাবনার সংখ্যা রয়েছে। উদাহরণস্বরূপ উপরের Q1 ক্যোয়ারিতে, col1কোনও বিরোধ চলাকালীন পোস্টগ্রেসকিএল আপডেট করা উচিত col2? কিন্তু যদি তা অন্য বিরোধের দিকে পরিচালিত করে তবে কী হবে col1? পোস্টগ্র্যাস্কেল কীভাবে এটি পরিচালনা করবে?

একটি সমাধান

একটি সমাধানটি পুরানো ফ্যাশনযুক্ত ইউপিএসআরটির সাথে কনফ্লিক্টকে একত্রিত করা ।

CREATE OR REPLACE FUNCTION merge_db(key1 INT, key2 INT, data TEXT) RETURNS VOID AS
$$
BEGIN
    LOOP
        -- first try to update the key
        UPDATE dupes SET col3 = data WHERE col1 = key1 and col2 = key2;
        IF found THEN
            RETURN;
        END IF;

        -- not there, so try to insert the key
        -- if someone else inserts the same key concurrently, or key2
        -- already exists in col2,
        -- we could get a unique-key failure
        BEGIN
            INSERT INTO dupes VALUES (key1, key2, data) ON CONFLICT (col1) DO UPDATE SET col3 = data;
            RETURN;
        EXCEPTION WHEN unique_violation THEN
            BEGIN
                INSERT INTO dupes VALUES (key1, key2, data) ON CONFLICT (col2) DO UPDATE SET col3 = data;
                RETURN;
            EXCEPTION WHEN unique_violation THEN
                -- Do nothing, and loop to try the UPDATE again.
            END;
        END;
    END LOOP;
END;
$$
LANGUAGE plpgsql;

আপনার এই সঞ্চিত ফাংশনের যুক্তিটি সংশোধন করতে হবে যাতে এটি কলামগুলি ঠিক যেভাবে চান তা আপডেট করে। এটি পছন্দ করুন

SELECT merge_db(3,2,'c');
SELECT merge_db(1,2,'d');

4
এটি এইভাবে কাজ করে তবে প্রয়োজনের তুলনায় আরও কিছুটা কাজ / যুক্তি, আপনাকে যা করতে হবে তা হ'ল দুটি কলামে একটি অনন্য প্রতিবন্ধকতা তৈরি করা। আমার উত্তর নীচে দেখুন।
যুবায়ের

আমি যদি একবারে একাধিক ভ্যালু'স সেট amুকিয়ে দিই তবে আমি কী মার্জ_ডাব সমাধানটি ব্যবহার করতে পারি?
দানিয়েল

@ ডানিয়েল আপনাকে সঞ্চিত ফাংশনটি আবার লিখতে হবে
e4c5

4
এটি আমার কাছে অস্পষ্ট যে এটি কীভাবে পুরানো ফ্যাশনযুক্ত উপস্থাপনাটি ব্যবহার করার পরামর্শ দেয় - এই প্রশ্নটি "পোস্টগ্র্যাস আপ্রেট 9.5" এর জন্য ভালভাবে উল্লেখ করা হয়েছে এবং এটি সমস্ত বাধা_নাম বিকল্পগুলির সাথে কীভাবে এটি ব্যবহার করবেন তা ব্যাখ্যা করে আরও ভাল হতে পারে।
পাক

4
@ পাক এটি আপনার কাছে অস্পষ্ট কারণ আপনি প্রশ্নটি পরিষ্কারভাবে পড়েন নি। বিকল্পগুলি সেই ক্ষেত্রগুলিতে কোনও সংমিশ্রিত কীটির সন্ধান করছে না। অন্য উত্তরটি যৌগিক কীগুলির জন্য কাজ করে
e4c5

66

ON CONFLICTদ্বন্দ্ব সনাক্তকরণের জন্য একটি অনন্য সূচক প্রয়োজন। সুতরাং আপনার উভয় কলামে একটি অনন্য সূচক তৈরি করতে হবে:

t=# create table t (id integer, a text, b text);
CREATE TABLE
t=# create unique index idx_t_id_a on t (id, a);
CREATE INDEX
t=# insert into t values (1, 'a', 'foo');
INSERT 0 1
t=# insert into t values (1, 'a', 'bar') on conflict (id, a) do update set b = 'bar';
INSERT 0 1
t=# select * from t;
 id | a |  b  
----+---+-----
  1 | a | bar

* অনন্য সূচক ছাড়াও, আপনি বর্জনীয় বাধাও ব্যবহার করতে পারেন । এগুলি অনন্য বাধার চেয়ে কিছুটা সাধারণ। ধরুন আপনার টেবিলটিতে idএবং valid_time(এবং valid_timeএটি ক tsrange) এর জন্য কলাম রয়েছে এবং আপনি সদৃশ idটির অনুমতি দিতে চেয়েছিলেন তবে ওভারল্যাপিং সময়ের জন্য নয়। একটি অনন্য প্রতিবন্ধকতা আপনাকে সাহায্য করবে না, তবে একটি বর্জনীয় বাধা দিয়ে আপনি বলতে পারবেন "নতুন রেকর্ডগুলি বাদ দিন যদি idসেগুলির পুরানো সমান হয় idএবং valid_timeসেগুলির ওভারল্যাপ হয় valid_time" "


4
এটি যা তৈরি করে তা হ'ল একসাথে অনন্য সূচক তৈরি করুন অনন্য সূচক তৈরি করুন আইডিএক্স_টি_আইডি_এ টি (আইডি, এ); অবশ্যই দুটি কলাম স্বতন্ত্রভাবে বা একসাথে অনন্য কিনা তা ওপি স্পষ্টভাবে জানায় না।
e4c5

পোস্টগ্রিস কেন কখনও কখনও বলে যে সূচকের নাম অনুসারে কোনও কলাম নেই এবং ব্যবহারে ব্যর্থ হয় ON CONFLICT?
পাক

@ পাক মনে হচ্ছে আপনার নিজের নির্দিষ্ট প্রশ্নটি আপনার ব্যবহার করা নির্দিষ্ট কমান্ড এবং আপনি প্রাপ্ত ত্রুটি বার্তা দিয়ে লিখতে হবে।
পল এ জংউথर्थ

@ পোল্যাজংথ্রিথ আমি জানি না, আপনার উত্তরটি দাগী - on conflictকমান্ডের সীমাবদ্ধতা হিসাবে একটি অনন্য সূচক । ত্রুটিটি কেবলমাত্র "কলামের আমার_আইডেক্স_নামের অস্তিত্ব নেই"।
পাক

ওপি জিজ্ঞাসা করার সাথে সাথে আমি প্রতিটি কলামে পৃথক অনন্য বাধা দিয়ে এটিকে চেষ্টা করেছিলাম, এবং এটি কার্যকর হয়নি। আমি এটি প্রত্যাশা করি না তা নয়, তবে আমি আশা করছিলাম।
sudo

6

আজকাল অসম্ভব (মনে হয়) অসম্ভব। ON CONFLICT সিনট্যাক্সের সর্বশেষ সংস্করণটিও এই ধারাটির পুনরাবৃত্তি করার অনুমতি দেয় না, বা সিটিই দিয়েও সম্ভব নয়: আরও সংঘাত-টার্গেট যুক্ত করতে অন কনফ্লিক্ট থেকে ইনসার্টটি ভঙ্গ করা সম্ভব নয়।


4

আপনি যদি 9.5 পোস্টগ্রেস ব্যবহার করে থাকেন তবে আপনি এক্সক্লুড স্পেস ব্যবহার করতে পারেন।

পোস্টগ্র্যাস এসকিউএল 9.5-এ নতুন কী থেকে নেওয়া উদাহরণ :

INSERT INTO user_logins (username, logins)
VALUES ('Naomi',1),('James',1)
ON CONFLICT (username)
DO UPDATE SET logins = user_logins.logins + EXCLUDED.logins;

2
  1. সীমাবদ্ধতা তৈরি করুন (উদাহরণস্বরূপ বিদেশী সূচক)।

অথবা এবং

  1. বিদ্যমান সীমাবদ্ধতাগুলি দেখুন (পিএসএকে q d)
  2. INSERT ধারাটিতে কনসার্ট (সীমাবদ্ধ_নাম) ব্যবহার করুন।

2

ভ্লাদ সঠিক ধারণা পেয়েছে।

প্রথমে আপনাকে কলামগুলিতে একটি টেবিলের অনন্য সীমাবদ্ধতা তৈরি col1, col2 করতে হবে তারপরে একবার আপনি এটি করতে পারলে নীচের কাজগুলি করতে পারেন:

INSERT INTO dupes values(3,2,'c') 
ON CONFLICT ON CONSTRAINT dupes_pkey 
DO UPDATE SET col3 = 'c', col2 = 2

5
দুঃখিত তবে আপনি প্রশ্নটি ভুল বুঝে গেছেন। ওপি একসাথে অনন্য বাধা চায় না।
e4c5

1

হ্যাকির মতো তবে আমি সমাধান করেছি কোল 1 এবং কোল 2 থেকে দুটি নতুন মানকে একটি নতুন কলাম, কল 3 (উভয়ের সূচকের মতো) হিসাবে সংযুক্ত করে এবং এর বিপরীতে তুলনা করে। এটি কেবল তখনই কাজ করে যখন আপনার কাছে দুটি কোল 1 এবং কল 2 এর সাথে মেলে।

INSERT INTO table
...
ON CONFLICT ( col3 ) 
DO UPDATE 
SET 
-- update needed columns here

যেখানে কল 3 = কোল 1 এবং কল 2 থেকে মানগুলির সংমিশ্রণ।


4
আপনি এই দুটি কলামের জন্য একটি অনন্য সূচক তৈরি করতে পারেন এবং সেই সীমাবদ্ধতাটি দিতে পারেন on conflict
কিশোর রেলেঙ্গি

0

আপনি সাধারণত (আমি মনে করি) কেবলমাত্র একটির সাথে একটি বিবৃতি উত্পন্ন করতে পারি on conflictযা আপনার সন্নিবেশ করানো জিনিসটির জন্য প্রাসঙ্গিকতার জন্য একমাত্র এবং কেবলমাত্র বাধা নির্দিষ্ট করে।

কারণ সাধারণত, কেবল একবারে "প্রাসঙ্গিক" একমাত্র প্রতিবন্ধকতা। (যদি অনেকগুলি থাকে তবে আমি ভাবছি যে কোনও কিছু অদ্ভুত / অদ্ভুতভাবে ডিজাইন করা হয়েছে, হুম।)

উদাহরণ:
(লাইসেন্স: সিসি 0 নয় , কেবল সিসি-বাই)

// there're these unique constraints:
//   unique (site_id, people_id, page_id)
//   unique (site_id, people_id, pages_in_whole_site)
//   unique (site_id, people_id, pages_in_category_id)
// and only *one* of page-id, category-id, whole-site-true/false
// can be specified. So only one constraint is "active", at a time.

val thingColumnName = thingColumnName(notfificationPreference)

val insertStatement = s"""
  insert into page_notf_prefs (
    site_id,
    people_id,
    notf_level,
    page_id,
    pages_in_whole_site,
    pages_in_category_id)
  values (?, ?, ?, ?, ?, ?)
  -- There can be only one on-conflict clause.
  on conflict (site_id, people_id, $thingColumnName)   <—— look
  do update set
    notf_level = excluded.notf_level
  """

val values = List(
  siteId.asAnyRef,
  notfPref.peopleId.asAnyRef,
  notfPref.notfLevel.toInt.asAnyRef,
  // Only one of these is non-null:
  notfPref.pageId.orNullVarchar,
  if (notfPref.wholeSite) true.asAnyRef else NullBoolean,
  notfPref.pagesInCategoryId.orNullInt)

runUpdateSingleRow(insertStatement, values)

এবং:

private def thingColumnName(notfPref: PageNotfPref): String =
  if (notfPref.pageId.isDefined)
    "page_id"
  else if (notfPref.pagesInCategoryId.isDefined)
    "pages_in_category_id"
  else if (notfPref.wholeSite)
    "pages_in_whole_site"
  else
    die("TyE2ABK057")

on conflictআমি কী করার চেষ্টা করছি তার উপর নির্ভর করে এই ধারাটি গতিশীলভাবে উত্পন্ন হয়েছে। যদি আমি কোনও পৃষ্ঠার জন্য কোনও বিজ্ঞপ্তি পছন্দ সন্নিবেশ করিয়ে দিই - তবে site_id, people_id, page_idসীমাবদ্ধতায় অনন্য সংঘাত হতে পারে । এবং যদি আমি কোনও বিভাগের জন্য বিজ্ঞপ্তি প্রিফগুলি কনফিগার করছি - তবে এর পরিবর্তে আমি জানি যে সীমাবদ্ধতা লঙ্ঘিত হতে পারে, তা site_id, people_id, category_id

সুতরাং আমিও, এবং আপনার ক্ষেত্রেও সম্ভবত আমি খুব সম্ভব, সঠিক উত্পাদন করতে on conflict (... columns )পারি, কারণ আমি জানি যে আমি কী করতে চাই এবং তারপরে আমি জানি যে অনেকগুলি অনন্য বাধার মধ্যে কোনটিই লঙ্ঘিত হতে পারে।


-4

কনফ্লিক্ট খুব আনাড়ি সমাধান, চালানো

UPDATE dupes SET key1=$1, key2=$2 where key3=$3    
if rowcount > 0    
  INSERT dupes (key1, key2, key3) values ($1,$2,$3);

ওরাকল, পোস্টগ্রিস এবং অন্যান্য সমস্ত ডাটাবেসে কাজ করে


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