所以这是我的更新功能:
CREATE OR REPLACE FUNCTION api.book_update(
in_id BIGINT,
in_category VARCHAR,
in_published DATE,
in_author VARCHAR,
in_name VARCHAR
) RETURNS VOID AS $$
DECLARE
in_category_id BIGINT;
tmp BIGINT;
BEGIN
SELECT COUNT(*) INTO tmp FROM schemas.book;
IF (NOT (tmp <> 0)) THEN
RETURN;
END IF;
SELECT
category_id
INTO
in_category_id
FROM
schemas.book
WHERE
id = in_id;
SELECT category_id INTO tmp FROM schemas.category WHERE name = in_category;
IF (NOT FOUND)
THEN
SELECT nextval('schemas.category_category_id_seq') INTO tmp;
UPDATE schemas.book
SET
category_id = tmp,
published = in_published,
author = in_author,
name = in_name
WHERE
id = in_id;
INSERT INTO schemas.category (
category_id,
name
) VALUES (
tmp,
in_category
);
ELSE
SELECT category_id INTO tmp FROM schemas.category WHERE name = in_category;
UPDATE schemas.book
SET
category_id = tmp,
published = in_published,
author = in_author,
name = in_name
WHERE
id = in_id;
END IF;
END;
$$
LANGUAGE plpgsql;
终端输出:
pgdb=# select * from api.book_add('aaa', '10-12-13', 'Aauthor','Name');
book_add
----------
(1 row)
pgdb=# select * from api.book_list;
id | category | published | author | name
----+----------+------------+---------+------
1 | aaa | 2013-10-12 | Aauthor | Name
(1 row)
pgdb=# select * from api.book_update(1, 'bbb', '10-12-13', 'Aauthor','Name');
ERROR: insert or update on table "category" violates foreign key constraint "category_category_id_fkey"
DETAIL: Key (category_id)=(2) is not present in table "book".
CONTEXT: SQL statement "INSERT INTO schemas.category (
category_id,
name
) VALUES (
tmp,
in_category
)"
PL/pgSQL function "book_update" line 31 at SQL statement
pgdb=#
为什么它不存在,当我在“book”中将category_id更新为tmp并且之后将此tmp插入“category”表
这是完整的架构script
对它的建议非常感谢,因为我没有
答案 0 :(得分:2)
通常情况下,一本书应该引用一个类别而不是反之亦然。书籍与类别之间存在N :: 1的关系;两本书可以指同一类别。
DROP SCHEMA IF EXISTS tmpschemas CASCADE;
CREATE SCHEMA tmpschemas;
CREATE TABLE tmpschemas.category
( category_id BIGSERIAL PRIMARY KEY
, catname VARCHAR NOT NULL
, UNIQUE(catname)
, CHECK (catname <> '')
);
CREATE TABLE tmpschemas.book
( id BIGSERIAL PRIMARY KEY
, category_id BIGINT NOT NULL REFERENCES tmpschemas.category(category_id) -- ON DELETE CASCADE ON UPDATE RESTRICT
, published DATE NOT NULL
, author VARCHAR NOT NULL
, bookname VARCHAR NOT NULL
, UNIQUE(category_id, published, author, bookname)
, CHECK (TEXT(published) <> '')
, CHECK (author <> '')
, CHECK (bookname <> '')
);
注意我删除了级联内容,我假设类别相当稳定(无论如何谁想要更新串行列)删除级联会更加棘手;我不认为你想扔掉所有关于园艺的书籍,只是因为园艺类别不再存在。类别永远不会被删除。
注意:如果您希望某本书能够属于多个类别,则应使用N :: M联结表。
更新:缩减功能:
CREATE OR REPLACE FUNCTION tmpapi.book_add(
in_catname VARCHAR,
in_published DATE,
in_author VARCHAR,
in_bookname VARCHAR
) RETURNS VOID AS $$
BEGIN
INSERT INTO tmpschemas.category(catname)
SELECT in_catname
WHERE NOT EXISTS (
SELECT *
FROM tmpschemas.category nx
WHERE nx.catname = in_catname
);
INSERT INTO tmpschemas.book ( category_id, published, author, bookname)
SELECT cc.category_id
, in_published,in_author, in_bookname
FROM tmpschemas.category cc
WHERE cc.catname = in_catname
;
END;
$$
LANGUAGE plpgsql;
SELECT tmpapi.book_add('gardening', '2013-01-06' , 'Maggie Thatcher' , 'Destructing flowers Thoroughly' );
SELECT tmpapi.book_add('gardening', '1980-05-26' , 'Umberto Eco' , 'The name of the rose' );
SELECT * FROM tmpschemas.book;
结果:
id | category_id | published | author | bookname
----+-------------+------------+-----------------+--------------------------------
1 | 1 | 2013-01-06 | Maggie Thatcher | Destructing flowers Thoroughly
2 | 1 | 1980-05-26 | Umberto Eco | The name of the rose
(2 rows)
正如您所看到的,这两本书都引用了相同的category_id。
UPDATE2:这是更新功能:
CREATE OR REPLACE FUNCTION tmpapi.book_update(
in_id BIGINT,
in_catname VARCHAR,
in_published DATE,
in_author VARCHAR,
in_bookname VARCHAR
) RETURNS VOID AS $$
BEGIN
INSERT INTO tmpschemas.category(catname)
SELECT in_catname
WHERE NOT EXISTS (
SELECT *
FROM tmpschemas.category nx
WHERE nx.catname = in_catname
)
-- avoid inserting a category
-- if the book to be updated does not exist
AND EXISTS (
SELECT * FROM tmpschemas.book bk
WHERE bk.id = in_id
)
;
UPDATE tmpschemas.book bk
SET category_id = cc.category_id
, published = in_published
, author = in_author
, bookname = in_bookname
FROM tmpschemas.category cc
WHERE cc.catname = in_catname
AND bk.id = in_id
;
END;
$$
LANGUAGE plpgsql;
SELECT tmpapi.book_update(1, 'politics', '2013-01-06' , 'Maggie Thatcher' , 'Destructing flowers Thoroughly' );
SELECT * FROM tmpschemas.book;
结果:
CREATE FUNCTION
book_update
-------------
(1 row)
id | category_id | published | author | bookname
----+-------------+------------+-----------------+--------------------------------
2 | 1 | 1980-05-26 | Umberto Eco | The name of the rose
1 | 2 | 2013-01-06 | Maggie Thatcher | Destructing flowers Thoroughly
(2 rows)
CREATE VIEW
id | category | published | author | bookname
----+-----------+------------+-----------------+--------------------------------
2 | gardening | 1980-05-26 | Umberto Eco | The name of the rose
1 | politics | 2013-01-06 | Maggie Thatcher | Destructing flowers Thoroughly
(2 rows)