নাল কলামগুলি দিয়ে অনন্য সীমাবদ্ধতা তৈরি করুন


251

এই লেআউটটি সহ আমার একটি টেবিল রয়েছে:

CREATE TABLE Favorites
(
  FavoriteId uuid NOT NULL PRIMARY KEY,
  UserId uuid NOT NULL,
  RecipeId uuid NOT NULL,
  MenuId uuid
)

আমি এর অনুরূপ একটি অনন্য বাধা তৈরি করতে চাই:

ALTER TABLE Favorites
ADD CONSTRAINT Favorites_UniqueFavorite UNIQUE(UserId, MenuId, RecipeId);

যাইহোক, এই একই সঙ্গে একাধিক সারি অনুমতি দেবে (UserId, RecipeId), যদি MenuId IS NULL। আমি অনুমতি দিতে চান NULLমধ্যে MenuIdএকটি প্রিয় কোন সংযুক্ত করেছে যে মেনু সঞ্চয় করতে, কিন্তু আমি শুধুমাত্র প্রতি ব্যবহারকারী / রেসিপি যুগল এই সারির সর্বাধিক এক চাই।

আমার এখনও অবধি ধারণাগুলি হ'ল:

  1. শূন্যের পরিবর্তে কিছু হার্ড-কোডড ইউআইডি (যেমন সমস্ত শূন্য) ব্যবহার করুন।
    তবে, MenuIdপ্রতিটি ব্যবহারকারীর মেনুতে এফকে বাধা রয়েছে, সুতরাং আমাকে তখন প্রতিটি ব্যবহারকারীর জন্য একটি বিশেষ "নাল" মেনু তৈরি করতে হবে যা ঝামেলা।

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

  3. এটির জন্য কেবল ভুলে যান এবং মাঝারি ওয়্যারে বা একটি সন্নিবেশ ফাংশনে নাল প্রবেশের পূর্ববর্তী অস্তিত্বের জন্য যাচাই করুন এবং এই সীমাবদ্ধতা রাখবেন না।

আমি Postgres 9.0 ব্যবহার করছি।

আমি কি কোন পদ্ধতি অবহেলা করছি?


কেন এটি যদি একই ( UserId, RecipeId) দিয়ে একাধিক সারিকে অনুমতি দেয় তবে যদি MenuId IS NULL?
ড্রুक्स

উত্তর:


382

দুটি আংশিক সূচক তৈরি করুন :

CREATE UNIQUE INDEX favo_3col_uni_idx ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;

CREATE UNIQUE INDEX favo_2col_uni_idx ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;

এইভাবে, কেবল (user_id, recipe_id)যেখানে menu_id IS NULLকাঙ্ক্ষিত সীমাবদ্ধতার কার্যকরভাবে কার্যকর করা যায় সেখানে একটির সংমিশ্রণ হতে পারে ।

সম্ভাব্য ত্রুটি: আপনার কোনও বিদেশী কী রেফারেন্সিং থাকতে (user_id, menu_id, recipe_id)পারে না, আপনি CLUSTERআংশিক সূচকে ভিত্তি করতে পারবেন না , এবং মিলের WHEREশর্ত ছাড়াই অনুসন্ধানগুলি আংশিক সূচক ব্যবহার করতে পারে না। (মনে হয় আপনি তিনটি কলাম প্রশস্ত এফকে রেফারেন্স চাইবেন - এর পরিবর্তে পিকে কলামটি ব্যবহার করুন)

আপনার যদি একটি সম্পূর্ণ সূচকের প্রয়োজন হয় তবে আপনি বিকল্পটি WHEREথেকে শর্তটি বাদ দিতে পারেন favo_3col_uni_idxএবং আপনার প্রয়োজনীয়তা এখনও প্রয়োগ করা হয়।
সূচক, এখন পুরো টেবিল সমন্বিত, অন্য একের সাথে ওভারল্যাপ করে বড় হয়। আদর্শ প্রশ্ন এবং NULLমানগুলির শতাংশের উপর নির্ভর করে এটি কার্যকর হতে পারে বা নাও পারে। চরম পরিস্থিতিতে এটি এমনকি তিনটি সূচকগুলি বজায় রাখতে সহায়তা করতে পারে (দুটি আংশিক এবং শীর্ষে মোট)।

একপাশে: আমি ব্যবহার না করার পরামর্শ পোস্টগ্রি মধ্যে মিশ্র হাতের শনাক্তকারী


1
@ আরউইন ব্র্যান্ডসেটর: " মিশ্র কেস শনাক্তকারীদের " মন্তব্য সম্পর্কে: যতক্ষণ কোনও ডাবল কোট ব্যবহার করা হয় না, ততক্ষণ মিক্সড কেসড আইডেন্টিফায়ার ব্যবহার করা একেবারে ঠিক। সমস্ত ছোট হাতের শনাক্তকারী (আবার: কেবল কোনও উদ্ধৃতি ব্যবহার করা হয় না) ব্যবহার করার ক্ষেত্রে কোনও পার্থক্য নেই
a_horse_with_no_name

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

3
@ এ_হর্স_বিহীন_নো নাম: হ্যাঁ, এটি অবশ্যই সত্য true তবে আপনি যদি এগুলি এড়াতে পারেন: আপনি মিশ্র কেস শনাক্তকারীদের চান না । তারা কোন উদ্দেশ্য পরিবেশন। যদি আপনি এগুলি এড়াতে পারেন: এগুলি ব্যবহার করবেন না। তদতিরিক্ত: তারা কেবল সাধারণ কদর্য। উদ্ধৃত সনাক্তকরণগুলিও কুরুচিপূর্ণ। এগুলির মধ্যে স্পেস সহ SQL92 শনাক্তকারীরা একটি কমিটি দ্বারা তৈরি একটি মিসটপ। এগুলি ব্যবহার করবেন না।
ওয়াইল্ডপ্লাজার

2
@ মাইক: আমার মনে হয় আপনাকে এসকিউএল স্ট্যান্ডার্ড কমিটির সাথে কথা বলতে হবে, সৌভাগ্য :)
মিউ খুব ছোট

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

74

আপনি মেনুআইডিতে একটি coalesce দিয়ে একটি অনন্য সূচক তৈরি করতে পারেন:

CREATE UNIQUE INDEX
Favorites_UniqueFavorite ON Favorites
(UserId, COALESCE(MenuId, '00000000-0000-0000-0000-000000000000'), RecipeId);

আপনার কেবলমাত্র কলের জন্য একটি ইউইউডি বাছাই করতে হবে যা "বাস্তব জীবনে" কখনও ঘটবে না। আপনি সম্ভবত বাস্তব জীবনে কখনও শূন্য ইউআইডি দেখতে পাবেন না তবে আপনি যদি ভৌতিক হয়ে থাকেন তবে আপনি একটি চেক সীমাবদ্ধতা যোগ করতে পারেন (এবং যেহেতু তারা আপনাকে সত্যিকার অর্থে বাইরে নিয়ে আসে ...):

alter table Favorites
add constraint check
(MenuId <> '00000000-0000-0000-0000-000000000000')

1
এটি (তাত্ত্বিক) ত্রুটি বহন করে, যে মেনু_আইডি = '00000000-0000-0000-0000-00000000000000' সহ একটি এন্ট্রি মিথ্যা অনন্য লঙ্ঘনের সূত্রপাত করতে পারে - তবে আপনি ইতিমধ্যে এটি আপনার মন্তব্যে সম্বোধন করেছেন।
এরউইন ব্র্যান্ডসটেটার

2
@ মিস্টুশোর্ট: হ্যাঁ, এটি একটি সঠিক সমাধান। (MenuId <> '00000000-0000-0000-0000-000000000000')যদিও সরল করুন । NULLডিফল্টরূপে অনুমোদিত। বিটিডব্লিউ, তিন ধরণের লোক রয়েছে। ভৌগলিক এবং ডেটাবেস না করে এমন লোক। তৃতীয় ধরণের মাঝে মাঝে বিস্ময় প্রকাশে এসওতে প্রশ্ন পোস্ট করে। ;)
এরউইন ব্র্যান্ডসেটেটার

2
@ আরউইন: আপনি কি "ভৌতিক ও ভাঙা ডাটাবেসযুক্ত" বলতে চাইছেন না?
মিউ খুব ছোট

2
এই দুর্দান্ত সমাধানটি একটি সহজ ধরণের শূন্য কলাম, যেমন পূর্ণসংখ্যার, কোনও অনন্য বাধাতে অন্তর্ভুক্ত করা খুব সহজ করে তোলে।
মার্কাস Pscheidt

2
এটি সত্য যে কোনও ইউইউডি সেই নির্দিষ্ট স্ট্রিং নিয়ে আসে না, কেবল জড়িত সম্ভাবনার কারণে নয়, কারণ এটি কোনও বৈধ ইউআইডি নয় । কোনও ইউইউডি জেনারেটর কোনও অবস্থাতেই কোনও হেক্স ডিজিট ব্যবহারের জন্য মুক্ত নয়, উদাহরণস্বরূপ, ইউইউডিটির সংস্করণ সংখ্যার জন্য একটি অবস্থান সংরক্ষিত।
টবি 1 কেনোবি

1

আপনি কোনও আলাদা টেবিলের সাথে সম্পর্কিত না মেনুতে পছন্দসইগুলি সংরক্ষণ করতে পারেন:

CREATE TABLE FavoriteWithoutMenu
(
  FavoriteWithoutMenuId uuid NOT NULL, --Primary key
  UserId uuid NOT NULL,
  RecipeId uuid NOT NULL,
  UNIQUE KEY (UserId, RecipeId)
)

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

আমি moreোকানো আরও জটিল হিসাবে মনে করি না। আপনি যদি এর সাথে একটি রেকর্ড সন্নিবেশ করতে চান তবে আপনি NULL MenuIdএই টেবিলটি .োকান। যদি না হয়, Favoritesটেবিলে। তবে জিজ্ঞাসাবাদ, হ্যাঁ, এটি আরও জটিল হবে।
ypercubeᵀᴹ

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

আপনি যদি একাধিক মেনুতে একই রেসিপি যুক্ত করতে চান তবে INSERT আরও জটিল হয়ে উঠবে, যেহেতু ফেভারিট উইথআউটমেনুতে ইউজারআইডি / রেসিপিআইডিতে আপনার এক অনন্য বাধা রয়েছে। আমার এই সারিটি তৈরি করতে হবে যদি এটি ইতিমধ্যে উপস্থিত না থাকে।
মাইক ক্রিস্টেনসেন

1
ধন্যবাদ! এই উত্তরটি একটি +1 এর প্রাপ্য কারণ এটি ক্রস-ডাটাবেস বিশুদ্ধ এসকিউএল জিনিস বেশি .. তবে, এই ক্ষেত্রে আমি আংশিক সূচক পথে যাব কারণ এটির জন্য আমার স্কিমাতে কোনও পরিবর্তন প্রয়োজন এবং আমি এটি পছন্দ করি :)
মাইক ক্রিস্টেনসেন

-1

আমি মনে করি এখানে একটি শব্দার্থিক সমস্যা আছে। আমার দৃষ্টিতে, কোনও নির্দিষ্ট মেনু প্রস্তুত করার জন্য কোনও ব্যবহারকারীর কাছে (তবে একটি মাত্র ) প্রিয় রেসিপি থাকতে পারে। (ওপিতে মেনু এবং রেসিপি মিশ্রিত রয়েছে; যদি আমি ভুল হয়: দয়া করে নীচে মেনুআইডি এবং রেসিপিআইডি বিনিময় করুন) এর দ্বারা বোঝা যায় যে {ব্যবহারকারী, মেনু this এই টেবিলের একটি অনন্য কী হওয়া উচিত। এবং এটি ঠিক একটি রেসিপি নির্দেশ করা উচিত । যদি ব্যবহারকারীটির কাছে এই নির্দিষ্ট মেনুর জন্য পছন্দসই রেসিপি না থাকে তবে এই {ব্যবহারকারীর জন্য কোনও সারি থাকা উচিত নয় , মেনু} কী জুটি। এছাড়াও: সারোগেট কী (FAVouRiteId) অতিমাত্রায়: যৌগিক প্রাথমিক কীগুলি রিলেশনাল-ম্যাপিং টেবিলগুলির জন্য পুরোপুরি বৈধ।

এটি হ্রাস টেবিল সংজ্ঞা হতে পারে:

CREATE TABLE Favorites
( UserId uuid NOT NULL REFERENCES users(id)
, MenuId uuid NOT NULL REFERENCES menus(id)
, RecipeId uuid NOT NULL REFERENCES recipes(id)
, PRIMARY KEY (UserId, MenuId)
);

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

1
যেমনটি আমি বলেছি: এটি শব্দার্থবিজ্ঞানের সমস্ত বিষয়। (আমি খাবারের কথা ভেবেছিলাম, স্পষ্টতই) একটি প্রিয় "যা কোনও মেনুর অন্তর্ভুক্ত নয়" থাকা আমার কাছে বোধগম্য নয়। আইএমএইচও, আপনি এমন কোনও কিছুর পক্ষে পক্ষে রাখতে পারবেন না।
ওয়াইল্ডপ্লাজার

দেখে মনে হচ্ছে কিছু ডিবি নরমালাইজেশন সাহায্য করতে পারে। একটি দ্বিতীয় সারণী তৈরি করুন যা মেনুগুলির সাথে রেসিপিগুলি সম্পর্কিত (বা না)। যদিও এটি সমস্যাটিকে সাধারণীকরণ করে এবং একাধিক মেনুর জন্য মঞ্জুরি দেয় যা কোনও রেসিপি অংশ হতে পারে। নির্বিশেষে, প্রশ্নটি পোস্টগ্রিজ এসকিউএল-এর অনন্য সূচী সম্পর্কে ছিল। ধন্যবাদ।
ক্রিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.