在Postgres中约束json键

时间:2014-11-25 19:07:00

标签: json postgresql foreign-keys

我试图在网上寻找这个,但我找不到任何东西。

我在JSON类型的PostgreSQL数据库中有一个列。我在数据库中也有一个表,表示可以在该JSON对象中使用有效的键名。

一个示例是,如果我希望JSON看起来像:{ "key":"value", "key2":"value" }keykey2必须是有效密钥表中的条目才能插入,否则会破坏约束。我在C#项目中使用这些,所以我可能会在代码中进行检查,我也会这样做,但我也想阻止某人通过pgAdmin创建一行。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

在插入时使用触发器,并在数据库处于不一致状态时更新RAISE异常。

CREATE TABLE t1 (
    value json
);
CREATE TABLE t2 (
    valid_key text
);

CREATE FUNCTION check_t1_val_integrity() RETURNS trigger AS $func$
    DECLARE 
       valid_key_count integer;
    BEGIN
        -- Count keys from NEW, not present in t2
       SELECT 
         count(*) 
       FROM 
         json_each(NEW.value) AS v(key,value)
         LEFT JOIN t2 ON t2.valid_key = v.key
       WHERE
         t2.valid_key IS NULL
       INTO 
         valid_key_count;

        -- If we found some key not present in t2, then raise exception
        IF valid_key_count > 0 THEN
            RAISE EXCEPTION 'value not valid';
        END IF;

        RETURN NEW;
    END;
$func$ LANGUAGE plpgsql;

CREATE TRIGGER check_t1_val_integrity_trigger BEFORE INSERT OR UPDATE ON t1
    FOR EACH ROW EXECUTE PROCEDURE check_t1_val_integrity();

这是你的测试:

INSERT INTO t2 (valid_key) VALUES(('a', ('b'));

-- should work well 
INSERT INTO t1 (value) VALUES(
  ('{"a":"a"}'::json, ('{"b":"b"}'::json), ('{"a":"a","b":"b"}'::json)
);

-- should raise exception 
INSERT INTO t1 (value) VALUES(
  ('{"a":"a", "c":"c"}'::json
);