过去,我被告知(在这个站点上)我应该规范化数据库中的值 - 使用查找表而不是使用直接(字符串)键。
我很困惑为什么这很好,以至于有几个人推荐了这个。仅仅是为了内存消耗吗?但是在我的情况下(如下所述)那是多少?
考虑我有一个网站的字典数据库:
CREATE TABLE dictionary
(
id serial NOT NULL,
key text NOT NULL,
language text NOT NULL,
value text,
PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)
然后插入会发生如下:
INSERT INTO public.dictionary VALUES
('yes_button', 'en', 'yes'), ('yes_button', 'nl', 'ja')
Run Code Online (Sandbox Code Playgroud)
或者,我会使用“en-us”来代替“en”。现在我被告知要“规范化”数据库——这意味着有一个查找表来绑定语言的字符串表示('en'、'nl' 到一个值):
CREATE TABLE languages
(
id serial NOT NULL,
language text
)
CREATE TABLE dictionary
(
id serial NOT NULL,
key text NOT NULL,
language integer NOT NULL,
value text,
PRIMARY KEY (id),
FOREIGN KEY (language)
REFERENCES public.languages (id)
)
Run Code Online (Sandbox Code Playgroud)
然而,这会增加相当多的复杂性,因为插入不再简单——它需要检查后端的外部表,或者使用一些更复杂的 …
在我们当前的应用程序中,我们基本上将为每个字段提供称为“翻译”的东西。所以一个表最初是这样的:
CREATE TABLE organisation (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL DEFAULT '',
)
Run Code Online (Sandbox Code Playgroud)
但是,该名称现在将取决于语言。
基本的解决方案是不再将名称字段存储在组织表中,而是存储在“organisation_language”表中:
CREATE TABLE organisation (
id SERIAL PRIMARY,
);
CREATE TABLE organisation_language
(
id SERIAL PRIMARY KEY,
organisation INTEGER NOT NULL,
field_name TEXT NOT NULL,
field_language TEXT NOT NULL,
field_translation TEXT NOT NULL DEFAULT '',
FOREIGN KEY (organisation)
REFERENCES public.organisation (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
NOT VALID
);
Run Code Online (Sandbox Code Playgroud)
(是的,我故意忽略了我可以为语言键添加查找表en-US并参考它)。
但是,现在我不能再“保证”name定义每个字段(如)。当然,代码可以确保它确实如此,但那是另一层。它还增加了相当多的复杂性,因为不再容易看到哪些字段甚至属于数据模型。或者为某个组织提供什么翻译。
如果我查看 JSON,我实际上会“喜欢”我的后端在请求“来自组织 1 …
我有一种感觉,这肯定被问过多次,但我只是找不到解决方案,甚至可能因为难以解释而提出问题。
我们都知道内连接基本上给出了两个表的“交集”。因此多个内连接给出了所有表的交集。但是,我希望获得一个内部连接,该连接获得表 B 与 A或表 C 与 A的交集。
对于获得所有组织的请求,我要么是主持人,要么是管理员。
SELECT *
FROM organization
INNER JOIN moderator_organization
ON organization.id = moderator_organization.organization AND moderator_organization.user = 10
INNER JOIN admin_organization
ON organization.id = admin_organization.organization AND admin_organization.user = 10
Run Code Online (Sandbox Code Playgroud)
然而,上面只会选择用户(ID 为 10)既是管理员又是组织者的组织,而不是其中任何一个都为真的组织。要在图表中可视化,我想:
红色区域是我想要请求的地方。