สมมติว่าฉันมีสารบัญ
CREATE TABLE items
(
item serial PRIMARY KEY,
...
);
ตอนนี้ฉันต้องการแนะนำแนวคิดของ "การอนุญาต" สำหรับแต่ละรายการ (โปรดทราบว่าฉันไม่ได้พูดถึงสิทธิ์การเข้าถึงฐานข้อมูลที่นี่ แต่สิทธิ์ทางตรรกะทางธุรกิจสำหรับรายการนั้น) แต่ละรายการมีสิทธิ์เริ่มต้นและสิทธิ์ต่อผู้ใช้ที่อาจแทนที่สิทธิ์เริ่มต้น
ฉันพยายามคิดหลายวิธีในการใช้งานและหาวิธีแก้ไขปัญหาต่อไปนี้ แต่ฉันไม่แน่ใจว่าวิธีใดดีที่สุดและเพราะเหตุใด:
1) โซลูชันบูลีน
ใช้คอลัมน์บูลีนสำหรับการอนุญาตแต่ละครั้ง:
CREATE TABLE items
(
item serial PRIMARY KEY,
can_change_description boolean NOT NULL,
can_change_price boolean NOT NULL,
can_delete_item_from_store boolean NOT NULL,
...
);
CREATE TABLE item_per_user_permissions
(
item int NOT NULL REFERENCES items(item),
user int NOT NULL REFERENCES users(user),
PRIMARY KEY(item, user),
can_change_description boolean NOT NULL,
can_change_price boolean NOT NULL,
can_delete_item_from_store boolean NOT NULL,
...
);
ข้อดี : แต่ละสิทธิ์มีชื่อ
ข้อเสีย : มีหลายสิทธิ์ที่เพิ่มจำนวนคอลัมน์อย่างมีนัยสำคัญและคุณต้องกำหนดพวกเขาสองครั้ง (หนึ่งครั้งในแต่ละตาราง)
2) โซลูชั่นจำนวนเต็ม
ใช้จำนวนเต็มและถือว่าเป็นบิตฟิลด์ (เช่นบิต 0 สำหรับcan_change_description
บิต 1 สำหรับcan_change_price
และอื่น ๆ และใช้การดำเนินการระดับบิตเพื่อตั้งค่าหรืออ่านสิทธิ์)
CREATE DOMAIN permissions AS integer;
ข้อดี : เร็วมาก
ข้อเสีย : คุณต้องติดตามว่าบิตใดที่ใช้แทนทั้งสิทธิ์ในฐานข้อมูลและส่วนต่อประสานส่วนหน้า
3) โซลูชัน Bitfield
เช่นเดียวกับ 2) bit(n)
แต่การใช้ ส่วนใหญ่แล้วข้อดีและข้อเสียเดียวกันอาจช้าลงเล็กน้อย
4) โซลูชัน Enum
ใช้ประเภท enum สำหรับการอนุญาต:
CREATE TYPE permission AS ENUM ('can_change_description', 'can_change_price', .....);
จากนั้นสร้างตารางพิเศษสำหรับการอนุญาตเริ่มต้น:
CREATE TABLE item_default_permissions
(
item int NOT NULL REFERENCES items(item),
perm permission NOT NULL,
PRIMARY KEY(item, perm)
);
และเปลี่ยนตารางนิยามต่อผู้ใช้เป็น:
CREATE TABLE item_per_user_permissions
(
item int NOT NULL REFERENCES items(item),
user int NOT NULL REFERENCES users(user),
perm permission NOT NULL,
PRIMARY KEY(item, user, perm)
);
ข้อดี : ง่ายต่อการตั้งชื่อการอนุญาตส่วนบุคคล (คุณไม่ต้องจัดการตำแหน่งบิต)
ข้อเสีย : แม้จะเพิ่งรับสิทธิ์เริ่มต้นก็ต้องเข้าถึงสองตารางเพิ่มเติม: ครั้งแรกตารางสิทธิ์เริ่มต้นและที่สองแคตตาล็อกระบบการจัดเก็บค่า enum
โดยเฉพาะอย่างยิ่งเนื่องจากต้องมีการดึงสิทธิ์เริ่มต้นสำหรับทุกการดูหน้าเดียวของรายการนั้นผลกระทบด้านประสิทธิภาพของตัวเลือกสุดท้ายอาจมีความสำคัญ
5) โซลูชัน Enum Array
เหมือนกับ 4) แต่ใช้อาร์เรย์เพื่อเก็บสิทธิ์ (ค่าเริ่มต้น) ทั้งหมด:
CREATE TYPE permission AS ENUM ('can_change_description', 'can_change_price', .....);
CREATE TABLE items
(
item serial PRIMARY KEY,
granted_permissions permission ARRAY,
...
);
ข้อดี : ง่ายต่อการตั้งชื่อการอนุญาตส่วนบุคคล (คุณไม่ต้องจัดการตำแหน่งบิต)
ข้อเสีย : แบ่งรูปแบบปกติที่ 1 และเป็นบิตที่น่าเกลียด ใช้จำนวนไบต์ที่มากพอในแถวหากจำนวนสิทธิ์มีขนาดใหญ่ (ประมาณ 50)
คุณนึกถึงทางเลือกอื่น ๆ ได้ไหม?
ควรใช้วิธีใดและทำไม
กรุณาหมายเหตุ: นี่เป็นรุ่นล่าสุดของคำถามที่โพสต์ก่อนหน้านี้เมื่อ Stackoverflow
bigint
ฟิลด์ (แต่ละที่ดีสำหรับ 64 บิต) หรือบิตสตริง ฉันเขียนคำตอบที่เกี่ยวข้องสองสามข้อเกี่ยวกับ SO ที่อาจช่วยได้