需要外键作为数组

时间:2013-11-26 11:22:28

标签: postgresql

CREATE TABLE test ( id int PRIMARY KEY , name );

CREATE TABLE test1 ( id integer[] REFERENCES test , rollid int );

错误:无法实现外键约束“test3_id_fkey” 详细信息:键列“id”和“id”是不兼容的类型:整数[]和整数。

之后我尝试了另一种方式

CREATE TABLE test1 ( id integer[] , rollid int);

ALTER TABLE test1 ADD CONSTRAINT foreignkeyarray FOREIGN KEY (id) REFERENCES test;

错误:无法实现外键约束“fkarray” 详细信息:键列“id”和“id”是不兼容的类型:整数[]和整数。

所以我尝试创建一个外键数组意味着它说错误。请告诉我任何人?

postgresql版本是9.1。

3 个答案:

答案 0 :(得分:2)

您尝试做的事情根本无法完成。完全没有。不,不,但没有。

创建一个新表test1_test,其中包含两个字段test1_id,test_id。将外键根据需要放在那个上,并使test1的id为整数。

答案 1 :(得分:1)

使用带有外键的数组通常是设计错误的标志。您需要创建具有一对多关系的单独表。

但是从技术上讲,这是可能的。在没有触发器的情况下检查数组值的示例。一种具有重用函数和动态sql的可重用函数。在PostgreSQL 10.5上测试

create schema if not exists test;

CREATE OR REPLACE FUNCTION test.check_foreign_key_array(data anyarray, ref_schema text, ref_table text, ref_column text)
    RETURNS BOOL
    RETURNS NULL ON NULL INPUT
    LANGUAGE plpgsql
AS
$body$
DECLARE
    fake_id text;
    sql text default format($$
            select id::text
            from unnest($1) as x(id)
            where id is not null
              and id not in (select %3$I
                             from %1$I.%2$I
                             where %3$I = any($1))
            limit 1;
        $$, ref_schema, ref_table, ref_column);
BEGIN
    EXECUTE sql USING data INTO fake_id;

    IF (fake_id IS NOT NULL) THEN
        RAISE NOTICE 'Array element value % does not exist in column %.%.%', fake_id, ref_schema, ref_table, ref_column;
        RETURN false;
    END IF;

    RETURN true;
END
$body$;

drop table if exists test.t1, test.t2;

create table test.t1 (
    id integer generated by default as identity primary key
);

create table test.t2 (
    id integer generated by default as identity primary key,
    t1_ids integer[] not null check (test.check_foreign_key_array(t1_ids, 'test', 't1', 'id'))
);

insert into test.t1 (id) values (default), (default), (default); --ok
insert into test.t2 (id, t1_ids) values (default, array[1,2,3]); --ok
insert into test.t2 (id, t1_ids) values (default, array[1,2,3,555]); --error

答案 2 :(得分:0)

如果你能够将test.id中的值放在那里,那么你可以试试这个:

CREATE OR REPLACE FUNCTION test_trigger() RETURNS trigger 
LANGUAGE plpgsql AS $BODY$ 
DECLARE 
val integer; 
BEGIN 
SELECT id INTO val 
  FROM (
       SELECT UNNEST(id) AS id
       FROM test1
       ) AS q
 WHERE id = OLD.id;

IF val IS NULL THEN RETURN OLD;
ELSE 
RAISE 'Integrity Constraint Violation: ID "%" in Test1', val USING ERRCODE = '23000';
    RETURN NULL;
END IF;
END; $BODY$;

-- DROP TRIGGER test_delete_trigger ON test;
CREATE TRIGGER test_delete_trigger BEFORE DELETE OR UPDATE OF id ON test
FOR EACH ROW EXECUTE PROCEDURE test_trigger();