使用 ROWTYPE 或 RECORD 文字调用 Postgresql 过程
Call a Postgresql procedure with a ROWTYPE or RECORD literal
我正在构建食谱书应用程序。我这样做只是为了练习在 Postgresql 中工作:
postgres=# select version();
version
------------------------------------------------------------------------------------------------------------------
PostgreSQL 12.2 (Debian 12.2-2.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
(1 row)
我有几个表用于存储基于配方的信息;一个与配料表有关:
CREATE TABLE ingredient (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name TEXT NOT NULL,
quantity NUMERIC NOT NULL,
unit TEXT,
display_order INT NOT NULL
);
我正在编写一个名为 save_recipe
的函数,这就是它目前的样子
CREATE OR REPLACE PROCEDURE save_recipe
(
first_name COOK.FIRST_NAME%TYPE,
last_name COOK.LAST_NAME%TYPE,
email COOK.EMAIL%TYPE,
recipe_name RECIPE.NAME%TYPE,
recipe_cook_time RECIPE.COOK_TIME%TYPE,
recipe_preface RECIPE.PREFACE%TYPE,
instructions RECIPE.INSTRUCTIONS%TYPE,
ingred INGREDIENT
)
AS $$
DECLARE
cook_id COOK.ID%TYPE;
recipe_id RECIPE.ID%TYPE;
BEGIN
INSERT INTO cook (first_name, last_name, email)
VALUES (first_name, last_name, email)
RETURNING id INTO cook_id;
INSERT INTO recipe (name, cook_id, created_at, cook_time, instructions, preface)
VALUES (recipe_name, cook_id, now(), recipe_cook_time, instructions, recipe_preface)
RETURNING id INTO recipe_id;
INSERT INTO ingredient (name, quantity, unit, display_order)
VALUES (ingred.name, ingred.quantity, ingred.unit, ingred.display_order);
COMMIT;
RAISE NOTICE 'Cook ID : %', cook_id;
RAISE NOTICE 'Recipe ID : %', recipe_id;
END;
$$
LANGUAGE plpgsql;
但是我在创建成分文字时遇到了问题(如果这是正确的词)。这是我目前所能做的最好的事情:
CALL save_recipe(
first_name => 'Joe',
last_name => 'Fresh',
email => 'joe@loblaws.com',
recipe_name => 'Cherry Pie',
recipe_cook_time => '1 hour',
recipe_preface =>'I love cherry pie.',
instructions => ARRAY['Make.', 'Bake.', 'Eat.'],
ingred => (0, 'Cherry', 20, 'small, pitted', 1)
);
我希望 ingred
成为一个数组,但我更担心的是我需要填充 ingredient.id
即使我在插入过程中忽略了它(因为我想使用Postgres 提供的生成的 ID)。有没有 structure/type 我可以在不需要像这样指定虚拟 ID 的地方使用(最终可以是 ARRAY
类型)。
提前致谢。
将参数声明为 variadic array 类型。使用 unnest()
将数组的元素作为行获取(为便于阅读而简化的函数):
CREATE OR REPLACE PROCEDURE save_recipe
(
first_name text,
last_name text,
email text,
VARIADIC ingred INGREDIENT[]
)
AS $$
DECLARE
cook_id COOK.ID%TYPE;
BEGIN
INSERT INTO cook (first_name, last_name, email)
VALUES (first_name, last_name, email)
RETURNING id INTO cook_id;
INSERT INTO ingredient (name, quantity, unit, display_order)
SELECT i.name, i.quantity, i.unit, i.display_order
FROM unnest(ingred) i;
RAISE NOTICE 'Cook ID : %', cook_id;
END;
$$
LANGUAGE plpgsql;
使用示例:
CALL save_recipe(
first_name => 'Joe',
last_name => 'Fresh',
email => 'joe@loblaws.com',
variadic ingred => array[
'(0, Apple, 2, small, 1)',
'(0, Pear, 5, large, 2)',
'(0, Cherry, 20, "small, pitted", 1)'
]::ingredient[]
);
select *
from ingredient;
id | name | quantity | unit | display_order
----+---------+----------+----------------+---------------
1 | Apple | 2 | small | 1
2 | Pear | 5 | large | 2
3 | Cherry | 20 | small, pitted | 1
(3 rows)
请注意,如果没有命名参数,过程调用可能会简单得多:
CALL save_recipe(
'Joe', 'Fresh', 'joe@loblaws.com',
'(0, Apple, 2, small, 1)',
'(0, Pear, 5, large, 2)',
'(0, Cherry, 20, "small, pitted", 1)'
);
我正在构建食谱书应用程序。我这样做只是为了练习在 Postgresql 中工作:
postgres=# select version();
version
------------------------------------------------------------------------------------------------------------------
PostgreSQL 12.2 (Debian 12.2-2.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
(1 row)
我有几个表用于存储基于配方的信息;一个与配料表有关:
CREATE TABLE ingredient (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name TEXT NOT NULL,
quantity NUMERIC NOT NULL,
unit TEXT,
display_order INT NOT NULL
);
我正在编写一个名为 save_recipe
的函数,这就是它目前的样子
CREATE OR REPLACE PROCEDURE save_recipe
(
first_name COOK.FIRST_NAME%TYPE,
last_name COOK.LAST_NAME%TYPE,
email COOK.EMAIL%TYPE,
recipe_name RECIPE.NAME%TYPE,
recipe_cook_time RECIPE.COOK_TIME%TYPE,
recipe_preface RECIPE.PREFACE%TYPE,
instructions RECIPE.INSTRUCTIONS%TYPE,
ingred INGREDIENT
)
AS $$
DECLARE
cook_id COOK.ID%TYPE;
recipe_id RECIPE.ID%TYPE;
BEGIN
INSERT INTO cook (first_name, last_name, email)
VALUES (first_name, last_name, email)
RETURNING id INTO cook_id;
INSERT INTO recipe (name, cook_id, created_at, cook_time, instructions, preface)
VALUES (recipe_name, cook_id, now(), recipe_cook_time, instructions, recipe_preface)
RETURNING id INTO recipe_id;
INSERT INTO ingredient (name, quantity, unit, display_order)
VALUES (ingred.name, ingred.quantity, ingred.unit, ingred.display_order);
COMMIT;
RAISE NOTICE 'Cook ID : %', cook_id;
RAISE NOTICE 'Recipe ID : %', recipe_id;
END;
$$
LANGUAGE plpgsql;
但是我在创建成分文字时遇到了问题(如果这是正确的词)。这是我目前所能做的最好的事情:
CALL save_recipe(
first_name => 'Joe',
last_name => 'Fresh',
email => 'joe@loblaws.com',
recipe_name => 'Cherry Pie',
recipe_cook_time => '1 hour',
recipe_preface =>'I love cherry pie.',
instructions => ARRAY['Make.', 'Bake.', 'Eat.'],
ingred => (0, 'Cherry', 20, 'small, pitted', 1)
);
我希望 ingred
成为一个数组,但我更担心的是我需要填充 ingredient.id
即使我在插入过程中忽略了它(因为我想使用Postgres 提供的生成的 ID)。有没有 structure/type 我可以在不需要像这样指定虚拟 ID 的地方使用(最终可以是 ARRAY
类型)。
提前致谢。
将参数声明为 variadic array 类型。使用 unnest()
将数组的元素作为行获取(为便于阅读而简化的函数):
CREATE OR REPLACE PROCEDURE save_recipe
(
first_name text,
last_name text,
email text,
VARIADIC ingred INGREDIENT[]
)
AS $$
DECLARE
cook_id COOK.ID%TYPE;
BEGIN
INSERT INTO cook (first_name, last_name, email)
VALUES (first_name, last_name, email)
RETURNING id INTO cook_id;
INSERT INTO ingredient (name, quantity, unit, display_order)
SELECT i.name, i.quantity, i.unit, i.display_order
FROM unnest(ingred) i;
RAISE NOTICE 'Cook ID : %', cook_id;
END;
$$
LANGUAGE plpgsql;
使用示例:
CALL save_recipe(
first_name => 'Joe',
last_name => 'Fresh',
email => 'joe@loblaws.com',
variadic ingred => array[
'(0, Apple, 2, small, 1)',
'(0, Pear, 5, large, 2)',
'(0, Cherry, 20, "small, pitted", 1)'
]::ingredient[]
);
select *
from ingredient;
id | name | quantity | unit | display_order
----+---------+----------+----------------+---------------
1 | Apple | 2 | small | 1
2 | Pear | 5 | large | 2
3 | Cherry | 20 | small, pitted | 1
(3 rows)
请注意,如果没有命名参数,过程调用可能会简单得多:
CALL save_recipe(
'Joe', 'Fresh', 'joe@loblaws.com',
'(0, Apple, 2, small, 1)',
'(0, Pear, 5, large, 2)',
'(0, Cherry, 20, "small, pitted", 1)'
);