যদি অন্য কোনও আপডেট না থাকে তবে অন্তর্ভুক্ত করুন?


275

আমি ক্লাসিকের জন্য কয়েকটি "সমাধান" পেয়েছি "আমি কীভাবে একটি নতুন রেকর্ড সন্নিবেশ করব বা এটি ইতিমধ্যে উপস্থিত থাকলে একটি আপডেট করব" তবে এসকিউএলাইটে কাজ করার জন্য আমি তাদের কোনওটিই পেতে পারি না।

আমার নীচের মতো একটি টেবিল সংজ্ঞায়িত হয়েছে:

CREATE TABLE Book 
ID     INTEGER PRIMARY KEY AUTOINCREMENT,
Name   VARCHAR(60) UNIQUE,
TypeID INTEGER,
Level  INTEGER,
Seen   INTEGER

আমি যা করতে চাই তা হল একটি অনন্য নামের সাথে একটি রেকর্ড যুক্ত করা। যদি নামটি ইতিমধ্যে বিদ্যমান থাকে তবে আমি ক্ষেত্রগুলি সংশোধন করতে চাই।

কেউ আমাকে কীভাবে এটি করতে দয়া করে বলতে পারেন?


3
"সন্নিবেশ করুন বা প্রতিস্থাপন করুন" "সন্নিবেশ বা আপডেট করুন" থেকে সম্পূর্ণ আলাদা
ফ্যাটি

উত্তর:


320

কটাক্ষপাত আছে http://sqlite.org/lang_conflict.html

আপনি যেমন কিছু চান:

insert or replace into Book (ID, Name, TypeID, Level, Seen) values
((select ID from Book where Name = "SearchName"), "SearchName", ...);

নোট করুন যে সারণি সারণীতে ইতিমধ্যে বিদ্যমান থাকলে সন্নিবেশ তালিকায় নেই এমন কোনও ক্ষেত্র NULL এ সেট করা হবে। এ কারণেই কলামটির জন্য সাব-সাবলেট আছে ID: প্রতিস্থাপনের ক্ষেত্রে বিবৃতিটি এটিকে NULL এ সেট করে এবং তারপরে একটি নতুন আইডি বরাদ্দ করা হবে।

যদি প্রতিস্থাপনের ক্ষেত্রে সারিটি নির্দিষ্ট ক্ষেত্রের মানগুলি একা রেখে দিতে চান তবে ক্ষেত্রটি সন্নিবেশ ক্ষেত্রে NULL এ সেট করতে চান তবে এই পদ্ধতির ব্যবহারও করা যেতে পারে।

উদাহরণস্বরূপ, ধরে নিই যে আপনি Seenএকা চলে যেতে চান :

insert or replace into Book (ID, Name, TypeID, Level, Seen) values (
   (select ID from Book where Name = "SearchName"),
   "SearchName",
    5,
    6,
    (select Seen from Book where Name = "SearchName"));

109
ভুল "সন্নিবেশ করুন বা প্রতিস্থাপন করুন" "সন্নিবেশ বা আপডেট করুন" এর চেয়ে আলাদা। একটি বৈধ উত্তর জন্য, দেখুন stackoverflow.com/questions/418898/...
RDS

12
@ আরডিএস না, এটি ভুল নয় কারণ এই প্রশ্নটি "ক্ষেত্রগুলি সংশোধন করুন" এবং প্রাথমিক কীটি কলাম তালিকার অংশ নয়, তবে অন্যান্য ক্ষেত্রগুলির সমস্ত। আপনি যদি ক্ষেত্রের সমস্ত মানকে প্রতিস্থাপন করছেন না এমন কোণার কেসগুলি করতে চলেছেন বা আপনি যদি প্রাথমিক কী দিয়ে গোলমাল করছেন তবে আপনার কিছু আলাদা করা উচিত। আপনার যদি নতুন ক্ষেত্রগুলির একটি সম্পূর্ণ সেট থাকে তবে এই পদ্ধতিটি ঠিক আছে। আপনার কি কোনও নির্দিষ্ট সমস্যা আছে যা আমি দেখতে পাচ্ছি না?
জানম

9
আপনি যদি সমস্ত ক্ষেত্রের জন্য সমস্ত নতুন মান জানেন তা এটি বৈধ। ব্যবহারকারী কেবল আপডেট হলে, বলুন Level, এই পদ্ধতির অনুসরণ করা যাবে না।
আরডিএস

4
সঠিক । অন্য উত্তরটি প্রাসঙ্গিক, তবে এই পদ্ধতিটি সমস্ত ক্ষেত্র আপডেট করার জন্য বৈধ (কী বাদে)।
Ярослав Рахматуллин

2
হ্যাঁ এটি সম্পূর্ণ ভুল। কেবলমাত্র যদি আমি নতুন থেকে দ্বন্দ্বের উপর একক কলাম মান আপডেট করতে চাই তবে কী হবে। উপরের ক্ষেত্রে অন্যান্য সমস্ত ডেটা নতুন দ্বারা প্রতিস্থাপন করা হবে যা সঠিক নয়।
মৃগ

85

INSERT OR IGNOREকমান্ডটি অনুসরণ করে আপনার কমান্ডটি ব্যবহার করা উচিত UPDATE: নিম্নলিখিত উদাহরণে nameএকটি প্রাথমিক কী রয়েছে:

INSERT OR IGNORE INTO my_table (name, age) VALUES ('Karen', 34)
UPDATE my_table SET age = 34 WHERE name='Karen'

প্রথম কমান্ড রেকর্ড সন্নিবেশ করবে। যদি রেকর্ডটি বিদ্যমান থাকে তবে এটি বিদ্যমান প্রাথমিক কীটির সাথে দ্বন্দ্বের কারণে সৃষ্ট ত্রুটিটিকে উপেক্ষা করবে।

দ্বিতীয় কমান্ড রেকর্ডটি আপডেট করবে (যা এখন অবশ্যই উপস্থিত রয়েছে)


6
কোন মুহুর্তে তা উপেক্ষা করবে? নাম এবং বয়স উভয় যখন এক হয়?
mou

এটি সমাধান হওয়া উচিত ... আপনি যদি সন্নিবেশতে কোনও ট্রিগার ব্যবহার করেন তবে গৃহীত উত্তরটি প্রতিবারই জ্বলজ্বল করে। এটি করে না এবং কেবল আপডেটটি করে
পডটেক.ইও

1
এটি কেবল নামের ভিত্তিতে উপেক্ষা করে। মনে রাখবেন যে কেবলমাত্র "নাম" কলামটি একটি প্রাথমিক কী।
গ্যাব্রিয়েল ফেরার

3
যখন রেকর্ডটি নতুন হয়, তখন আপডেটটি প্রয়োজনীয় হয় না তবে যেভাবেই সম্পাদন করা হবে যা খারাপ পারফরম্যান্সের দিকে পরিচালিত করবে?
মার্জজি

কিভাবে এই জন্য একটি প্রস্তুত বিবৃতি কার্যকর?
প্রশান্ত

65

" দ্বন্দ্ব " ট্রিগার করতে আপনাকে টেবিলে একটি সীমাবদ্ধতা তৈরি করতে হবে যা আপনি তারপরে প্রতিস্থাপনের মাধ্যমে সমাধান করুন:

CREATE TABLE data   (id INTEGER PRIMARY KEY, event_id INTEGER, track_id INTEGER, value REAL);
CREATE UNIQUE INDEX data_idx ON data(event_id, track_id);

তারপরে আপনি ইস্যু করতে পারেন:

INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 2, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 5);

"নির্বাচন থেকে তথ্য নির্বাচন করুন" আপনাকে দেবে:

2|2|2|3.0
3|1|2|5.0

নোট করুন যে ডেটা.আইডটি "3" এবং "1" নয় কারণ প্রতিস্থাপন একটি আপডেট এবং ডিলিট করে না, আপডেট করে না। এর অর্থ হ'ল এটি আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনি সমস্ত প্রয়োজনীয় কলামগুলি সংজ্ঞায়িত করেছেন বা আপনি অপ্রত্যাশিত নাল মান পাবেন।


33

প্রথমে এটি আপডেট করুন। যদি সারি গণনা = 0 প্রভাবিত হয় তবে এটি প্রবেশ করান। এটি সমস্ত আরডিবিএমএসের জন্য সবচেয়ে সহজ এবং উপযুক্ত ।


11
ডাটাবেস নির্বিশেষে সঠিক বিচ্ছিন্নতা স্তরে লেনদেনের ক্ষেত্রে দুটি ক্রিয়াকলাপের কোনও সমস্যা হওয়া উচিত নয়।
জানম

5
Insert or Replaceসত্যিই আরও ভাল।
এমপিলেটিয়ার

1
আমি সত্যিই আইটি ডকুমেন্টেশনের আরও উদাহরণ থাকতে পারে তা চাই। আমি এটি নীচে চেষ্টা করেছি এবং এটি কাজ করে না (আমার বাক্য গঠনটি অবশ্যই ভুল)। এটি হওয়া উচিত কোন ধারণা? অন্তর্ভুক্ত বইয়ের নাম (নাম, টাইপআইডি, স্তর, দেখেছে) ভ্যালু ('সুপারম্যান', '2', '14', '0') কনফ্লিক রিপ্লেস বইয়ের (নাম, টাইপআইডি, স্তর, দেখেছে) ভ্যালু ('সুপারম্যান', ' 2 ',' 14 ',' 0 ')
স্পারকিএনজেড

6
এছাড়াও যদি সারি মানগুলি হুবহু একই হয় তবে প্রভাবিত সারি গণনা শূন্য হবে এবং একটি নতুন সদৃশ সারি তৈরি হবে।
বার্কসাইড

2
+1 টি কারণ ঢোকান বা প্রতিস্থাপন সংঘাত মূল সারি মুছে ফেলবে এবং যদি আপনি সব কলাম সেটিং করা হয় না, আপনি মূল মান নষ্ট হয়ে যাবে
পাভেল Machyniak

20

INSERT OR REPLACE অন্যান্য ক্ষেত্রগুলি ডিফল্ট মানকে প্রতিস্থাপন করবে।

sqlite> CREATE TABLE Book (
  ID     INTEGER PRIMARY KEY AUTOINCREMENT,
  Name   TEXT,
  TypeID INTEGER,
  Level  INTEGER,
  Seen   INTEGER
);

sqlite> INSERT INTO Book VALUES (1001, 'C++', 10, 10, 0);
sqlite> SELECT * FROM Book;
1001|C++|10|10|0

sqlite> INSERT OR REPLACE INTO Book(ID, Name) VALUES(1001, 'SQLite');

sqlite> SELECT * FROM Book;
1001|SQLite|||

আপনি যদি অন্য ক্ষেত্র সংরক্ষণ করতে চান

sqlite> SELECT * FROM Book;
1001|C++|10|10|0

sqlite> INSERT OR IGNORE INTO Book(ID) VALUES(1001);
sqlite> UPDATE Book SET Name='SQLite' WHERE ID=1001;

sqlite> SELECT * FROM Book;
1001|SQLite|10|10|0

বা ইউপিএসআরটি ব্যবহার করে (সংস্করণটি এসকিউএলাইটে সংস্করণ 3.24.0 (2018-06-04) সহ যুক্ত হয়েছিল)

INSERT INTO Book (ID, Name)
  VALUES (1001, 'SQLite')
  ON CONFLICT (ID) DO
  UPDATE SET Name=excluded.Name;

excluded.Prefix মধ্যে মান সমান VALUES


16

Upsert আপনি যা চান তা নয়। UPSERT3.24.0 সংস্করণ (2018-06-04) সহ এসকিউএলাইটে সিনট্যাক্স যুক্ত হয়েছিল।

CREATE TABLE phonebook2(
  name TEXT PRIMARY KEY,
  phonenumber TEXT,
  validDate DATE
);

INSERT INTO phonebook2(name,phonenumber,validDate)
  VALUES('Alice','704-555-1212','2018-05-08')
  ON CONFLICT(name) DO UPDATE SET
    phonenumber=excluded.phonenumber,
    validDate=excluded.validDate
  WHERE excluded.validDate>phonebook2.validDate;

সতর্কতা অবলম্বন করুন যে এই মুহুর্তে আসল শব্দ "ইউপিএসআরটি" উপস্থাপনা বাক্য গঠনের অংশ নয়।

সঠিক বাক্য গঠন

INSERT INTO ... ON CONFLICT(...) DO UPDATE SET...

এবং যদি আপনি INSERT INTO SELECT ...অন্তত WHERE trueটোকেন সম্পর্কে পার্সার অস্পষ্টতা সমাধান করার জন্য আপনার নির্বাচিত প্রয়োজনগুলি করেনON সিনট্যাক্সের সাথে ।

সতর্কতা অবলম্বন করুন যে INSERT OR REPLACE...কোনও নতুন প্রতিস্থাপন করতে গেলে এটি সন্নিবেশ করার আগে রেকর্ডটি মুছে ফেলবে, যা আপনার কাছে বিদেশী কী ক্যাসকেড বা অন্য মুছে ফেলার ট্রিগার থাকলে খারাপ হতে পারে।


এটি ডকুমেন্টেশনে বিদ্যমান এবং আমার কাছে স্ক্লাইটের সর্বশেষতম সংস্করণ রয়েছে যা 3.25.1 কিন্তু এটি আমার পক্ষে কাজ করে না
বেন্টাইবা মেল করা বাসমা

আপনি কি ভারব্যাটিমের উপরে এই দুটি প্রশ্নের চেষ্টা করেছেন?
কমরেডজাইকুল

মনে রাখবেন যে উবুন্টু 18.04 এসকিউএল 3 v3.22 এর সাথে আসে , 3.25 নয়, সুতরাং এটি UPSERTসিনট্যাক্স সমর্থন করে না ।
স্টারবিয়াম্রেনবোলাবস

বৈশিষ্ট্যে রেফারেন্স সংস্করণের জন্য ধন্যবাদ!
ম্যাটিও

6

আপনার যদি কোনও প্রাথমিক কী না থাকে তবে আপনি উপস্থিত না থাকলে sertোকাতে পারেন, তবে একটি আপডেট করুন। এটি ব্যবহারের আগে সারণীতে কমপক্ষে একটি প্রবেশ থাকতে হবে।

INSERT INTO Test 
   (id, name)
   SELECT 
      101 as id, 
      'Bob' as name
   FROM Test
       WHERE NOT EXISTS(SELECT * FROM Test WHERE id = 101 and name = 'Bob') LIMIT 1;

Update Test SET id='101' WHERE name='Bob';

এটিই একমাত্র সমাধান যা ডুপ্লিকেট এন্ট্রি না তৈরি করে আমার পক্ষে কাজ করেছিল। সম্ভবত যেহেতু আমি যে টেবিলটি ব্যবহার করছি তার কোনও প্রাথমিক কী নেই এবং এতে কোনও কলামের কোনও ডিফল্ট মান নেই। যদিও এটি একটি দীর্ঘ সমাধান কিছুটা হলেও এটি কাজটি সঠিকভাবে করে এবং প্রত্যাশার মতো কাজ করে।
ইনবার রোজ

4

আমি বিশ্বাস করি আপনি ইউপিএসআরটি চান

উত্তরের অতিরিক্ত কৌশল ছাড়া "" লিখুন বা প্রতিস্থাপন করুন "আপনি যে ক্ষেত্রগুলি NULL বা অন্যান্য ডিফল্ট মান নির্দিষ্ট করে না তা পুনরায় সেট করবে। (INSERT or REPLACE এর এই আচরণটি আপডেটের মতো নয়; এটি হ'ল INSERT এর মতো, কারণ এটি আসলে INSERT; তবে আপনি যা চেয়েছিলেন তা যদি আপডেট-ই-উপস্থিত থাকে তবে আপনি সম্ভবত আপডেটের শব্দার্থবিজ্ঞান চান এবং প্রকৃত ফলাফল দ্বারা বিস্মিত হয়ে অবাক হবেন।)

প্রস্তাবিত ইউপিএসআরটি বাস্তবায়নের কৌশলটি মূলত INSERT বা REPLACE ব্যবহার করা হয় তবে আপনি যে ক্ষেত্রগুলি পরিবর্তন করতে চান না তার বর্তমান মান পুনরুদ্ধার করতে এম্বেড করা SELECT ধারাগুলি ব্যবহার করে সমস্ত ক্ষেত্র নির্দিষ্ট করে।


1

আমি মনে করি এটি উল্লেখ করা মূল্যবান যে আপনি এখানে কী কীভাবে প্রাথমিক কী এবং অনন্য বিষয়টি পুরোপুরি বুঝতে না পারলে কিছু অপ্রত্যাশিত আচরণ হতে পারে ।

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

আপনাকে বরখাস্ত করবার বৈধ বাধ্যতা ব্যতিক্রম চান, আপনি একটি ব্যবহার করতে হবে ঢোকান বিবৃতি এবং একটি পৃথক উপর নির্ভর আপডেট কমান্ড রেকর্ড আপডেট করার জন্য একবার আপনি জানেন নাম নেওয়া হয়।

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