মাইএসকিউএল সাবকিউরিতে সমস্যা


16

কেন এই কোয়েরি

DELETE FROM test 
WHERE id = ( SELECT id 
             FROM (SELECT * FROM test) temp 
             ORDER BY RAND() 
             LIMIT 1
           );

কখনও 1 সারি, কখনও কখনও 2 সারি এবং কখনও কখনও কিছুই মুছবেন?

আমি যদি এই ফর্মটিতে এটি লিখি:

SET @var = ( SELECT id 
             FROM (SELECT * FROM test) temp 
             ORDER BY RAND() 
             LIMIT 1
           ); 
DELETE FROM test 
WHERE id=@var;

তাহলে এটি সঠিকভাবে কাজ করে - উপকোয়ায় সমস্যা আছে?

উত্তর:


13

প্রথম জিজ্ঞাসাটি যেভাবে অবিচ্ছিন্নভাবে কাজ করে না তার সাথে মাইএসকিউএল সাবকিউরিয়াসগুলি কীভাবে প্রক্রিয়া করে তা জড়িত। প্রকৃতপক্ষে, subqueries পুনর্লিখন এবং রূপান্তর অভিজ্ঞতা হবে

এখানে চারটি (4) উপাদান ব্যাখ্যা করা হয়েছে:

  • Item_in_optimizer
  • Item_in_subselect
  • Item_ref
  • Left_expression_Cache

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

মাইএসকিএল সাবকিউরিগুলি কেবলমাত্র সাব-নির্বাচনগুলির জন্য দুর্দান্ত, এমনকি একটি টেবিলকে একাধিকবার স্ব-রেফারেন্স করা। অ-নির্বাচনী প্রশ্নের জন্য একই কথা বলা যায় না।

আমি আশা করি এই ব্যাখ্যা সাহায্য করবে।


7

আমি মনে করি যে এটি কেন প্রত্যাশিত হিসাবে কাজ করে না তা নয় যে মাইএসকিউএল subqueries প্রক্রিয়া করে তবে মাইএসকিউএল UPDATEবিবৃতিতে কীভাবে প্রক্রিয়া করে । বিবৃতি:

DELETE 
FROM test 
WHERE id = 
      ( SELECT id 
        FROM 
            ( SELECT * 
              FROM test
            ) temp 
        ORDER BY RAND() 
        LIMIT 1
      ) 

WHEREসারি সারি শর্তটি প্রক্রিয়া করবে । অর্থ, প্রতিটি সারির জন্য, এটি সাবকিউারি চালাবে এবং ফলাফলটির বিরুদ্ধে পরীক্ষা করবে id:

  ( SELECT id 
    FROM 
        ( SELECT * 
          FROM test
        ) temp 
    ORDER BY RAND() 
    LIMIT 1
  ) 

সুতরাং, এটি মাঝে মধ্যে 0, 1, 2 বা আরও বেশি সারি মিলবে (এবং মুছে ফেলবে)!


আপনি এটির মতো এটি আবার লিখতে পারেন এবং সাবকিউরিটি একবার প্রক্রিয়া করা হবে:

DELETE t
FROM 
      test t
  JOIN 
      ( SELECT id 
        FROM test  
        ORDER BY RAND() 
        LIMIT 1
      ) tmp
    ON tmp.id = t.id

1

এই পৃষ্ঠার প্রথম বুলেট থেকে , LIMITমাইএসকিএল সাবকিউরিয়ায় সমর্থিত নয়। যদিও এটি আপনার জন্য ত্রুটি ফেলবে না আমি নিশ্চিত নই, যদিও।


2
LIMITকেবলমাত্র IN (<কোড> ব্যাকটিক্স ~ ড্র্যাচেনস্টেন দিয়ে প্রতিস্থাপন)
টমাস.লং

ভাল ... আমি এমন কিছু শিখলাম, যা ব্যাখ্যা করে যে এটি ত্রুটি কেন টস করল না!
ডেরেক ডাউনি

@ tomas.lang আপনি <কোড> ব্লকের পরিবর্তে শব্দটি ঘিরে `(টিক চিহ্ন) ব্যবহার করতে পারেন।
ডেরেক ডোনয়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.