সরল INSERT
INSERT INTO bar (description, foo_id)
SELECT val.description, f.id
FROM (
VALUES
(text 'testing', text 'blue') -- explicit type declaration; see below
, ('another row', 'red' )
, ('new row1' , 'purple') -- purple does not exist in foo, yet
, ('new row2' , 'purple')
) val (description, type)
LEFT JOIN foo f USING (type);
LEFT [OUTER] JOINপরিবর্তে এর ব্যবহারের [INNER] JOINঅর্থ val হ'ল কোনও মিল পাওয়া না গেলে সারিগুলি সরিয়ে ফেলা হয় নাfoo । পরিবর্তে, NULLজন্য প্রবেশ করানো হয় foo_id।
VALUESSubquery মধ্যে অভিব্যক্তি হিসাবে একই আছে @ ypercube এর কোটে। সাধারণ সারণী এক্সপ্রেশন অতিরিক্ত বৈশিষ্ট্যগুলি সরবরাহ করে এবং বড় প্রশ্নগুলিতে পড়া সহজ, তবে সেগুলি অপ্টিমাইজেশন বাধা হিসাবেও ডাকে। সুতরাং উপরেরগুলির কোনও প্রয়োজন না হলে সাবকুইরিগুলি সাধারণত কিছুটা দ্রুত হয়।
idকলামের নামটি হ'ল বিস্তৃত ছড়িয়ে পড়া বিরোধী-নিদর্শন। foo_idএবং bar_idবর্ণনামূলক কিছু হতে হবে । একগুচ্ছ টেবিলগুলিতে যোগদান করার সময়, আপনি নামযুক্ত একাধিক কলাম দিয়ে শেষ করবেন id...
সরল textবা এর varcharপরিবর্তে বিবেচনা করুন varchar(n)। আপনার যদি সত্যিই দৈর্ঘ্যের সীমাবদ্ধতা আরোপ করতে হয় তবে একটি CHECKসীমাবদ্ধতা যুক্ত করুন:
আপনার স্পষ্টত ধরণের ক্যাসেট যুক্ত করার প্রয়োজন হতে পারে। যেহেতু VALUESঅভিব্যক্তিটি কোনও টেবিলের সাথে সরাসরি সংযুক্ত থাকে না ( INSERT ... VALUES ...প্রকারের মতো ), প্রকারগুলি উত্পন্ন করা যায় না এবং স্পষ্টত ধরণের ঘোষণা ছাড়াই ডিফল্ট ডেটা টাইপ ব্যবহৃত হয়, যা সব ক্ষেত্রেই কাজ না করে। এটি প্রথম সারিতে করা যথেষ্ট, বাকিগুলি লাইনে পড়বে।
একই সময়ে এফকে সারি নিখোঁজ করুন
আপনি যদি fooএকটি একক এসকিউএল স্টেটমেন্টে ফ্লাইতে অ-অস্তিত্বপ্রাপ্ত এন্ট্রিগুলি তৈরি করতে চান তবে সিটিই হ'ল সহায়ক
WITH sel AS (
SELECT val.description, val.type, f.id AS foo_id
FROM (
VALUES
(text 'testing', text 'blue')
, ('another row', 'red' )
, ('new row1' , 'purple')
, ('new row2' , 'purple')
) val (description, type)
LEFT JOIN foo f USING (type)
)
, ins AS (
INSERT INTO foo (type)
SELECT DISTINCT type FROM sel WHERE foo_id IS NULL
RETURNING id AS foo_id, type
)
INSERT INTO bar (description, foo_id)
SELECT sel.description, COALESCE(sel.foo_id, ins.foo_id)
FROM sel
LEFT JOIN ins USING (type);
সন্নিবেশ করানোর জন্য দুটি নতুন ডামি সারি নোট করুন। দুটিই বেগুনি , যা fooএখনও নেই। প্রথম বিবৃতিতে প্রয়োজনীয়তা বর্ণনা করার জন্য দুটি সারি ।DISTINCTINSERT
ধাপে ধাপে ব্যাখ্যা
1 ম সিটিই selইনপুট ডেটারের বহুগুণ সারি সরবরাহ করে। Subquery valসঙ্গে VALUESঅভিব্যক্তি উৎস হিসেবে একটি টেবিল বা subquery সঙ্গে প্রতিস্থাপিত হতে পারে। অবিলম্বে LEFT JOINকরার জন্য fooসংযোজন করতে foo_idজন্য পূর্ব বিদ্যমান typeসারি। অন্যান্য সমস্ত সারি foo_id IS NULLএইভাবে পায়।
২ য় সিটিই স্বতন্ত্র নতুন প্রকারগুলি ( ) insসন্নিবেশ করায় এবং সদ্য উত্পন্ন উত্সাহ দেয় - একসাথে সারি সন্নিবেশ করানোর জন্য যোগ দেয়।foo_id IS NULLfoofoo_idtype
চূড়ান্ত INSERTবাহিরটি এখন প্রতিটি সারির জন্য একটি foo.id সন্নিবেশ করতে পারে: টাইপটি প্রাক-বিদ্যমান, অথবা এটি পদক্ষেপ 2 এ সন্নিবেশ করা হয়েছিল।
কড়া কথায় বলতে গেলে উভয় সন্নিবেশ "সমান্তরালভাবে" ঘটে, তবে এটি যেহেতু এটি একক বিবৃতি, তাই ডিফল্ট FOREIGN KEYসীমাবদ্ধতাগুলি অভিযোগ করবে না। ডিফল্টরূপে বিবৃতি শেষে রেফারেন্সিয়াল অখণ্ডতা প্রয়োগ করা হয়।
পোস্টগ্রিসের জন্য এসকিউএল ফিডল 9.3। (9.1 এ একই কাজ করে।)
আপনি যদি এই কোয়েরিতে একসাথে একাধিক চালনা করেন তবে একটি ক্ষুদ্র জাতির শর্ত রয়েছে । এখানে এবং এখানে এবং এখানে সম্পর্কিত প্রশ্নের অধীনে আরও পড়ুন । সত্যিই কেবল কখনও ভারী সমবর্তী লোডের অধীনে ঘটে। অন্য উত্তরে বিজ্ঞাপন দেওয়ার মতো ক্যাশিং সমাধানগুলির তুলনায়, সুযোগটি অতি ক্ষুদ্র ।
বারবার ব্যবহারের জন্য ফাংশন
বারবার ব্যবহারের জন্য আমি একটি এসকিউএল ফাংশন তৈরি করব যা প্যারামিটার হিসাবে রেকর্ডগুলির একটি অ্যারে নেয় এবং এক্সপ্রেশনটির unnest(param)জায়গায় ব্যবহার VALUESকরে।
অথবা, যদি রেকর্ডগুলির অ্যারেগুলির সিনট্যাক্স আপনার পক্ষে খুব অগোছালো হয় তবে পরামিতি হিসাবে কমা-বিচ্ছিন্ন স্ট্রিংটি ব্যবহার করুন _param। ফর্ম উদাহরণস্বরূপ:
'description1,type1;description2,type2;description3,type3'
তারপরে VALUESউপরের বিবৃতিতে ভাবটি প্রতিস্থাপন করতে এটি ব্যবহার করুন :
SELECT split_part(x, ',', 1) AS description
split_part(x, ',', 2) AS type
FROM unnest(string_to_array(_param, ';')) x;
পোস্টগ্রিস 9.5 এ ইউপিএসআরটির সাথে ফাংশন
প্যারামিটার পাস করার জন্য একটি কাস্টম সারি প্রকার তৈরি করুন। আমরা এটি না করেই করতে পারি, তবে এটি সহজ:
CREATE TYPE foobar AS (description text, type text);
ফাংশন:
CREATE OR REPLACE FUNCTION f_insert_foobar(VARIADIC _val foobar[])
RETURNS void AS
$func$
WITH val AS (SELECT * FROM unnest(_val)) -- well-known row type
, ins AS (
INSERT INTO foo AS f (type)
SELECT DISTINCT v.type -- DISTINCT!
FROM val v
ON CONFLICT(type) DO UPDATE -- type already exists
SET type = excluded.type WHERE FALSE -- never executed, but lock rows
RETURNING f.type, f.id
)
INSERT INTO bar AS b (description, foo_id)
SELECT v.description, COALESCE(f.id, i.id) -- assuming most types pre-exist
FROM val v
LEFT JOIN foo f USING (type) -- already existed
LEFT JOIN ins i USING (type) -- newly inserted
ON CONFLICT (description) DO UPDATE -- description already exists
SET foo_id = excluded.foo_id -- real UPSERT this time
WHERE b.foo_id IS DISTINCT FROM excluded.foo_id -- only if actually changed
$func$ LANGUAGE sql;
কল করুন:
SELECT f_insert_foobar(
'(testing,blue)'
, '(another row,red)'
, '(new row1,purple)'
, '(new row2,purple)'
, '("with,comma",green)' -- added to demonstrate row syntax
);
একযোগে লেনদেন সহ পরিবেশের জন্য দ্রুত এবং রক-সলিড।
উপরের প্রশ্নগুলি ছাড়াও, এটি ...
... প্রযোজ্য SELECTবা INSERTচালু foo: typeএফকে টেবিলের মধ্যে বিদ্যমান না এমন যে কোনও এখনও .োকানো হয়। ধরে নিচ্ছি বেশিরভাগ ধরণের প্রাক-অস্তিত্ব রয়েছে। একেবারে নিশ্চিত হয়ে ও বর্ণের পরিস্থিতি বাতিল করার জন্য, আমাদের বিদ্যমান বিদ্যমান সারিগুলি লক করা আছে (যাতে সমবর্তী লেনদেন হস্তক্ষেপ করতে না পারে)। যদি এটি আপনার ক্ষেত্রে খুব অসতর্ক থাকে তবে আপনি প্রতিস্থাপন করতে পারেন:
ON CONFLICT(type) DO UPDATE -- type already exists
SET type = excluded.type WHERE FALSE -- never executed, but lock rows
সঙ্গে
ON CONFLICT(type) DO NOTHING
... প্রযোজ্য INSERTবা UPDATE(সত্য "ইউপিএসআরটি") চালু bar: descriptionইতিমধ্যে বিদ্যমান থাকলে typeএটি আপডেট হয়:
ON CONFLICT (description) DO UPDATE -- description already exists
SET foo_id = excluded.foo_id -- real UPSERT this time
WHERE b.foo_id IS DISTINCT FROM excluded.foo_id -- only if actually changed
তবে শুধুমাত্র যদি typeআসলে পরিবর্তন হয়:
... একটি VARIADICপ্যারামিটার সহ মান হিসাবে পরিচিত সারি প্রকারগুলি পাস করে । সর্বোচ্চ 100 পরামিতি নোট করুন! তুলনা করা:
একাধিক সারি পাস করার আরও অনেক উপায় আছে ...
সম্পর্কিত: