পোস্টগ্র্রেএসকিউএলে সারি বিদ্যমান কিনা তা দ্রুততম পরীক্ষা করুন


177

আমার কাছে টেবিলের মধ্যে সারি সন্নিবেশ করা দরকার এমন একটি সারির গুচ্ছ রয়েছে তবে এই সন্নিবেশগুলি সর্বদা ব্যাচগুলিতে করা হয়। সুতরাং আমি ব্যাচ থেকে কোনও একক সারিটি টেবিলে উপস্থিত আছে কিনা তা খতিয়ে দেখতে চাই কারণ তখন আমি জানি তারা সমস্ত allোকানো হয়েছিল।

সুতরাং এটি প্রাথমিক কী চেক নয়, তবে খুব বেশি কিছু হওয়া উচিত নয়। আমি কেবল একটি একক সারি পরীক্ষা করতে চাই তাই count(*)সম্ভবত এটি ভাল নয়, সুতরাং এটি existsঅনুমান করার মতো কিছু ।

তবে যেহেতু আমি পোস্টগ্রিসকিউএল-এ মোটামুটি নতুন, আমি বরং তাদের পরিচিত লোকদের জিজ্ঞাসা করব।

আমার ব্যাচে নিম্নলিখিত কাঠামোর সাথে সারি রয়েছে:

userid | rightid | remaining_count

সুতরাং যদি টেবিলটিতে প্রদত্ত কোনও সারি থাকে তবে এর useridঅর্থ হ'ল তারা সমস্ত সেখানে উপস্থিত রয়েছে।


আপনি দেখতে চান যে টেবিলটিতে কোনও সারি রয়েছে বা আপনার ব্যাচ থেকে কোনও সারি রয়েছে?
জেএনকে

হ্যাঁ আমার ব্যাচ থেকে কোনও সারি। তারা সকলেই অল্প সম্পাদনা করে একই ক্ষেত্র ভাগ করে নেয়।
ভ্যালেন্টাইন কুজুব

আপনার প্রশ্নটি পরিষ্কার করুন। আপনি রেকর্ডের একটি ব্যাচ যুক্ত করতে চান, সব কিছু না? গণনা সম্পর্কে কি বিশেষ কিছু আছে? (বিটিডব্লিউ একটি সংরক্ষিত শব্দ, কলামের নাম হিসাবে
অবর্ণনীয়

ঠিক আছে, আমি বাস্তব পরিস্থিতিটি কিছুটা সহজ করার চেষ্টা করছিলাম তবে আমরা বাস্তব বাস্তবায়নের আরও কাছাকাছি এবং কাছাকাছি চলেছি। এই সারিগুলি sertedোকানো হয়ে গেলে (for_date এর জন্য অন্য ক্ষেত্র রয়েছে) নির্দিষ্ট ব্যবহারকারীদের নির্দিষ্ট অধিকারগুলি ব্যবহার করার সাথে সাথে আমি অধিকার ব্যবহারকারীর হ্রাস শুরু করি, একবার অধিকার 0 হয়ে গেলে তারা সেই তারিখের জন্য আর সেই ক্রিয়া সম্পাদন করতে পারে না। আসল গল্পটি শুরু করে
ভ্যালেন্টাইন কুজুব

1
সারণির সংজ্ঞাগুলি কেবল (এর প্রাসঙ্গিক অংশ) দেখান এবং আপনি কী করতে চান তা জানান।
ওয়াইল্ডপ্লাজার

উত্তর:


345

সত্য / মিথ্যা ফেরতের জন্য বিদ্যমান কী শব্দটি ব্যবহার করুন:

select exists(select 1 from contact where id=12)

21
এটিতে প্রসারিত, আপনি সহজ রেফারেন্সের জন্য ফিরে আসা কলামটির নাম রাখতে পারেন। উদাselect exists(select 1 from contact where id=12) AS "exists"
রোয়ান

3
এটি আরও ভাল, কারণ এটি সর্বদা কখনও কখনও কোনওটির পরিবর্তে কোনও মান (সত্য বা মিথ্যা) ফিরিয়ে দেবে (আপনার প্রোগ্রামিং ভাষার উপর নির্ভর করে) যা আপনার প্রত্যাশার উপায়টিকে প্রসারিত করতে পারে না।
isaaclw

1
এই পদ্ধতিটি ব্যবহার করে আমার সিক স্ক্যান রয়েছে। আমি কিছু ভুল করি?
ফিফটিএন

2
@ মাইকেল.এমআই এর কাছে 30 মিলিয়ন সারি সহ ডিবি টেবিল রয়েছে এবং আমি যখন ব্যবহার করি existsবা limit 1আমার দৃ strong় পারফরম্যান্স ড্রপ হয় কারণ পোস্টগ্র্যাস ইনডেক্স স্ক্যানের পরিবর্তে সিক স্ক্যান ব্যবহার করে। এবং analyzeসাহায্য করে না।
ফিফটিএন

2
@ ম্যাসিক দয়া করে বুঝতে পারেন যে 'আইডি' একটি প্রাথমিক কী, সুতরাং "লিমিটেড 1" অর্থহীন হবে যেহেতু এই
আইডিটির

34

কীভাবে সহজভাবে:

select 1 from tbl where userid = 123 limit 1;

কোথায় 123আপনি যে ব্যাচের সন্নিবেশ করতে চলেছেন তার ইউজারিড ?

প্রদত্ত ইউজারিডের সাথে রেকর্ড রয়েছে কিনা তার উপর নির্ভর করে উপরের জিজ্ঞাসাটি খালি সেট বা একটি একক সারিতে ফিরে আসবে।

যদি এটি খুব ধীর হয়ে যায় তবে আপনি সূচি তৈরির দিকে নজর রাখতে পারেন tbl.userid

এমনকি যদি ব্যাচ থেকে একক সারিও টেবিলের মধ্যে উপস্থিত থাকে তবে সেক্ষেত্রে আমাকে আমার সারিগুলি toোকাতে হবে না কারণ আমি নিশ্চিতভাবে জানি যে সেগুলি সমস্ত .োকানো হয়েছিল।

এটি ঠিক থাকার জন্য এমনকি যদি আপনার প্রোগ্রামটি মিড ব্যাচটি বাধাগ্রস্ত হয় তবে আমি আপনাকে সুপারিশ করব যে আপনি ডাটাবেস লেনদেনগুলি যথাযথভাবে পরিচালনা করেছেন (যেমন পুরো ব্যাচটি একটি লেনদেনের মধ্যে sertedোকানো হবে))


11
কখনও কখনও 0 বা 1 এর গণনা (*) এর মান দিয়ে একটি সারিতে সর্বদা ফেরত দেওয়ার গ্যারান্টিযুক্ত হিসাবে "(1 নির্বাচন করুন ... 1 টি সীমা) থেকে গণনা (*) বাছাই করা প্রোগ্রামগতভাবে সহজ হতে পারে
ডেভিড অলড্রিজ

@ ডেভিডএলড্রিজ গণনা (*) এর অর্থ এখনও রয়েছে যে সমস্ত সারি পড়তে হবে, যেখানে প্রথম রেকর্ডে সীমা 1 থামবে এবং ফিরে আসবে
ইমরান

3
@ ইমরান আমি মনে করি আপনি কোয়েরিটি ভুল ব্যাখ্যা করেছেন। COUNTএকটি নেস্টেড উপর কাজ করে SELECT(কারণ সর্বাধিক 1 টি সারি আছে LIMITsubquery হয়)।
jpmc26

9
INSERT INTO target( userid, rightid, count )
  SELECT userid, rightid, count 
  FROM batch
  WHERE NOT EXISTS (
    SELECT * FROM target t2, batch b2
    WHERE t2.userid = b2.userid
    -- ... other keyfields ...
    )       
    ;

বিটিডাব্লু: আপনি যদি চান নকলের ক্ষেত্রে পুরো ব্যাচটি ব্যর্থ হয়, তবে (প্রাথমিক কী বাধা দেওয়া হয়েছে)

INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count 
FROM batch
    ;

আপনি যা চান ঠিক তা করবে: হয় তা সফল হয়, অথবা এটি ব্যর্থ হয়।


এটি প্রতিটি সারি পরীক্ষা করবে। তিনি একটি চেক করতে চান।
জেএনকে

1
না, এটি একটি চেক করে। সাবকোরিটি অসম্পৃক্ত। একবার একটি ম্যাচিং জুটি পাওয়া গেলে এটি জামিন হয়ে যায়।
ওয়াইল্ডপ্লাজার

ঠিক আপনিই, আমি ভেবেছিলাম এটি বাহ্যিক ক্যোয়ারী উল্লেখ করেছে। আপনার কাছে +1
জেএনকে

বিটিডাব্লু: যেহেতু ক্যোয়ারী একটি লেনদেনের ভিতরে রয়েছে তাই কোনও সদৃশ আইডি wereোকানো থাকলে কিছুই ঘটবে না, সুতরাং সাবকিউরিটি বাদ দেওয়া যেতে পারে।
ওয়াইল্ডপ্লাজার

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

1
select true from tablename where condition limit 1;

আমি বিশ্বাস করি যে এটি বিদেশী কীগুলি পরীক্ষার জন্য পোস্টগ্রাগেস ব্যবহার করে query

আপনার ক্ষেত্রে, আপনি এক বারে এটি করতে পারেন:

insert into yourtable select $userid, $rightid, $count where not (select true from yourtable where userid = $userid limit 1);

1

@ মাইকেম হিসাবে চিহ্নিত।

select exists(select 1 from contact where id=12)

যোগাযোগের সূচক সহ , এটি সাধারণত সময় ব্যয় হ্রাস করে 1 এমএস করতে পারে।

CREATE INDEX index_contact on contact(id);

0
SELECT 1 FROM user_right where userid = ? LIMIT 1

যদি আপনার রেজাল্টটিতে একটি সারি থাকে তবে আপনাকে প্রবেশ করতে হবে না। অন্যথায় আপনার রেকর্ড সন্নিবেশ করুন।


গুচ্ছ যদি 100 টি সারি থাকে তবে তা আমাকে 100 সারি ফিরিয়ে দেবে, আপনি কি মনে করেন ভাল?
ভ্যালেন্টাইন কুজুব

আপনি এটি 1 সারিতে সীমাবদ্ধ করতে পারেন। আরও ভাল পারফরম্যান্স করা উচিত। এর জন্য @ অ্যাক্সের সম্পাদিত উত্তরটি দেখুন।
ফ্যাবিয়ান বার্নি

0

যদি আপনি পারফরম্যান্স সম্পর্কে ভাবেন, তবে আপনি সম্ভবত কোনও ফাংশনে "পারফর্ম" ব্যবহার করতে পারেন:

 PERFORM 1 FROM skytf.test_2 WHERE id=i LIMIT 1;
  IF FOUND THEN
      RAISE NOTICE ' found record id=%', i;  
  ELSE
      RAISE NOTICE ' not found record id=%', i;  
 END IF;

আমার সাথে কাজ করে না: আমি পারফর্ম করার কাছাকাছি একটি সিনট্যাক্স ত্রুটি পেয়েছি
সাইমন

1
এটি pl / pgsql, এসকিউএল নয়, অতএব "পারফর্ম" এর সিনট্যাক্স ত্রুটিটি যদি এটি এসকিউএল হিসাবে চালানোর চেষ্টা করে
মার্ক কে কোয়ান

-1

আমি আপনার বাক্যটি বিশেষভাবে সম্বোধন করার জন্য আরেকটি চিন্তার প্রস্তাব দিতে চাই: "সুতরাং আমি ব্যাচ থেকে কোনও একক সারিটি টেবিলে উপস্থিত আছে কিনা তা খতিয়ে দেখতে চাই কারণ আমি জানি যে তারা সমস্ত all োকানো হয়েছিল ।"

আপনি "ব্যাচ" সন্নিবেশ করিয়ে জিনিসগুলিকে দক্ষ করে তুলছেন কিন্তু তারপরে অস্তিত্ব একবারে একটি করে রেকর্ড চেক করেন? এটি আমার কাছে স্বতঃস্ফূর্ত মনে হয়। সুতরাং আপনি যখন বলেন " সন্নিবেশগুলি সর্বদা ব্যাচগুলিতে করা হয় " আমি এটি গ্রহণ করি আপনার অর্থ আপনি একটি সন্নিবেশ বিবৃতি দিয়ে একাধিক রেকর্ড সন্নিবেশ করছেন । আপনার বুঝতে হবে যে পোস্টগ্র্রেসগুলি এসিডি অনুগত। আপনি যদি একটি সন্নিবেশ বিবৃতি সহ একাধিক রেকর্ড (ডেটা ব্যাচ) সন্নিবেশ করিয়ে থাকেন তবে কিছু sertedোকানো হয়েছে কি না তা খতিয়ে দেখার দরকার নেই। বিবৃতিটি হয় পাস হয় অথবা এটি ব্যর্থ হবে। সমস্ত রেকর্ড সন্নিবেশ করা হবে বা কিছুই হবে না।

অন্যদিকে, যদি আপনার সি # কোডটি কেবল একটি "সেট" পৃথক সন্নিবেশ বিবৃতিগুলি করছে, উদাহরণস্বরূপ, একটি লুপে এবং আপনার মনে এটি একটি "ব্যাচ" .. তবে আপনার আসলে এটিকে "" হিসাবে বর্ণনা করা উচিত নয় সন্নিবেশগুলি সর্বদা ব্যাচগুলিতে করা হয় "। আপনি যেটিকে "ব্যাচ" বলছেন তার যে অংশটি আপনি প্রত্যাশা করেছেন তা বাস্তবে beোকানো যাবে না এবং তাই একটি চেকের প্রয়োজনীয়তা অনুভব করে, দৃ strongly়ভাবে প্রস্তাব দেয় এটিই এই ক্ষেত্রে, যার ক্ষেত্রে আপনার আরও মৌলিক সমস্যা রয়েছে। একটি sertোকানো সহ একাধিক রেকর্ড সন্নিবেশ করানোর জন্য আপনার দৃষ্টান্ত পরিবর্তন করতে হবে এবং স্বতন্ত্র রেকর্ডগুলি এটি তৈরি করেছে কিনা তা পরীক্ষা করতে হবে।

এই উদাহরণ বিবেচনা করুন:

CREATE TABLE temp_test (
    id SERIAL PRIMARY KEY,
    sometext TEXT,
    userid INT,
    somethingtomakeitfail INT unique
)
-- insert a batch of 3 rows
;;
INSERT INTO temp_test (sometext, userid, somethingtomakeitfail) VALUES
('foo', 1, 1),
('bar', 2, 2),
('baz', 3, 3)
;;
-- inspect the data of what we inserted
SELECT * FROM temp_test
;;
-- this entire statement will fail .. no need to check which one made it
INSERT INTO temp_test (sometext, userid, somethingtomakeitfail) VALUES
('foo', 2, 4),
('bar', 2, 5),
('baz', 3, 3)  -- <<--(deliberately simulate a failure)
;;
-- check it ... everything is the same from the last successful insert ..
-- no need to check which records from the 2nd insert may have made it in
SELECT * FROM temp_test

এটি আসলে যে কোনও এসআইডি কমপ্লায়েন্ট ডিবির জন্য দৃষ্টান্ত .. কেবল পোস্টগ্র্যাস্কল নয়। অন্য কথায় আপনি যদি আপনার "ব্যাচ" ধারণাটি স্থির করেন এবং প্রথম স্থানে সারি চেক করে কোনও সারি করা থেকে বিরত থাকেন তবে আপনি আরও ভাল।

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