Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询在视图的插入触发器中返回了3列_Sql_Postgresql - Fatal编程技术网

Sql 查询在视图的插入触发器中返回了3列

Sql 查询在视图的插入触发器中返回了3列,sql,postgresql,Sql,Postgresql,我有两个表(test\u a和test\u b),一个表(test\u b)基本上是第二个表(test\u a)的扩展,用于某些条目,以主要防止NULL值列。为了保持存储数据的逻辑一致性,我包装了test_b,以表示描述存储实体的完整值范围,因此需要在该视图中插入完整范围的所需信息 table_b_视图和table_a_视图上的insert需要能够返回插入实体的id,因为使用此db的应用程序可能需要保留该id以供内部参考 我目前的(poc)解决方案是: DROP TABLE IF EXISTS

我有两个表(
test\u a
test\u b
),一个表(
test\u b
)基本上是第二个表(
test\u a
)的扩展,用于某些条目,以主要防止
NULL
值列。为了保持存储数据的逻辑一致性,我包装了
test_b
,以表示描述存储实体的完整值范围,因此需要在该视图中插入完整范围的所需信息

table_b_视图
table_a_视图
上的insert需要能够返回插入实体的id,因为使用此db的应用程序可能需要保留该id以供内部参考

我目前的(poc)解决方案是:

DROP TABLE IF EXISTS TEST_A CASCADE;

CREATE TABLE  TEST_A (
       id     SERIAL,
       name   text,
       PRIMARY KEY(id)
);


CREATE OR REPLACE VIEW TEST_A_VIEW AS
SELECT id,
       name
FROM TEST_A;


DROP TABLE IF EXISTS TEST_B CASCADE;

CREATE TABLE TEST_B (
       id    int,
       second_name text,
       PRIMARY KEY(id),
       FOREIGN KEY(id)
       REFERENCES TEST_A(id)
);


CREATE OR REPLACE VIEW TEST_B_VIEW AS
SELECT tb.id, name, second_name
FROM TEST_B as tb JOIN TEST_A as ta
     ON tb.id = ta.id;


CREATE OR REPLACE FUNCTION TEST_B_INSERT_FUNC() RETURNS TRIGGER AS $$
DECLARE
    ident int;
BEGIN
    INSERT INTO TEST_A_VIEW (name) VALUES (NEW.name)
    RETURNING id INTO ident;
    INSERT INTO TEST_B (id, second_name) VALUES (ident, NEW.second_name);
    RETURN ident, NEW.name, NEW.second_name;
END; $$ LANGUAGE PLPGSQL;



CREATE TRIGGER TEST_B_INSERT
INSTEAD OF INSERT ON TEST_B_VIEW
FOR EACH ROW EXECUTE PROCEDURE TEST_B_INSERT_FUNC();
这给了我一个机会

ERROR:  query "SELECT ident, NEW.name, NEW.second_name" returned 3 columns
CONTEXT:  PL/pgSQL function test_b_insert_func() line 8 at RETURN
运行查询时

INSERT INTO TEST_B_VIEW(name, second_name) VALUES ('test', 'test') RETURNING id;
询问

INSERT INTO TEST_A_VIEW (name) VALUES ('test') RETURNING id;
就像一个符咒,并返回给我相应的id

我如何修复我的功能或调整我的方法,以便能够

  • 保持数据的原样表示(即,表_b是表_a的扩展,仅从查看视图的人看不到)

  • 任何一个表上的插入都必须能够返回用于实体的id


  • 解决办法比预期的容易。您必须返回
    NEW
    ,但可以在触发器中“操纵”
    NEW
    的值

    DROP TABLE IF EXISTS TEST_A CASCADE;
    
    CREATE TABLE  TEST_A (
           id     SERIAL,
           name   text,
           PRIMARY KEY(id)
    );
    
    
    CREATE OR REPLACE VIEW TEST_A_VIEW AS
    SELECT id,
           name
    FROM TEST_A;
    
    
    DROP TABLE IF EXISTS TEST_B CASCADE;
    
    CREATE TABLE TEST_B (
           id    int,
           second_name text,
           PRIMARY KEY(id),
           FOREIGN KEY(id)
           REFERENCES TEST_A(id)
    );
    
    
    CREATE OR REPLACE VIEW TEST_B_VIEW AS
    SELECT tb.id, ta.name, tb.second_name
    FROM TEST_B as tb JOIN TEST_A as ta
         ON tb.id = ta.id;
    
    
    CREATE OR REPLACE FUNCTION TEST_B_INSERT_FUNC() RETURNS TRIGGER AS $$
    DECLARE
        ident int;
    BEGIN
        INSERT INTO TEST_A_VIEW (name) VALUES (NEW.name)
        RETURNING id INTO ident;
        INSERT INTO TEST_B (id, second_name) VALUES (ident, NEW.second_name);
        NEW.id = ident;
        RETURN NEW;
    END; $$ LANGUAGE PLPGSQL;
    
    
    
    CREATE TRIGGER TEST_B_INSERT
    INSTEAD OF INSERT ON TEST_B_VIEW
    FOR EACH ROW EXECUTE PROCEDURE TEST_B_INSERT_FUNC();
    
    现在,
    INSERT
    查询按预期工作:

    INSERT INTO TEST_B_VIEW (name, second_name)
           VALUES ('test', 'test')
           RETURNING id;
    
     id 
    ----
      1
    (1 row)
    
    
    INSERT INTO TEST_B_VIEW (name, second_name)
           VALUES ('test', 'test')
           RETURNING id;
     id 
    ----
      2
    (1 row)
    

    谢谢,
    INSERT
    语句返回
    自动生成的主键(在我的例子中是
    id
    ),并从INSERT触发器将其值分配到
    RETURN
    之前的
    NEW
    行,这是我需要的解决方案。