আমি কীভাবে বিদ্যমান এসকিউএল টেবিলটিতে একটি বিদেশী কী যুক্ত করব?


128

আমার নিম্নলিখিত টেবিল রয়েছে:

CREATE TABLE child( 
  id INTEGER PRIMARY KEY, 
  parent_id INTEGER, 
  description TEXT);

আমি কীভাবে একটি বিদেশী কী বাধা যুক্ত করব parent_id? ধরুন বিদেশী কী সক্ষম হয়েছে।

বেশিরভাগ উদাহরণ ধরে নেওয়া হয় যে আপনি টেবিলটি তৈরি করছেন - আমি কোনও বিদ্যমানটিতে সীমাবদ্ধতা যুক্ত করতে চাই।


SQLite ALTER কমান্ড কেবল "পুনরায় নামকরণ সারণী" এবং "কলাম যুক্ত করুন" সমর্থন করে। তবে, আমরা অপারেশনগুলির একটি সাধারণ ক্রম ব্যবহার করে একটি সারণির বিন্যাসে অন্যান্য স্বেচ্ছাসেবী পরিবর্তন করতে পারি। পরীক্ষা করে দেখুন আমার উত্তর
situee

উত্তর:


198

আপনি পারবেন না।

যদিও আপনার টেবিলটিতে একটি বিদেশী কী যুক্ত করতে এসকিউএল -২৯ সিনট্যাক্সটি নীচে থাকবে:

ALTER TABLE child ADD CONSTRAINT fk_child_parent
                  FOREIGN KEY (parent_id) 
                  REFERENCES parent(id);

SQLite সমর্থন করে নাADD CONSTRAINT এর বৈকল্পিক ALTER TABLEকমান্ড ( sqlite.org: এসকিউএল বৈশিষ্ট্য SQLite নেই বাস্তবায়ন না যে )।

সুতরাং, স্ক্লাইট 3.6.1 এ একটি বিদেশী কী যুক্ত করার একমাত্র উপায় CREATE TABLEনিম্নলিখিত হিসাবে রয়েছে:

CREATE TABLE child ( 
    id           INTEGER PRIMARY KEY, 
    parent_id    INTEGER, 
    description  TEXT,
    FOREIGN KEY (parent_id) REFERENCES parent(id)
);

দুর্ভাগ্যক্রমে আপনাকে অস্থায়ী টেবিলটিতে বিদ্যমান ডেটা সংরক্ষণ করতে হবে, পুরাতন টেবিলটি ফেলে দিতে হবে, এফকে বাধা দিয়ে নতুন টেবিল তৈরি করতে হবে, তারপরে অস্থায়ী টেবিল থেকে ডেটাটি অনুলিপি করতে হবে। ( sqlite.org - FAQ: Q11 )


28
আমি মনে করি পুরানো টেবিলটির নতুন নামকরণ, নতুন টেবিল তৈরি করা এবং ডেটাটি আবার অনুলিপি করা আরও সহজ Then
tuinstoel

হ্যাঁ, এটি আরও সহজ। আমি কেবল স্ক্লাইট এফএকিউ: sqlite.org/faq.html#q11 উদ্ধৃত করছিলাম । বাস্তবে, RENAME TOকয়েকটি ALTER TABLEস্ক্রাইটে সমর্থিত কয়েকটি রূপগুলির মধ্যে একটি হ'ল
ড্যানিয়েল

3
এটি হওয়া উচিত নয়: বিদেশী কী (প্যারেন্ট_আইডি) পিতা বা মাতা (আইডি) সত্য, জনাথন "প্যারেন্ট টেবিল" নামটি দেয়নি। আসলে, টেবিলটির নাম ব্যক্তির রাখা উচিত, তবে ...
igorludi

3
এটি আমার কাছে বড় সমস্যা বলে মনে হচ্ছে। সাধারণত আপনি যখন একটি ডেটাবেস ডাম্প করেন, আপনি প্রথমে তৈরি টেবিল কমান্ড রফতানি করে। তারপরে অন্তর্ভুক্ত কমান্ডগুলি অন্তর্ভুক্ত করুন এবং অবশেষে কমান্ড কমান্ড যুক্ত করুন। যদি আপনার ডেটাতে বিজ্ঞপ্তি (বৈদেশিক কী মান) নির্ভরতা থাকে তবে বিদেশী কীগুলি প্রয়োগ করার সময় আপনি আপনার ডেটা sertোকাতে পারবেন না। তবে আপনি যদি পরে বিদেশী কী বাধাগুলি যোগ করতে না পারেন তবে আপনি আটকে আছেন। অবশ্যই পিছনে সীমাবদ্ধতা আছে, কিন্তু এটি খুব আনাড়ি।
নগাইলজ

9
অন্যান্য টেবিলের এই টেবিলের রেফারেন্স থাকলে প্রথম মন্তব্যে যেমন বলা হয়েছে তেমন পুরানো টেবিলটির নাম পরিবর্তন করবেন না! এই ক্ষেত্রে আপনাকে এই সমস্ত সারণীও পুনরায় তৈরি করতে হবে।
রকনো

57

আপনি যদি সারণি পরিবর্তন করেন এবং সীমাবদ্ধতা ব্যবহার করে এমন কলাম যুক্ত করেন তবে আপনি সীমাবদ্ধতা যুক্ত করতে পারেন।

প্রথমে, প্যারেন্ট_আইডি ছাড়াই টেবিল তৈরি করুন:

CREATE TABLE child( 
  id INTEGER PRIMARY KEY,  
  description TEXT);

তারপরে, টেবিল পরিবর্তন করুন:

ALTER TABLE child ADD COLUMN parent_id INTEGER REFERENCES parent(id);

2
এই ক্রমটি ব্যবহার করতে ভাল, তবে এটি আসল প্রশ্নের উত্তর দেয় না: আমি একটি বিদ্যমানটিতে প্রতিবন্ধকতা যুক্ত করতে চাই।
নেকড়ে

9

দয়া করে https://www.sqlite.org/lang_altertable.html#otheralter দেখুন

এসকিউএলাইট দ্বারা সরাসরি সমর্থিত একমাত্র স্কিমা পরিবর্তনকারী কমান্ডগুলি হ'ল উপরে বর্ণিত "পুনরায় নামকরণ সারণি" এবং "কলাম যুক্ত করুন" কমান্ডগুলি। তবে অ্যাপ্লিকেশনগুলি সাধারণ ক্রিয়াকলাপের সাহায্যে টেবিলের বিন্যাসে অন্যান্য স্বেচ্ছাসেবী পরিবর্তন করতে পারে। কিছু টেবিল এক্স এর স্কিমা ডিজাইনে স্বেচ্ছাসেবী পরিবর্তন করার পদক্ষেপগুলি নিম্নরূপ:

  1. যদি বিদেশী কী সীমাবদ্ধতাগুলি সক্ষম করা থাকে তবে PRAGMA বিদেশী_কিগুলি = বন্ধ ব্যবহার করে তাদের অক্ষম করুন।
  2. একটি লেনদেন শুরু করুন।
  3. টেবিল এক্স এর সাথে সম্পর্কিত সমস্ত সূচিপত্র এবং ট্রিগারগুলির ফর্ম্যাটটি মনে রাখুন below নীচের আট ধাপে এই তথ্যটির প্রয়োজন হবে। এটি করার একটি উপায় হ'ল নিম্নলিখিতগুলির মতো একটি ক্যোয়ারী চালানো: নির্বাচন করুন টাইপ করুন, স্ক্যুইট_মাস্টার থেকে স্কয়ার করুন যেখানে tbl_name = 'এক্স'।
  4. নতুন টেবিল "new_X" তৈরি করতে টেবিল এক্সের পছন্দসই সংশোধিত ফর্ম্যাটে তৈরি করতে টেবিল তৈরি করুন sure অবশ্যই নিশ্চিত করুন যে "নতুন_এক্স" নামটি কোনও বিদ্যমান সারণীর নামের সাথে সংঘর্ষে না চলে।
  5. এক্স থেকে নতুন_ এক্সে লিখিত সামগ্রী যেমন স্থানান্তর করুন: INSERT INTO new_X নির্বাচন করুন ... এক্স থেকে
  6. পুরানো টেবিলটি ড্রপ করুন: টেবিল এক্স ড্রপ করুন।
  7. এক্স_এর পরিবর্তে নতুন_এক্সের নাম পরিবর্তন করুন: টেবিল নতুন_এক্সের পুনরায় নামকরণ করুন এক্স।
  8. সারণী এক্স-এর সাথে সম্পর্কিত সূচকগুলি এবং ট্রিগারগুলি পুনর্গঠন করতে ক্রিয়েট ইন্ডেক্স এবং ক্রিয়েট ট্রিগার ব্যবহার করুন Perhaps সম্ভবত উপরের পদক্ষেপ 3 থেকে সংরক্ষণ করা ট্রিগার এবং সূচকগুলির পুরানো ফর্ম্যাটটি গাইড হিসাবে ব্যবহার করুন, পরিবর্তনের জন্য উপযুক্ত হিসাবে পরিবর্তনগুলি করুন।
  9. যদি কোনও মতামত স্কিমা পরিবর্তনের দ্বারা প্রভাবিত এমনভাবে টেবিল এক্সকে উল্লেখ করে, তবে ড্রপ ভিউ ব্যবহার করে সেই মতামতগুলি ফেলে দিন এবং ক্রেইট ভিউ ব্যবহার করে স্কিমা পরিবর্তনটি সামঞ্জস্য করতে প্রয়োজনীয় পরিবর্তনগুলি নিয়ে তাদের পুনরায় তৈরি করুন।
  10. বিদেশী কী সীমাবদ্ধতাগুলি যদি প্রাথমিকভাবে সক্ষম করা থাকে তবে স্কিমা পরিবর্তনটি কোনও বিদেশী কী সীমাবদ্ধতা ভঙ্গ করে না তা যাচাই করতে PRAGMA বিদেশী_কি_চেক চালান।
  11. লেনদেনটি প্রতিশ্রুতিবদ্ধ পদক্ষেপ 2-এ শুরু হয়েছিল।
  12. বিদেশী কীগুলির সীমাবদ্ধতা যদি প্রাথমিকভাবে সক্ষম করা থাকে তবে এখনই তাদের পুনরায় সক্ষম করুন।

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


4

হ্যাঁ, আপনি নতুন কলাম যুক্ত না করেই পারেন। ডাটাবেসটি ক্ষতিগ্রস্ত না করতে যাতে সঠিকভাবে তা করতে আপনাকে সতর্ক হতে হবে, তাই চেষ্টা করার আগে আপনার ডাটাবেসটিকে পুরোপুরি ব্যাকআপ করা উচিত।

আপনার নির্দিষ্ট উদাহরণের জন্য:

CREATE TABLE child(
  id INTEGER PRIMARY KEY,
  parent_id INTEGER,
  description TEXT
);

--- create the table we want to reference
create table parent(id integer not null primary key);

--- now we add the foreign key
pragma writable_schema=1;
update SQLITE_MASTER set sql = replace(sql, 'description TEXT)',
    'description TEXT, foreign key (parent_id) references parent(id))'
) where name = 'child' and type = 'table';

--- test the foreign key
pragma foreign_keys=on;
insert into parent values(1);
insert into child values(1, 1, 'hi'); --- works
insert into child values(2, 2, 'bye'); --- fails, foreign key violation

বা আরও সাধারণভাবে:

pragma writable_schema=1;

// replace the entire table's SQL definition, where new_sql_definition contains the foreign key clause you want to add
UPDATE SQLITE_MASTER SET SQL = new_sql_definition where name = 'child' and type = 'table';

// alternatively, you might find it easier to use replace, if you can match the exact end of the sql definition
// for example, if the last column was my_last_column integer not null:
UPDATE SQLITE_MASTER SET SQL = replace(sql, 'my_last_column integer not null', 'my_last_column integer not null, foreign key (col1, col2) references other_table(col1, col2)') where name = 'child' and type = 'table';

pragma writable_schema=0;

যে কোনও উপায়ে, আপনি সম্ভবত কোনও পরিবর্তন করার আগে প্রথমে এসকিউএল সংজ্ঞা কী তা দেখতে চাইবেন:

select sql from SQLITE_MASTER where name = 'child' and type = 'table';

আপনি যদি প্রতিস্থাপন () পদ্ধতির ব্যবহার করেন তবে কার্যকর করার আগে, প্রথমে আপনার প্রতিস্থাপন () কমান্ডটি চালিয়ে যাচাই করার জন্য আপনি এটি সহায়ক হতে পারেন:

select replace(sql, ...) from SQLITE_MASTER where name = 'child' and type = 'table';

3

আপনি যদি ফায়ারফক্স অ্যাড-অন স্ক্লাইট-ম্যানেজার ব্যবহার করেন তবে আপনি নিম্নলিখিতটি করতে পারেন:

টেবিলটি ড্রপ করে আবার তৈরি করার পরিবর্তে যেকোন একটি ঠিক এভাবে পরিবর্তন করতে পারে।

কলামগুলির পাঠ্য বাক্সে, প্রসঙ্গ মেনু আনতে তালিকাভুক্ত সর্বশেষ কলামের নামটিতে ডান ক্লিক করুন এবং কলাম সম্পাদনা করুন নির্বাচন করুন। নোট করুন যে টেবিল সংজ্ঞাটির শেষ কলামটি যদি প্রাথমিক কী হয় তবে প্রথমে একটি নতুন কলাম যুক্ত করা দরকার এবং তারপরে বিদেশী কী সংজ্ঞা যুক্ত করতে নতুন কলামের কলামের ধরণটি সম্পাদনা করা প্রয়োজন। কলামের ধরণের বাক্সের মধ্যে একটি কমা এবং এটি যুক্ত করুন

FOREIGN KEY (parent_id) REFERENCES parent(id)

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

তথ্যসূত্র: স্ক্লাইট ম্যানেজার



-1

মূলত আপনি পারবেন না তবে আপনি পরিস্থিতিটি বাইপাস করতে পারবেন।

বিদ্যমান সারণীতে বিদেশী কী সীমাবদ্ধতার সঠিক উপায়টি হ'ল নিম্নলিখিত আদেশ command

db.execSQL("alter table child add column newCol integer REFERENCES parent(parent_Id)");

তারপর কপি parent_Id তথ্য newCol এবং তারপর মুছে ফেলতে Parent_Id কলাম। সুতরাং, অস্থায়ী টেবিলের প্রয়োজন নেই।


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

নাঃ। এটি জিজ্ঞাসা প্রশ্নের উত্তর দেয় না।
এমকে

-4

প্রথম সন্তানের টেবিলে একটি কলাম যোগ Cidহিসাবে intতারপর alter tableনিচের কোড দিয়ে। এইভাবে আপনি Cidপ্যারেন্ট সারণীর প্রাথমিক কী হিসাবে বিদেশী কীটি যুক্ত করতে পারেন এবং এটি শিশু টেবিলে বিদেশী কী হিসাবে ব্যবহার করতে পারেন ... আশা করি এটি আপনাকে সহায়তা করবে কারণ এটি আমার পক্ষে ভাল:

ALTER TABLE [child] 
  ADD CONSTRAINT [CId] 
  FOREIGN KEY ([CId]) 
  REFERENCES [Parent]([CId]) 
  ON DELETE CASCADE ON UPDATE NO ACTION;
GO

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