দুটি অপ্রয়োজনীয় কলামের একটিতে মান হওয়া দরকার


10

না-ব্যাখ্যা প্রশ্ন:

যাইহোক 2 টি নাল মানের সীমাবদ্ধতা আছে যাতে সর্বদা 1 টির মান হওয়া দরকার? উদাহরণস্বরূপ দুটি তারিখের কলাম দুটি নাল তবে কমপক্ষে 1 থাকা যার একটি মান হওয়া দরকার

সমস্যার বিবরণ:

ধরা যাক আমার কাছে টেবিল রয়েছে ব্যয় বলে

এবং 2 তারিখ রয়েছে:

উপস্থাপনা_প্রেম_পরিচালনা_ তারিখ তারিখ নূলেবল ব্যয়_প্রেমী_ তারিখ তারিখ নূলেবল

এই 2 টি কলামের যুক্তিটি নিম্নলিখিত:

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

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

আমি জানি আমার 2 টি সমান টেবিল থাকতে পারে যা প্রিভিশন_এক্সপেন্স এবং কনফার্মড_এক্সপেনস বলা হয় তবে ঠিক তেমন শোনায় না তাই আমার কাছে একই টেবিলে আছে, ২ টি তারিখ, অবনমিত, তবে আমি বাধা বা কিছু চাই যাতে সর্বদা প্রয়োজন হয়।

আরও একটি সম্ভাব্য কৌশল রয়েছে:

পেমেন্ট_ডেট তারিখটি নোট নয়_প্রেভিশন_ডেটটি বাতিল নয়

সুতরাং, এক্ষেত্রে, তারিখটি অগ্রগতির জন্য বুলের মান হবে 1, অন্যথায় 0 হবে No নাল মান নেই, সব ভাল। তা ছাড়া আমি প্রথমে যখন আমার পূর্ববর্তী তারিখ থাকে তখন আমি দুটি মান সংরক্ষণ করার বিকল্পটি চাই এবং তার পরে (ব্যয়টি দু'দিন পরে বলা হয়) সেই ব্যয়ের জন্য একটি নিশ্চিত তারিখ রাখি, কৌশল 2 এর সাথে আমার সেই বিকল্প থাকবে না।

আমি কি ডাটাবেস ডিজাইনে সবকিছু ভুল করছি? : ডি

উত্তর:


10

জেডি শমিটের উত্তরের একটি সংস্করণ, তবে অতিরিক্ত কলামের বিশ্রীতা ছাড়াই:

CREATE TABLE foo (
  FieldA INT,
  FieldB INT
);

DELIMITER //
CREATE TRIGGER InsertFieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
  IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
  END IF;
END//
CREATE TRIGGER UpdateFieldABNotNull BEFORE UPDATE ON foo
FOR EACH ROW BEGIN
  IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
  END IF;
END//
DELIMITER ;

INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
UPDATE foo SET FieldA = NULL; -- gives error

2

আপনি যদি এসকিউএল সার্ভার ব্যবহার করে থাকেন তবে আপনি নিজের টেবিলের মধ্যে স্থির গণিত কলামটি ব্যবহার করে ট্রিগার ব্যবহার এড়াতে পারবেন:

CREATE TABLE Test_Constraint
(
    A DateTime Null,
    B DateTime Null,
    A_and_B AS (CASE WHEN A IS Null AND B IS Null THEN Null ELSE Convert(Binary(1), 1) END) PERSISTED Not Null 
);

A_and_B গণিত কলামে কেস স্টেটমেন্ট একটি নাল মান ফিরিয়ে দিবে যদি ক এবং ক এবং ক উভয় কলাম নাল হয় তবে গণনা কলামে নট নট সীমাবদ্ধতা সন্নিবেশকে আটকাতে একটি ত্রুটি বাড়িয়ে তুলবে। অন্যথায় এটি 1 প্রদান করে।

গণিত কলামটি যেহেতু অবিচল রয়েছে তাই এটি শারীরিকভাবে সারণীতে সংরক্ষণ করা হবে। বাইনারিতে রূপান্তরকরণ এর প্রভাবকে হ্রাস করে, কলামটি দৈর্ঘ্য 1-এর বাইনারি ডেটাটাইপ তৈরি করে।


1
এসকিউএল-সার্ভারে, আপনি CHECKখুব বাধা দিয়ে এটি করতে পারেন । স্থায়ী কলামের প্রয়োজন নেই।
ypercubeᵀᴹ

1
দুর্দান্ত, এটিকে কিছুটা পরিষ্কার বলে মনে হচ্ছে। CREATE TABLE Test_Constraint2 ( A DateTime Null, B DateTime Null, CONSTRAINT A_or_B_Not_Null CHECK (CASE WHEN A IS Null AND B IS Null THEN 0 ELSE 1 END = 1) )
শেন এস্টেল

দুর্দান্ত উত্তর! এইটি অন্যটির চেয়ে বেশি পরিচিত তবে আমি যেহেতু মাইএসকিউএল ব্যবহার করছি, চেক ক্লাসটি পার্স করা হয়েছে কিন্তু মাইএসকিউএলে উপেক্ষা করা হয়েছে যাতে আমি অন্য উত্তরটিকে গ্রহণযোগ্য হিসাবে চিহ্নিত করি। +1
বার্ট ক্যালিক্সটো

1

আমি একটি নিবন্ধ সৌন্দর্য একই জিনিস চাই যে খুঁজে পাওয়া যায় নি এখানে

CREATE TABLE foo (
  FieldA INT,
  FieldB INT,
  FieldA_or_FieldB TINYINT NOT NULL;
);

DELIMITER //
CREATE TRIGGER FieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
  IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
    SET NEW.FieldA_or_FieldB = NULL;
  ELSE
    SET NEW.FieldA_or_FieldB = 1;
  END IF;
END//
DELIMITER ;

INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error

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