মাইএসকিউএল একাধিক টেবিল sertোকান? (ডাটাবেস সাধারণীকরণ?)


136

আমি insertএকই ক্যোয়ারিতে একাধিক টেবিলগুলিতে তথ্যের জন্য কোনও উপায় অনুসন্ধান করার চেষ্টা করেছি , তবে এটি অসম্ভব? সুতরাং আমি insertএটি কেবল একাধিক প্রশ্নগুলি ব্যবহার করে চাই ;

INSERT INTO users (username, password) VALUES('test', 'test')
INSERT INTO profiles (userid, bio, homepage) VALUES('[id of the user here?]','Hello world!', 'http://www.stackoverflow.com')

তবে আমি কীভাবে টেবিলের জন্য "ম্যানুয়াল" idথেকে অটো-ইনক্রিমেন্ট দিতে পারি ?usersuseridprofile


8
আপনি লেনদেন সম্পর্কে শিখতে চান
vichle

উত্তর:


241

না, আপনি একটি মাইএসকিউএল কমান্ডে একাধিক সারণীতে সন্নিবেশ করতে পারবেন না। আপনি তবে লেনদেন ব্যবহার করতে পারেন।

BEGIN;
INSERT INTO users (username, password)
  VALUES('test', 'test');
INSERT INTO profiles (userid, bio, homepage) 
  VALUES(LAST_INSERT_ID(),'Hello world!', 'http://www.stackoverflow.com');
COMMIT;

LAST_INSERT_ID()স্বতঃসংশোধের মানগুলি পুনরায় ব্যবহার করতে একবার দেখুন ।

সম্পাদনা: আপনি বলেছিলেন " এতক্ষণ পরে এটি বের করার চেষ্টা করার পরেও এটি কার্যকর হয় না I আমি কেবল উত্পন্ন আইডিটি $ ভারে স্থাপন করতে পারি না এবং সমস্ত মাইএসকিউএল কমান্ডের মধ্যে $ ভার্টটি রাখতে পারি না? "

আমাকে বিশদভাবে বলতে দাও: এখানে 3 টি সম্ভাব্য উপায় রয়েছে:

  1. উপরের কোডটিতে আপনি দেখতে পাচ্ছেন। এটি মাইএসকিউএল এ সবই করে, এবং LAST_INSERT_ID()দ্বিতীয় বিবৃতিতে স্বয়ংক্রিয়ভাবে প্রথম বিবৃতিতে wasোকানো স্বতঃসংশোধ-কলামের মান হবে।

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

  2. এটি LAST_INSERT_ID()একটি মাইএসকিউএল ভেরিয়েবলে স্টক করবে :

    INSERT ...
    SELECT LAST_INSERT_ID() INTO @mysql_variable_here;
    INSERT INTO table2 (@mysql_variable_here, ...);
    INSERT INTO table3 (@mysql_variable_here, ...);
  3. LAST_INSERT_ID()একটি পিএইচপি ভেরিয়েবল (বা আপনার পছন্দের কোনও ডাটাবেসের সাথে সংযোগ করতে পারে এমন কোনও ভাষা ) স্টক করবে :

    • INSERT ...
    • আপনার ভাষাটি পুনরুদ্ধারের জন্য ব্যবহার করুন LAST_INSERT_ID(), হয় মাইএসকিউএলে সেই আক্ষরিক বিবৃতিটি কার্যকর করে বা উদাহরণস্বরূপ পিএইচপি ব্যবহার করে mysql_insert_id()যা এটি আপনার জন্য করে
    • INSERT [use your php variable here]

সতর্কতামূলক

আপনি যেভাবে এটি বেছে নেওয়ার সমাধান করুন না কেন, প্রশ্নগুলির মধ্যে মৃত্যুদন্ড কার্যকর করা উচিত (তবে উদাহরণস্বরূপ, আপনার ডাটাবেস-সার্ভার ক্র্যাশ) what যদি আপনি "কিছু শেষ করেছেন, অন্যেরা না" দিয়ে বাঁচতে পারেন তবে পড়বেন না।

তবে আপনি যদি সিদ্ধান্ত নেন "হয় সমস্ত প্রশ্নের সমাপ্তি, না কোনও শেষ - আমি কিছু টেবিলগুলিতে সারি চাই না তবে অন্যগুলিতে কোনও মিল নেই, আমি সর্বদা আমার ডাটাবেস টেবিলগুলিকে সামঞ্জস্যপূর্ণ রাখতে চাই", আপনাকে লেনদেনে সমস্ত বিবৃতি মোড়ানো দরকার। এজন্য আমি এখানে BEGINএবং COMMITএখানে ব্যবহার করেছি ।

আপনার আরও তথ্যের প্রয়োজন হলে আবার মন্তব্য করুন :)


3
এবং যদি আমি 2 টিরও বেশি টেবিলের মধ্যে সন্নিবেশ করতে চাই এবং আমি অন্য সমস্তের কাছে একটি অনন্য আইডি এবং ব্যবহারকারী ব্যবহার করতে চাই? এটা কি সম্ভব?
জে উইট

আপনি একটি মাইএসকিউএল ভেরিয়েবলের মূল টেবিল থেকে সর্বশেষ_সাইন্ট_আইডি রাখতে পারেন এবং আপনার অন্যান্য সমস্ত টেবিলগুলিতে সেই পরিবর্তনশীলটি ব্যবহার করতে পারেন। সঞ্চিত পদ্ধতি ব্যবহারের জন্য f00 এর পরামর্শটি যদি আপনি একবারে প্রচুর টেবিল ব্যবহার করতে চলেছেন তবে আরও বেশি অর্থবোধ তৈরি করে।
কোনারাক

3
@ জে উইট: আমি উত্তরটি আপডেট করেছি। 'ওয়ে 3' ব্যাখ্যা করে আপনি প্রকৃতপক্ষে আইডিটি কোনও পরিবর্তনশীলে রাখতে পারেন এবং এটি সমস্ত মাইএসকিউএল কমান্ডে পুনরায় ব্যবহার করতে পারেন, তবে আপনি যদি লঙ্ঘনের ক্ষেত্রে আপনার ডিবি সামঞ্জস্য বজায় রাখতে চান তবে আপনার লেনদেন সম্পর্কে পড়া উচিত।
কুনেরাক

3
অবশ্যই, তারা যেমন নির্বাচন, আপডেট, INSERT এবং মোছার মত মাইএসকিউএল বিবৃতি গ্রহণ করা হয়। প্রথমে একটু টেস্টস্ক্রিপ্ট তৈরি করুন, এবং যদি সবকিছু ঠিকঠাক কাজ করে তবে আপনি ভাল to
কনারাক

2
@ কেনারাক কীভাবে এই একাধিক এসকিউএল স্টেটমেন্টগুলি @mysql_variablesপ্রস্তুত বিবৃতিগুলির সাথে মিল রেখে ব্যবহার করবেন ?
ফার্নান্দো সিলভা

17

আপনি যদি সঞ্চিত পদ্ধতি ব্যবহার করেন তবে মোটামুটি সহজ:

call insert_user_and_profile('f00','http://www.f00.com');

সম্পূর্ণ স্ক্রিপ্ট:

drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varchar(32) unique not null
)
engine=innodb;

drop table if exists user_profile;
create table user_profile
(
profile_id int unsigned not null auto_increment primary key,
user_id int unsigned not null,
homepage varchar(255) not null,
key (user_id)
)
engine=innodb;

drop procedure if exists insert_user_and_profile;

delimiter #

create procedure insert_user_and_profile
(
in p_username varchar(32),
in p_homepage varchar(255)
)
begin
declare v_user_id int unsigned default 0;

insert into users (username) values (p_username);
set v_user_id = last_insert_id(); -- save the newly created user_id

insert into user_profile (user_id, homepage) values (v_user_id, p_homepage);

end#

delimiter ;

call insert_user_and_profile('f00','http://www.f00.com');

select * from users;
select * from user_profile;

2
দুঃখিত, তবে এই পিএইচপি? আমি এর আগে কিছু দেখিনি। আমি পিএইচপি এবং মাইএসকিউএল ব্যবহার করছি, কোনও টিপস?
জে উইট

1
দেখতে অনেক দীর্ঘ বর্গাকার স্টেটমেন্টের মতো দেখাচ্ছে
মেলবোর্ন

1
@ জয়উইট: না, এগুলি সমস্ত এসকিউএল স্টেটমেন্ট। পদ্ধতিগুলি তৈরি করুন, তারপরে আপনি যে কোনও সময় ব্যবহার করতে পারেন। Dev.mysql.com/doc/refman/5.7/en/create-procedure.html
পিয়েরে-অলিভিয়ার

7

আপনি যদি এই জাতীয় অনেকগুলি রেকর্ড তৈরি করতে চান (তবে একজনকে নয়, 10 জন ব্যবহারকারীকে নিবন্ধিত করতে চান) কী হবে? আমি নিম্নলিখিত সমাধানটি (মাত্র 5 টি অনুসন্ধান) খুঁজে পাচ্ছি:

প্রথম পদক্ষেপ: নতুন ডেটা সঞ্চয় করার জন্য অস্থায়ী সারণী তৈরি করুন।

CREATE TEMPORARY TABLE tmp (id bigint(20) NOT NULL, ...)...;

পরবর্তী, মান সহ এই টেবিলটি পূরণ করুন।

INSERT INTO tmp (username, password, bio, homepage) VALUES $ALL_VAL

এখানে আপনার পরিবর্তে $ALL_VALমানগুলির তালিকা রাখুন: ('টেস্ট 1', 'টেস্ট 1', 'বায়ো 1', 'হোম 1'), ..., ('টেস্টন', 'টেস্টন', 'বিয়ন', 'হোমেন')

দ্বিতীয় ধাপ: 'ব্যবহারকারী' সারণীতে ডেটা প্রেরণ করুন।

INSERT IGNORE INTO users (username, password)
SELECT username, password FROM tmp;

আপনি যদি ইতিমধ্যে কিছু ব্যবহারকারীকে ভিতরে থাকতে দেন তবে এখানে "আইজিনোর" ব্যবহার করা যেতে পারে। Stepচ্ছিক আপনি এই পদক্ষেপের আগে তৃতীয় ধাপের অনুরূপ আপডেট আপডেট ব্যবহার করতে পারেন, ব্যবহারকারীরা ইতিমধ্যে যার ভিতরে আছেন তা খুঁজে পেতে (এবং তাদের টিএমপি টেবিলটিতে চিহ্নিত করুন)। এখানে আমরা সাফল্য জানাই, সেই ব্যবহারকারীর নামটি PRIMARYব্যবহারকারীদের সারণিতে ঘোষণা করা হয়েছে।

তৃতীয় ধাপ: সমস্ত ব্যবহারকারীদের আইডি টিএমপি টেবিল থেকে ব্যবহারকারীদের আইডি পড়তে আপডেট প্রয়োগ করুন। এটি প্রয়োজনীয় পদক্ষেপ।

UPDATE tmp JOIN users ON tmp.username=users.username SET tmp.id=users.id

চতুর্থ ধাপ: ব্যবহারকারীদের জন্য পঠন আইডি ব্যবহার করে অন্য একটি সারণী তৈরি করুন

INSERT INTO profiles (userid, bio, homepage) 
SELECT id, bio, homepage FROM tmp

1
এটি 6 টি কোয়েরি
টেম্পোরারি

3

এটা চেষ্টা কর

$sql= " INSERT INTO users (username, password) VALUES('test', 'test') ";
mysql_query($sql);
$user_id= mysql_insert_id();
if(!empty($user_id) {

$sql=INSERT INTO profiles (userid, bio, homepage) VALUES($user_id,'Hello world!', 'http://www.stackoverflow.com');
/* or 
 $sql=INSERT INTO profiles (userid, bio, homepage) VALUES(LAST_INSERT_ID(),'Hello   world!', 'http://www.stackoverflow.com'); */
 mysql_query($sql);
};

রেফারেন্স
পিএইচপি
MYSQL


2
ব্যবহারকারী তৈরির পরে কিন্তু প্রোফাইল তৈরির আগে সার্ভার ক্র্যাশ হয়ে গেলে এটি সম্ভবত কিছু অযাচিত আচরণের ফলস্বরূপ।
ভিসলে

@ উইচলে তাহলে সবচেয়ে ভাল উপায় কি ??
ডায়োকো

2
@ ভিচলে এই কোডটিতে আপনার সুস্পষ্ট লেনদেন যুক্ত করুন এবং ইতিমধ্যে সেই বাজে কথা বন্ধ করুন
আপনার প্রচলিত

3
@ কনারাক আমি 10 বছরেরও বেশি সময় ধরে পিএইচপি স্ক্রিপ্ট চালাচ্ছি। তাদের উভয়েরই লাইনের মাঝে থেমে থাকার অভ্যাস নেই। আপনার সার্ভারের গুণমানটি প্রায়শই না কমে যাওয়ার জন্য এটির উন্নতি করার বিষয়ে আপনি আরও ভালভাবে ভাবতে চাইবেন। এটা ওয়েব, বন্ধু। এটি ফেডারেল রিজার্ভ নয়। 100,000 000 সফল ব্যক্তিদের এক ভাঙা ব্যবহারকারীর নিবন্ধের সাথে কোনও সমস্যা নেই।
আপনার কমন সেন্স

2
এই উদাহরণে, আপনি সঠিক হতে পারে। যদিও আমার কোডটি সর্বদা অ্যাকাউন্টিংয়ের জন্য ব্যবহৃত হয় - এ-তে অর্থ সরিয়ে নেওয়া এবং এটি বিতে যুক্ত না করার চিন্তাভাবনা অসহনীয়। এছাড়াও, এটি কেবল ওয়েব হলেও কোনও লেনদেন এতটা কঠিন / ব্যয়বহুল নয়? আইএমএইচও, তারা ভাল অভ্যাস তৈরি করে।
কোনারাক

3

mysql_insert_id () দেখুন

এখানে ডকুমেন্টেশন: http://in.php.net/manual/en/function.mysql-insert-id.php


1
এই ফাংশনটি হ'ল ডেটাবেস ধারাবাহিকতার শয়তান।
ভিসলে

সম্মত হন - কোনও লেনদেন ব্যবহার করা আরও ভাল সমাধান হতে পারে
ড্যানিয়েল কুটিক

@ ভিচল: তাই নাকি? আমি প্রায়শই পিএইচপি ব্যবহার করি না তবে আমি বুঝতে পেরেছিলাম LAST_INSERT_ID()যে প্রোগ্রামারটির জন্য ফোন করা তাদের শর্টকাট ছিল ?
কোনারাক

1
সমস্ত প্রশ্নের লেনদেন হয়। বেশিরভাগ প্রোগ্রামিং ভাষায় ডিফল্ট হ'ল স্বয়ংক্রিয় প্রতিশ্রুতিবদ্ধ লেনদেন, যেহেতু বেশিরভাগ লেনদেন কেবল একটি কোয়েরি। Mysql_insert_id () ফাংশনটি বোঝানো হয় যখন আপনি স্বয়ংক্রিয় প্রতিশ্রুতি বন্ধ করেন, তবে লেনদেনের ধারণার সাথে পরিচিত না লোকেরা খুব প্রায়ই ভুল প্রসঙ্গে ব্যবহার হয়।
vichle

3
@ ডিএনএল আপনি এই ফাংশনটি ব্যবহার করতে পারেন এবং লেনদেন ঠিক আছে। এই লেনদেনের মন্তব্যটি প্রশ্নের সাথে সম্পর্কিত নয়।
আপনার প্রচলিত সেনস

1

এটি আমি একটি ইউনি প্রকল্পের জন্য এটি করেছি, সূক্ষ্মভাবে কাজ করে, সম্ভবত নিরাপদ নয়

$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$conn = mysql_connect($dbhost, $dbuser, $dbpass);

$title =    $_POST['title'];            
$name =     $_POST['name'];         
$surname =  $_POST['surname'];                  
$email =    $_POST['email'];            
$pass =     $_POST['password'];     
$cpass =    $_POST['cpassword'];        

$check = 1;

if (){
}
else{
    $check = 1;
}   
if ($check == 1){

require_once('website_data_collecting/db.php');

$sel_user = "SELECT * FROM users WHERE user_email='$email'";
$run_user = mysqli_query($con, $sel_user);
$check_user = mysqli_num_rows($run_user);

if ($check_user > 0){
    echo    '<div style="margin: 0 0 10px 20px;">Email already exists!</br>
             <a href="recover.php">Recover Password</a></div>';
}
else{
    $users_tb = "INSERT INTO users ". 
           "(user_name, user_email, user_password) ". 
        "VALUES('$name','$email','$pass')";

    $users_info_tb = "INSERT INTO users_info".
           "(user_title, user_surname)".
        "VALUES('$title', '$surname')";

    mysql_select_db('dropbox');
    $run_users_tb = mysql_query( $users_tb, $conn );
    $run_users_info_tb = mysql_query( $users_info_tb, $conn );

    if(!$run_users_tb || !$run_users_info_tb){
        die('Could not enter data: ' . mysql_error());
    }
    else{
        echo "Entered data successfully\n";
    }

    mysql_close($conn);
}

}


-1

আপনার বক্তব্য সম্পর্কে একটি মন্তব্য

হাই, আমি একই ক্যোয়ারিতে একাধিক টেবিলগুলিতে তথ্য সন্নিবেশ করার জন্য একটি উপায় অনুসন্ধান করার চেষ্টা করেছি

আপনি কি একই বাটিতে পানীয়ের সাথে মিশ্রিত খাবারের সমস্ত খাবার খান?
আমি মনে করি - না।

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

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

এবং mysql_insert_id () এর সাথে লেনদেনের বিষয়টি লক্ষ্য করা যায়। আপনি ঠিকঠাক লেনদেন অন্তর্ভুক্ত করতে পারেন। এটা ঠিক বিভিন্ন বিষয়। কেউ কোথাও এই প্রশ্ন উত্থাপন।


আপনি যখন সহজে এড়ানো যায় তখন আপনি কেন এমন জিনিসপত্র ঠিক করার ঝুঁকি নিতে চান?
vichle

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

6
কেন আপনি এত আক্রমণাত্মক হন? আমি কেবল উল্লেখ করছি যে লেনদেনগুলি এখানে যাওয়ার উপায়। আপনি যদি চান তবে আপনি এটি নিজের উপায়ে করুন, এখনও সত্য যে লেনদেন এই জাতীয় পরিস্থিতির জন্য তৈরি হয়েছিল।
vichle

@ ভিচলে হ্যাঁ, আমি বেশ কঠোর ছিলাম, আমি ক্ষমা চাইছি। That function is the devil of database consistency.লেনদেন নয়, এটিই আপনার হয়েছিল । আমি লেনদেনে খারাপ কিছু দেখছি না।
আপনার কমন সেন্স

ক্ষমা প্রার্থনা করা হয়েছে। আমি কেবল বোঝাতে চাইছিলাম যে ফাংশনটি প্রায়শই লোকেরা লেনদেনের অস্তিত্ব সম্পর্কে সচেতন নয় তাদের দ্বারা অপব্যবহার করে। এই লোকগুলি পিএইচপি সম্প্রদায়েও যথেষ্ট উপস্থাপন করা হয়।
ভিসলে

-4

পিডিওর জন্য আপনি এটি করতে পারেন

$stmt1 = "INSERT INTO users (username, password) VALUES('test', 'test')"; 
$stmt2 = "INSERT INTO profiles (userid, bio, homepage) VALUES('LAST_INSERT_ID(),'Hello world!', 'http://www.stackoverflow.com')";

$sth1 = $dbh->prepare($stmt1);
$sth2 = $dbh->prepare($stmt2);

BEGIN;
$sth1->execute (array ('test','test'));
$sth2->execute (array ('Hello world!','http://www.stackoverflow.com'));
COMMIT;

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