How to store site wide settings in a database?

前端 未结 9 2878
时光说笑
时光说笑 2021-02-19 10:08

I\'m debating three different approaches to to storing sitewide settings for a web application.

A key/value pair lookup table, each key represents a setting.

    <
9条回答
  •  南旧
    南旧 (楼主)
    2021-02-19 10:33

    Following Mike's idea, here is a script to create a table to save pairs of key/value. This integrates a mechanism (constraint) to check that the values is ok with respect to min/max/not null, and it also automatically creates a function fn_setting_XXXX() to quickly get the value of the corresponding setting (correctly casted).

    CREATE TABLE settings
    (
       id serial,
       name varchar(30),
       type regtype,
       value text,
       v_min double precision,
       v_max double precision,
       v_not_null boolean default true,
       description text,
       constraint settings_pkey primary key(id),
       constraint setting_unique unique(name),
       constraint setting_type check (type in ('boolean'::regtype, 'integer'::regtype, 'double precision'::regtype, 'text'::regtype))
    );
    
    /* constraint to check value */
    
    ALTER TABLE settings
      ADD CONSTRAINT check_value
      CHECK (
            case when type in ('integer'::regtype,'double precision'::regtype) then
                case when v_max is not null and v_min is not null then
                    value::double precision <= v_max and value::double precision >= v_min
                when v_max is not null then
                    value::double precision <= v_max 
                when v_min is not null then
                    value::double precision >= v_min
                else
                    true
                end
            else
                true
            end
        and
            case when v_not_null then
                value is not null
            else
                true
            end
        );
    
    /* trigger to create get function for quick access to the setting */
    
    CREATE OR REPLACE FUNCTION ft_setting_create_fn_get() RETURNS TRIGGER AS
        $BODY$
        BEGIN
            IF TG_OP <> 'INSERT' THEN
                EXECUTE format($$DROP FUNCTION IF EXISTS fn_setting_%1$I();$$, OLD.name);
            END IF;
            IF TG_OP <> 'DELETE' THEN
                EXECUTE format($$
                    CREATE FUNCTION fn_setting_%1$I() RETURNS %2$s AS
                        'SELECT value::%2$s from settings where name = ''%1$I''' language sql
                $$, NEW.name, NEW.type::regtype );
            END IF;
            RETURN NEW;
        END;
        $BODY$
        LANGUAGE plpgsql;
    
    
    CREATE TRIGGER tr_setting_create_fn_get_insert
        BEFORE INSERT OR DELETE ON settings
        FOR EACH ROW
        EXECUTE PROCEDURE ft_setting_create_fn_get();
    COMMENT ON TRIGGER tr_setting_create_fn_get_insert ON settings IS 'Trigger: automatically create get function for inserted settings';
    
    CREATE TRIGGER tr_setting_create_fn_get_update
        BEFORE UPDATE OF type, name ON settings
        FOR EACH ROW
        WHEN ( NEW.type <> OLD.type OR  OLD.name <> NEW.name)
        EXECUTE PROCEDURE ft_setting_create_fn_get();
    COMMENT ON TRIGGER tr_setting_create_fn_get_update ON settings IS 'Trigger: automatically create get function for inserted settings';
    

提交回复
热议问题