আমি টেবিলের সমস্ত সারিটি কীভাবে লুপ করব? (মাইএসকিউএল)


90

আমার একটি টেবিল এ রয়েছে এবং সেখানে একটি প্রাথমিক কী আইডি রয়েছে।

এখন আমি এ-তে সমস্ত সারি পেরিয়ে যেতে চাই

আমি 'এ-তে প্রতিটি রেকর্ডের জন্য' জাতীয় কিছু খুঁজে পেয়েছি তবে এটি মাইএসকিউএলে আপনি কীভাবে করেন তা মনে হয় না।

বিষয়টি প্রতিটি সারিটির জন্য আমি একটি ক্ষেত্র নিতে এবং এটি রূপান্তর করতে চাই, এটি অন্য টেবিলের মধ্যে sertোকানো এবং তারপরে সারির কয়েকটি ক্ষেত্র আপডেট করতে চাই। আমি নির্বাচিত অংশ এবং একটি বিবৃতিতে সন্নিবেশ রাখতে পারি, তবে সেখানে কীভাবে আপডেট পেতে হয় তা আমি জানি না। আমি লুপ করতে চাই। এবং অনুশীলনের জন্য আমি মাইএসকিউএল ব্যতীত অন্য কিছু ব্যবহার করতে চাই না।

সম্পাদনা করুন

আমি একটি উদাহরণ প্রশংসা করব।

এবং একটি সমাধান যা একটি পদ্ধতিতে রাখা প্রয়োজন হয় না।

সম্পাদনা 2

ঠিক আছে এই দৃশ্যটি সম্পর্কে চিন্তা করুন:

সারণি A এবং B, প্রতিটি ক্ষেত্রের ID এবং VAL রয়েছে।

এখন আমি যা করতে চাই তার এটি সিডো কোড:

for(each row in A as rowA)
{
  insert into B(ID, VAL) values(rowA[ID], rowA[VAL]);
}

মূলত একটি লুপ ব্যবহার করে এ-এর লিখিত সামগ্রী অনুলিপি করা।

(এটি কেবল একটি সরল উদাহরণ, অবশ্যই আপনি এটির জন্য কোনও লুপ ব্যবহার করবেন না))}


হাই রেফেল আমার জন্য এটির ত্রুটিটি প্রদান করে: আমার এসকিউএল> এর জন্য (ডাব্লুপিওউবিউবিউনে_কোমিনি_উজারে প্রতিটি সারি এক্স হিসাবে) w wp_mobiune_ecommune_user (লিঙ্গ_নউ) মানগুলিতে প্রবেশ করুন (এক্স [লিঙ্গ])}; আরআরও 1064 (42000): আপনার এসকিউএল সিনট্যাক্সে আপনার একটি ত্রুটি রয়েছে; ডান সিনট্যাক্সের জন্য আপনার মাইএসকিউএল সার্ভার সংস্করণের সাথে সামঞ্জস্যপূর্ণ ম্যানুয়ালটি পরীক্ষা করুন (এক্সপি হিসাবে ডাব্লিউপি_মোবিউন_মেকিউমনে_উজারে প্রতিটি সারি) p wp_mobiune_ecommune '1
োকান

উত্তর:


137

যেহেতু একটি লুপের পরামর্শটি কোনও পদ্ধতির ধরণের সমাধানের অনুরোধকে বোঝায়। আমারটা এখানে.

টেবিল থেকে নেওয়া যে কোনও একক রেকর্ডে কাজ করে এমন যে কোনও ক্যোয়ারী এটিকে টেবিলের প্রতিটি সারি পেরিয়ে চালানোর জন্য কোনও পদ্ধতিতে মোড়ানো হতে পারে:

DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;

তারপরে আপনার উদাহরণ অনুসারে পদ্ধতিটি এখানে রয়েছে (টেবিল_এ এবং টেবিল_বি স্পষ্টতার জন্য ব্যবহৃত)

CREATE PROCEDURE ROWPERROW()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM table_A INTO n;
SET i=0;
WHILE i<n DO 
  INSERT INTO table_B(ID, VAL) SELECT (ID, VAL) FROM table_A LIMIT i,1;
  SET i = i + 1;
END WHILE;
End;
;;

তারপরে ডিলিমিটারটি পুনরায় সেট করতে ভুলবেন না

DELIMITER ;

এবং নতুন পদ্ধতি চালান

CALL ROWPERROW();

আপনার "অনুরোধ INTO" লাইনে আপনি যা খুশি তা করতে পারেন যা আমি আপনার উদাহরণ অনুরোধ থেকে কেবল অনুলিপি করেছি।

সাবধানে নোট করুন যে এখানে ব্যবহৃত "INSERT INTO" লাইনটি প্রশ্নের রেখাটি আয়না করে। এই উত্তরের মতামত অনুসারে আপনাকে নিশ্চিত করতে হবে যে আপনার এসকিউএল এর যে সংস্করণটি চলছে তার জন্য আপনার প্রশ্নটি সিনট্যাক্টিক্যালি সঠিক কিনা is

সাধারণ ক্ষেত্রে যেখানে আপনার আইডি ক্ষেত্রটি বাড়ানো হয় এবং 1 থেকে শুরু হয় উদাহরণের লাইনটি হতে পারে:

INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;

"নির্বাচন COUNT" লাইনটি এর সাথে প্রতিস্থাপন করা হচ্ছে

SET n=10;

কেবলমাত্র টেবিল_এ-তে প্রথম 10 রেকর্ডে আপনার ক্যোয়ারিকে পরীক্ষা করতে দেবে।

গত এক জিনিস. এই প্রক্রিয়াটি বিভিন্ন টেবিল জুড়ে বাসা বাঁধার পক্ষে খুব সহজ এবং আমি এক টেবিলে এমন কোনও প্রক্রিয়া চালিয়ে যেতে পারি যা অভিভাবক সারণীর প্রতিটি সারি থেকে একটি নতুন টেবিলের মধ্যে বিভিন্ন সংখ্যক রেকর্ডকে গতিশীলভাবে sertedোকানো হয়েছিল।

আপনার যদি দ্রুত চালনার প্রয়োজন হয় তবে অবশ্যই এটি ভিত্তিক সেট করার চেষ্টা করুন, যদি না হয় তবে এটি ঠিক আছে। আপনি উপরের কার্সার আকারে আবারও লিখতে পারেন তবে এটি কার্য সম্পাদন করতে পারে না। যেমন:

DROP PROCEDURE IF EXISTS cursor_ROWPERROW;
DELIMITER ;;

CREATE PROCEDURE cursor_ROWPERROW()
BEGIN
  DECLARE cursor_ID INT;
  DECLARE cursor_VAL VARCHAR;
  DECLARE done INT DEFAULT FALSE;
  DECLARE cursor_i CURSOR FOR SELECT ID,VAL FROM table_A;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
  OPEN cursor_i;
  read_loop: LOOP
    FETCH cursor_i INTO cursor_ID, cursor_VAL;
    IF done THEN
      LEAVE read_loop;
    END IF;
    INSERT INTO table_B(ID, VAL) VALUES(cursor_ID, cursor_VAL);
  END LOOP;
  CLOSE cursor_i;
END;
;;

ভেরিয়েবলগুলি ঘোষণার কথা মনে রাখবেন আপনি কোয়েরি সারণীগুলির মতো একই ধরণের হিসাবে ব্যবহার করবেন।

আমার পরামর্শ হ'ল আপনি যখন পারেন তখন সেটবেসড কোয়েরিগুলি সহ যান এবং আপনার যদি প্রয়োজন হয় তবে কেবল সাধারণ লুপ বা কার্সার ব্যবহার করুন।


4
টেবিল_বিতে অন্তর্ভুক্ত করুন সারণী_বি (আইডি, ভ্যাল) ভ্যালু (আইডি, ভ্যাল) থেকে টেবিল_এ লিমিটেড i, 1; একটি সিনট্যাক্স ত্রুটি দেয়।
জোনাথন

4
নিখোঁজ বলে মনে হচ্ছে 'মিথ্যা ফলস ডটলারে করা হয়েছে;' কার্সার_আই ঘোষণার পরে
এরিকএল 2'14

4
সম্পত্তিটি সত্য হিসাবে সেট করা হয়, আমার এটি স্থাপন করা উচিত বা একটি সংরক্ষিত শব্দ যা মাইএসকিএল কার্সার দ্বারা স্বয়ংক্রিয়ভাবে ব্যবহৃত হয়?
IgniteCoders

4
INSERT INTO কলটি এসকিউএল 5.5 হিসাবে একটি বাক্য গঠন ত্রুটি ছুঁড়েছে, সঠিক কলটি INSERT INTOTT_B (ID, VAL) নির্বাচন করুন (ID, VAL) সারণী_এ যেখানে আইডি = i থেকে;
আম্বার

এটি একটি আজীবন সময় নেবে, সুতরাং সীমা এবং বৃদ্ধি বৃদ্ধি করে ব্যাচের আকার 1000 এ বাড়ানোর চেষ্টা করুন: LIMIT i,1000;এবং set i = i + 1000;
অ্যালান দীপ

16

আপনার সত্যিকার অর্থে দুটি প্রশ্নের সাথে জড়িত একটি সেট ভিত্তিক সমাধান ব্যবহার করা উচিত (বেসিক সন্নিবেশ):

INSERT INTO TableB (Id2Column, Column33, Column44)
SELECT id, column1, column2 FROM TableA

UPDATE TableA SET column1 = column2 * column3

এবং আপনার রূপান্তরের জন্য:

INSERT INTO TableB (Id2Column, Column33, Column44)
SELECT 
    id, 
    column1 * column4 * 100, 
    (column2 / column12) 
FROM TableA

UPDATE TableA SET column1 = column2 * column3

এখন যদি আপনার রূপান্তরটি আরও জটিল এবং একাধিক টেবিলের সাথে জড়িত থাকে তবে বিশদ সহ আরও একটি প্রশ্ন পোস্ট করুন।


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

4
@ রাফেল ১৯৮৪: "নির্দিষ্ট সারিগুলির জন্য নির্দিষ্ট সারিগুলির" শর্ত যুক্ত করতে আপনার প্রশ্নটি সম্পাদনা করুন এবং আমরা এটিতে সহায়তা করতে পারি। আপনি সত্যিই কার্সার / লুপের রুটে যেতে চান না - এটি অত্যন্ত অদক্ষ fficient
রাজ মোর

ওহ ভাল ... আপনি জানেন আমি সেট ভিত্তিক ক্যোয়ারি পথে যেতে আরও বেশি খুশি হব! তবে দক্ষতা এখানে কোনও অনুপ্রেরণা নয় কারণ আমার প্রশ্নটি একাডেমিক আগ্রহের। টেবিলটি যথেষ্ট ছোট আমি নিজেই এটি করতে পারি। আমি সত্যিই একটি লুপ সংস্করণ প্রশংসা করব। আমি হয়ত সেই সমস্যাটি পোস্ট করে আবার কাউকে সেট ভিত্তিক শৈলীতে সহায়তা করতে অনুমতি দেওয়ার জন্য আরও বিশদ সরবরাহ করি।
রাফেল

@RajMore সাথে একমত, কার্সার / লুপ অদক্ষ হয়, নীচের রেফারেন্সের জন্য কার্সার কর্মক্ষমতা প্রায় 2 লিঙ্ক: 1. rpbouman.blogspot.tw/2006/09/refactoring-mysql-cursors.html 2. stackoverflow.com/questions/11549567/ …
ব্রাউনি লিন

@ রাজমোর আপনি কি আমাকে আমার প্রশ্নে
নুরভ

4

কার্সরগুলি এখানে একটি বিকল্প, তবে তারা প্রায়শই ক্যোয়ারী ইঞ্জিনটির সর্বোত্তম ব্যবহার না করায় সাধারণত তা ভ্রষ্ট হয়। আপনি যদি কোনও কর্সর ব্যবহার না করেই যা করতে চান তা অর্জন করতে পারেন কিনা তা দেখার জন্য 'সেট ভিত্তিক প্রশ্নগুলি' তদন্তের বিষয়টি বিবেচনা করুন।


সেট ভিত্তিক ক্যোয়ারী সম্পর্কে আমি বেশি তথ্য খুঁজে পাচ্ছি না। তবে আমি অনুমান করি আপনি একটি নির্বাচনী বিবৃতিতে নির্বাচন বলতে চাইছেন। সমস্যাটি হ'ল আমারও একটি আপডেট চালানো দরকার।
রাফেল

0

মিঃ পার্পল এর উদাহরণটি আমি যেমন মাইএসকিএল ট্রিগারটিতে ব্যবহার করেছি,

begin
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
Select COUNT(*) from user where deleted_at is null INTO n;
SET i=0;
WHILE i<n DO 
  INSERT INTO user_notification(notification_id,status,userId)values(new.notification_id,1,(Select userId FROM user LIMIT i,1)) ;
  SET i = i + 1;
END WHILE;
end

4
আপনি কীভাবে সমাধান করতে পারেন তা দয়া করে কিছু তথ্য যুক্ত করতে পারেন?
থ্যানটিক

-26
    Use this:

    $stmt = $user->runQuery("SELECT * FROM tbl WHERE ID=:id");
    $stmt->bindparam(":id",$id);
    $stmt->execute();

        $stmt->bindColumn("a_b",$xx);
        $stmt->bindColumn("c_d",$yy);


    while($rows = $stmt->fetch(PDO::FETCH_BOUND))
    {
        //---insert into new tble
    }   
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.