كيف يمكنني أن أفعل الوصول التحكم عن طريق جدول SQL؟
-
03-07-2019 - |
سؤال
وأنا أحاول أن إنشاء نظام لمراقبة الدخول.
وهنا جردت أسفل مثال على ما الجدول أحاول التحكم في الوصول إلى يشبه:
things table:
id group_id name
1 1 thing 1
2 1 thing 2
3 1 thing 3
4 1 thing 4
5 2 thing 5
والجدول التحكم في الوصول يبدو مثل هذا:
access table:
user_id type object_id access
1 group 1 50
1 thing 1 10
1 thing 2 100
ويمكن الحصول على منح إما عن طريق تحديد هوية من 'شيء' مباشرة، أو منح لمجموعة كاملة من الاشياء عن طريق تحديد هوية المجموعة. في المثال أعلاه، تم منح المستخدم 1 مستوى الوصول من 50 الى مجموعة 1، التي يجب أن تطبق ما لم تكن هناك أي قواعد أخرى منح وصول أكثر تحديدا إلى شيء الفردية.
وأحتاج استعلام يقوم بإرجاع قائمة من الأشياء (هويات ما يرام فقط) جنبا إلى جنب مع مستوى الوصول لمستخدم معين. وذلك باستخدام المثال أعلاه كنت أريد شيئا من هذا القبيل للمستخدم معرف 1:
desired result:
thing_id access
1 10
2 100
3 50 (things 3 and 4 have no specific access rule,
4 50 so this '50' is from the group rule)
5 (thing 5 has no rules at all, so although I
still want it in the output, there's no access
level for it)
والأقرب أستطيع الخروج مع هذا:
SELECT *
FROM things
LEFT JOIN access ON
user_id = 1
AND (
(access.type = 'group' AND access.object_id = things.group_id)
OR (access.type = 'thing' AND access.object_id = things.id)
)
ولكن هذا يعود صفوف متعددة، عندما أريد واحدة فقط لكل صف في الجدول "الأشياء". أنا لست متأكدا من كيفية ننكب على صف واحد لكل "شيء"، أو كيفية تحديد الأولويات "شيء" قواعد على قواعد "مجموعة".
وإذا كان يساعد، وقاعدة بيانات أنا باستخدام هي كيو.
لا تتردد في ترك التعليق إذا كان هناك أي معلومات لقد غاب.
ويرجع الفضل في ذلك مسبقا!
المحلول
وأنا لا أعرف لهجة بوستجرس SQL، ولكن ربما شيء من هذا القبيل:
select thing.*, coalesce ( ( select access
from access
where userid = 1
and type = 'thing'
and object_id = thing.id
),
( select access
from access
where userid = 1
and type = 'group'
and object_id = thing.group_id
)
)
from things
وبالمناسبة، أنا لا أحب التصميم. وأود أن تفضل الجدول الوصول إلى تقسيمها إلى قسمين:
thing_access (user_id, thing_id, access)
group_access (user_id, group_id, access)
وبلدي الاستعلام ثم يصبح:
select thing.*, coalesce ( ( select access
from thing_access
where userid = 1
and thing_id = thing.id
),
( select access
from group_access
where userid = 1
and group_id = thing.group_id
)
)
from things
وأنا أفضل ذلك لأن المفاتيح الخارجية ويمكن الآن أن تستخدم في الجداول الوصول.
نصائح أخرى
ولقد قرأت للتو ورقة الليلة الماضية في هذا الشأن. لديه بعض الأفكار حول كيفية القيام بذلك. إذا كنت لا تستطيع استخدام وصلة على لقب حاول استخدام الباحث العلمي من Google على rel="nofollow الحد الإفصاح في أبقراط قواعد البيانات.
وفي حين أن هناك عدة أجوبة جيدة، فإن الأكثر كفاءة ربما يكون شيئا مثل هذا:
SELECT things.id, things.group_id, things.name, max(access)
FROM things
LEFT JOIN access ON
user_id = 1
AND (
(access.type = 'group' AND access.object_id = things.group_id)
OR (access.type = 'thing' AND access.object_id = things.id)
)
group by things.id, things.group_id, things.name
والذي يستخدم ببساطة بإضافة تلخيص لك الاستعلام للحصول على ما كنت أبحث عنه.
وتوني:
وليس حلا سيئا، وأنا أحب ذلك، ويبدو أن العمل. وإليك طلبك بعد التغيير والتبديل البسيط:
SELECT
things.*,
coalesce (
( SELECT access
FROM access
WHERE user_id = 1
AND type = 'thing'
AND object_id = things.id
),
( SELECT access
FROM access
WHERE user_id = 1
AND type = 'group'
AND object_id = things.group_id
)
) AS access
FROM things;
والنتائج تبدو الصحيح:
id | group_id | name | access
----+----------+---------+--------
1 | 1 | thing 1 | 10
2 | 1 | thing 2 | 100
3 | 1 | thing 3 | 50
4 | 1 | thing 4 | 50
5 | 2 | thing 5 |
وأفعل <م> تماما م> اتخاذ نقطة عن أنه لم يكن مخطط مثالي. ومع ذلك، وأنا عالقة معها إلى حد ما.
وجوزيف:
والحل الخاص بك هو تشبه الى حد بعيد الاشياء كنت ألعب معها، وبلدي الغرائز (مثل هم) يقول لي أنه ينبغي أن يكون من الممكن أن تفعل ذلك بهذه الطريقة. لسوء الحظ أنها لا تنتج النتائج الصحيحة تماما:
id | group_id | name | max
----+----------+---------+-----
1 | 1 | thing 1 | 50
2 | 1 | thing 2 | 100
3 | 1 | thing 3 | 50
4 | 1 | thing 4 | 50
5 | 2 | thing 5 |
لقد اتخذت مستوى الوصول ل"الشيء 1" القيمة وصول "مجموعة" أعلى، بدلا من "شيء" القيمة وصول أكثر تحديدا من 10، وهو ما أنا بعد. أنا لا أعتقد أن هناك وسيلة لتحديد ذلك ضمن GROUP BY
، ولكن إذا كان أي شخص لديه أي اقتراحات أنا أكثر من سعيدة لإثبات غير صحيحة حول هذه النقطة.