You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在目标表中通过静态表达式引用字典表条目?

核心需求与问题

我有一个dict表,希望通过字典名称来引用其中的条目,请问这个需求是否可行?我预想的SQL语句示例如下:

-- 'SourceType' 用于限定引用范围
foreign key (tid, 'SourceType', source_type) references dict_entry (tid, dict_code, value)

目前我是通过创建大量独立字典表来实现类似功能的,比如:

create table if not exists source_type
(
    tid           text  not null default public.current_tenant_id() references public.tenant (tid),
    value         text,
    label         text,
    display_order bigint         default nextval('seq_display_order'),
    attributes    jsonb not null default '{}'::jsonb,
    properties    jsonb not null default '{}'::jsonb,
    extensions    jsonb not null default '{}'::jsonb,
    primary key (tid, value)
);

完整上下文

我希望用单个dict表替代大量上述这类独立字典表。

现有实现代码

create table if not exists dict
(
    id           text        not null default 'dict_' || public.gen_ulid() primary key,
    uid          uuid        not null default gen_random_uuid() unique,
    created_at   timestamptz not null default current_timestamp,
    updated_at   timestamptz not null default current_timestamp,
    deleted_at   timestamptz,
    tid          text        not null default public.current_tenant_id() references public.tenant (tid),
    eid          text,

    display_name text        not null,
    description  text,
    code         text        not null default 'D' || to_char(now(), 'YYYYMMDD') || (regexp_match(gen_random_uuid()::text, '([0-9a-f]{6})'))[1],
    value_schema jsonb                default '{
      "type": "string"
    }',
    sequence     bigint      not null default 0,
    system       bool        not null default false,

    attributes   jsonb       not null default '{}',
    properties   jsonb       not null default '{}',
    extensions   jsonb       not null default '{}',
    unique (tid, display_name),
    unique (tid, code)
);

create or replace function er.next_dict_value(in_dict_code text, in_tid tenant.tid%TYPE = current_tenant_id())
    returns jsonb
    language plpgsql
    volatile
as
$$
declare
    out_next dict.sequence%TYPE;
    _schema  dict.value_schema%TYPE;
begin
    if in_dict_code is null then
        raise exception 'Empty sequence'
            using hint = 'check you table definition';
    end if;
    select value_schema into _schema from dict where tid = in_tid and code = in_dict_code;

    -- schema是字符串类型时使用uuid
    if _schema ->> 'type' = 'string' then
        return to_jsonb(('V' || public.gen_ulid()));
    end if;

    -- schema是整数类型时使用自增序列
    if _schema ->> 'type' = 'integer' then
        update dict
        set sequence=sequence + 1,
            updated_at = now()
        where tid = in_tid
          and code = in_dict_code
        returning sequence into out_next;
        if out_next is null
        then
            raise exception 'Empty sequence'
                using hint = 'ensure you dict exists: ' || in_dict_code;
        end if;
        return to_jsonb(out_next);
    end if;
    raise exception 'Empty sequence'
        using hint = 'unknown schema type: ' || in_dict_code;
end;
$$;

create table if not exists dict_entry
(
    id            text        not null default 'dicte_' || public.gen_ulid() primary key,
    uid           uuid        not null default gen_random_uuid() unique,
    created_at    timestamptz not null default current_timestamp,
    updated_at    timestamptz not null default current_timestamp,
    deleted_at    timestamptz,
    tid           text        not null default public.current_tenant_id() references public.tenant (tid),
    eid           text,

    dict_code     text        not null,
    label         text        not null,
    value         jsonb       not null,
    description   text,
    display_order int         not null default nextval('seq_display_order'),
    active        bool        not null default true,
    metadata      jsonb       not null default '{}',

    attributes    jsonb       not null default '{}',
    properties    jsonb       not null default '{}',
    extensions    jsonb       not null default '{}',
    unique (tid, eid),
    unique (tid, dict_code, value),
    foreign key (tid, dict_code) references dict (tid, code) on update cascade on delete cascade
);

待替代的多表实现示例

create table if not exists gender_type
(
    like tpl_dict_type including all
);

insert into gender_type (value, label)
values ('Male', '男'),
       ('Female', '女')
on conflict(tid,value) do update set (label, extensions) = (excluded.label, excluded.extensions);

内容的提问来源于stack exchange,提问作者wener

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:26:15