【问题标题】:Postgres function creates but does not executePostgres 函数创建但不执行
【发布时间】:2023-03-23 17:36:01
【问题描述】:

我一直在尝试很多方法来让它发挥作用。据我所知,我已经按照文档进行了操作,但这只是行不通。

各位有 Postgres 经验的人可以推荐一个修复方法吗?我将永远感激不尽。

我使用的是 1.18.1 版(2014 年 6 月 9 日,修订版:REL-1_18_1)

我的创建代码:

set search_path = PsychoProductions;
create or replace function fcn_insert_person(
        -- person table
        prm_role_id int, 
        prm_first_name text, 
        prm_last_name text, 
        prm_organization text, 
        prm_website text, 
        prm_default_billing_method_id text, 
        prm_active boolean, 
        -- address table
        prm_address_type_id int, 
        prm_address text, 
        prm_city text, 
        prm_state text, 
        prm_zip_code text, 
        -- email table
        prm_email_address text, 
        prm_email_type_id int, 
        -- phone table
        prm_phone_number text, 
        prm_phone_type_id int
)
returns void as
$$
set search_patch = PsychoProductions;

insert into PsychoProductions.person (
        role_id,
        first_name,
        last_name,
        organization,
        website,
        default_billing_method_id,
        active
        )
values (
        prm_role_id,
        prm_first_name,
        prm_last_name,
        prm_organization,
        prm_website,
        prm_default_Billing_Method_ID,
        prm_active
        );

insert into PsychoProductions.address (
        person_id,
        address_type_id,
        address,
        city,
        state,
        zip_code
        )
values (
        ( select currval('person_id_seq') ),
        prm_address_type_id,
        prm_address,
        prm_city,
        prm_state,
        prm_zip_code
        );

insert into email (
        person_id,
        email_address,
        email_type_id
        )
values (
        ( select currval('person_id_seq') ),
        prm_email_address,
        prm_email_type_id
        );

insert into phone (
        person_id,
        phone_number,
        phone_type_id
        )
values (
        ( select currval('person_id_seq') ),
        prm_phone_number,
        prm_phone_type_id
        );

-- end;
$$
language sql;

我的执行/调用代码:

set search_path = PsychoProductions;
select fcn_insert_person(
-- NOTE: DO NOT REMOVE QUOTATION MARKS
        -- person table
        3,                      -- customer
        'firstname', 
        'lastname', 
        'organization', 
        'website', 
        2,                      -- net 30
        True,                   -- active
        -- address table
        1,                      -- unique
        'address', 
        'city', 
        'state', 
        'zip', 
        -- email table
        'email', 
        1,                      -- business email 
        -- phone table
        'phone', 
        1                       -- mobile
  );

错误:

ERROR:  function fcn_insert_person(integer, unknown, unknown, unknown, unknown, integer, boolean, integer, unknown, unknown, unknown, unknown, unknown, integer, unknown, integer) does not exist
LINE 2: select fcn_insert_person(
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

********** Error **********

ERROR: function fcn_insert_person(integer, unknown, unknown, unknown, unknown, integer, boolean, integer, unknown, unknown, unknown, unknown, unknown, integer, unknown, integer) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 45

【问题讨论】:

  • 最后,两个答案都很好。 200_success 帮助我意识到我需要进行健全性检查,并且我发现我正在查看的架构设计是 my old version 而不是 my final version。 @PavelStehule 建议显式传递参数(我将开始这样做)以及使错误处理更容易的方法。我接受了 Pavel 的花时间来解释这一切。
  • 1.18.1 看起来像您的 pgAdmin 版本,而不是 Postgres。请修复。您将获得带有 SELECT version() 的 Postgres 版本。

标签: sql postgresql plpgsql


【解决方案1】:

我也遇到过类似的情况 - 具有广泛参数列表的函数。使用所谓的命名参数,您不需要遵守参数的顺序。代码更长,但(我希望)更易读、更健壮。

CREATE TABLE tab(name text, surname text, address text, city text, zip text);

CREATE OR REPLACE FUNCTION public.fx(name text, surname text,
                                     address text, city text, zip text)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
  INSERT INTO tab(name, surname, address, city, zip)
    VALUES(fx.name, fx.surname, fx.address, fx.city, fx.zip);
  -- ... some other logic
END;
$function$

这个函数可以用命名参数表示法调用:

SELECT fx(name := 'Pavel', surname := 'Stehule',
          address := 'Skalice 12', city := 'Benesov', zip := '12');

注意:当我使用错误类型时 - Postgres 报告消息:

postgres=# SELECT fx(name := 'Pavel', surname := 'Stehule', 地址:='Skalice 12',城市:='Benesov',邮编:= 12); 错误:函数 fx(名称:= 未知,姓:= 未知,地址:= 未知,城市:= 未知,邮编:= 整数)不存在 第 1 行:SELECT fx(name := 'Pavel', surname := 'Stehule', ^ 提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。

消息有效,但不干净。这是功能重载支持的成本。还有其他技巧,如何划分长参数列表,以及如何更轻松地找到这些问题。

Postgres 支持自定义类型。你可以使用它:

CREATE TYPE person_type AS (name text, surname text);
CREATE TYPE address_type AS (address text, city text, zip text);

你可以写一个构造函数:

CREATE OR REPLACE FUNCTION public._person_type(name text, surname text)
RETURNS person_type
LANGUAGE plpgsql
AS $function$
DECLARE r person_type;
BEGIN
  r.name = name;
  r.surname = surname;
  RETURN r;
END;
$function$

CREATE OR REPLACE FUNCTION public._address_type(address text, city text, zip text)
RETURNS address_type
LANGUAGE plpgsql
AS $function$ DECLARE r address_type;
BEGIN
  r.address = address;
  r.city = city;
  r.zip = zip;
  RETURN r;
END;
$function$

创建此系统需要做一些工作,并且仅适用于长寿命系统。另一方面,它降低了未来维护工作的成本。

CREATE OR REPLACE FUNCTION public.fx(p person_type, a address_type)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
  INSERT INTO tab(name, surname, address, city, zip)
    VALUES(p.name, p.surname, a.address, a.city, a.zip);
   -- ... some other logic
END;
$function$

现在,更多的符号(符号的组合)是可能的:

postgres=# SELECT fx(_person_type('Pavel','Stehule'),
postgres(#           _address_type('Skalice 12','Benesov', '25601'));
 fx 
----

(1 row)

构造函数有助于错误定位:

postgres=# SELECT fx(_person_type('Pavel','Stehule'), _address_type('Skalice 12','Benesov', 25601)); 错误:函数_address_type(未知,未知,整数)不存在 第 2 行:_address_type('Skalice 12','Benesov', 25601)); ^ 提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。

【讨论】:

    【解决方案2】:

    函数调用中的参数类型与函数定义中的参数类型不匹配。特别是,prm_default_billing_method_id 应该是 text,但您传递给它的是一个整数 2。您可以使用'2'2::textcast(2 as text)

    此外,在您的函数中,您在第 26 行附近有一个错字:set search_patch 而不是 set search_path

    【讨论】:

    • 很好地发现了那个错字!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-10
    • 2011-07-18
    相关资源
    最近更新 更多