无法选择最佳候选函数。您可能需要在 Postgres 中添加显式类型转换
Could not choose a best candidate function. You might need to add explicit type casts in Postgres
我正在使用以下脚本创建函数
CREATE OR REPLACE FUNCTION public.fninsertreceipttransaction(
accountid1 integer,
customerid1 integer,
receiptid1 integer,
retailerid1 integer,
planid1 integer,
enteredat1 timestamp without time zone,
cardtype1 character varying,
last4digits1 integer,
receiptnumber1 character varying,
totalreceiptspend1 double precision,
transactiondate1 timestamp without time zone,
storeid1 integer,
title1 character varying,
message1 character varying,
enteredby1 character varying)
RETURNS typcounter
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
declare
counter typcounter;
planId1 int;
cardid1 int;
spendtargetmax1 double precision;
begin
-- insert receipt data
update tblreceipts
set
ReceiptIssuedAt = transactiondate1,
IsDownloaded = 't',
IsProcessed = 't',
IsVerified1 = 't',
IsVerified2 = 't',
DownloadedAt = current_timestamp,
ProcessedAt = current_timestamp,
VerifiedAt1 = current_timestamp,
VerifiedAt2 = current_timestamp,
DownloadedBy = 'user1',
ProcessedBy = 'user1',
VerifiedBy1 = 'user1',
VerifiedBy2 = 'user1'
where accountId = accountId1 and receiptId = receiptId1;
-- Check if there is active plan
-- when changing plan status, update actualCompletion date
-- Also update EOD process to include receipts
-- this should change depending on plan start and end condition
-- add transaction
select cardid into cardid1 from TblAccountCards
where accountid=accountid1
and cardtype=cardtype1
and last4digits=last4digits1;
update TblTransactions
set
RetailerId = retailerId1,
StoreId = storeid1,
TransactionAt = transactiondate1,
EnteredAt = enteredat1,
UpdatedAt = current_timestamp,
Subtotal = totalreceiptspend1,
CardId = cardid1
where accountId = accountId1 and receiptId = receiptId1;
-- roll up transactions to plan spent
update tblcustomerplans
set currentAmountSpent = (select sum(subtotal) from TblTransactions where
accountId = accountId1 and planId = planId1)
where
accountId = accountId1
and customerId = customerId1;
select spendtargetmax into spendtargetmax1 from tblcustomerplans
where accountid=accountid1
and customerid=customerid1
and planid=planid1;
update tblcustomerplans
set status = 'MarkComplete'
where
accountId = accountId1
and customerId = customerId1
and planId = planId1
and currentamountspent >= spendtargetmax1;
select cast(1 as bigint) into counter;
return counter;
end
$BODY$;
并使用以下查询执行函数
DO $$ BEGIN
PERFORM fninsertreceipttransaction(31, 24, 56, 10001, 53, '2018-11-16 20:03:28', 'Mastercard', '3434', '203', 200, '2018-11-17 00:00:00', 1,
'Receipt Trnasaction', 'Transaction Successfully Processed', 'Admin');
END $$;
获取错误:
ERROR: function fninsertreceipttransaction(integer, integer, integer,
integer, integer, unknown, unknown, unknown, unknown, integer,
unknown, integer, unknown, unknown, unknown) is not unique
我还使用静态数据回溯了所有查询
--------------------------------
update tblreceipts
set
ReceiptIssuedAt = '2018-11-17 00:00:00',
IsDownloaded = 't',
IsProcessed = 't',
IsVerified1 = 't',
IsVerified2 = 't',
DownloadedAt = current_timestamp,
ProcessedAt = current_timestamp,
VerifiedAt1 = current_timestamp,
VerifiedAt2 = current_timestamp,
DownloadedBy = 'user1',
ProcessedBy = 'user1',
VerifiedBy1 = 'user1',
VerifiedBy2 = 'user1'
where accountId = 31 and receiptId = 53;
------------------------------------
select cardid from TblAccountCards
where accountid=31
and cardtype='Mastercard'
and last4digits=3434;
---------------------------------------
update TblTransactions
set
RetailerId = 10001,
StoreId = 1,
TransactionAt = '2018-11-17 00:00:00',
EnteredAt = '2018-11-16 20:03:28',
UpdatedAt = current_timestamp,
Subtotal = 200,
CardId = 1
where accountId = 31 and receiptId = 53;
--------------------------------------------
update tblcustomerplans
set currentAmountSpent = (select sum(subtotal) from TblTransactions where
accountId = 31 and planId = 53)
where
accountId = 31 and customerId = 24;
------------------------------------------------------------------------
select spendtargetmax from tblcustomerplans
where accountid=31 and customerid=24 and planid=53;
--------------------------------
update tblcustomerplans
set status = 'MarkComplete'
where
accountId = 31
and customerId = 24
and planId = 53
and currentamountspent >= 550;
但不知道为什么问题会出现在执行函数时
发生这种情况是因为您已经创建了两个或更多函数,其名称为 fninsertreceipttransaction
且参数数量与执行期间传递的参数数量相同,而 Postgres 无法确定应调用哪个函数。
为了说明,让我们创建 2 个函数。
函数1
knayak= CREATE FUNCTION myfunction(p TIMESTAMP)
knayak- RETURNS BOOLEAN AS $$
knayak$ BEGIN
knayak$ RETURN true;
knayak$ END;
knayak$ $$ LANGUAGE plpgsql;
CREATE FUNCTION
函数2
knayak=
knayak=
knayak= CREATE FUNCTION myfunction(p ) --unknown type p
knayak- RETURNS INTEGER AS $$
knayak$ BEGIN
knayak$ RETURN 1;
knayak$ END;
knayak$ $$ LANGUAGE plpgsql;
CREATE FUNCTION
现在尝试通过传递一个字符串来执行函数
knayak= DO $$
knayak$ BEGIN
knayak$ PERFORM myfunction('2018-11-16 20:03:28');
knayak$ END$$;
我收到此错误是因为 Postgres 无法根据我的论点在两者之间做出决定。
ERROR: function myfunction(unknown) is not unique LINE 1: SELECT
myfunction('2018-11-16 20:03:28')
^ HINT: Could not choose a best candidate function. You might need to add explicit type casts. QUERY: SELECT
myfunction('2018-11-16 20:03:28') CONTEXT: PL/pgSQL function
inline_code_block line 3 at PERFORM
现在,如何知道存在哪些函数?
如果您正在使用 psql
命令提示符,运行 这个简单的命令。
knayak=# \df myfunction
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+------------+------------------+-------------------------------+--------
public | myfunction | integer | p | normal
public | myfunction | boolean | p timestamp without time zone | normal
(2 rows)
您可以看到存在两个具有不同参数的函数。
如果您正在使用 PgAdmin,运行此查询应该会给您相同的结果。
SELECT n.nspname as "Schema",
p.proname as "Name",
pg_catalog.pg_get_function_result(p.oid) as "Result data type",
pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
CASE
WHEN p.proisagg THEN 'agg'
WHEN p.proiswindow THEN 'window'
WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
ELSE 'normal'
END as "Type"
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE p.proname OPERATOR(pg_catalog.~) '^(myfunction)$'
AND pg_catalog.pg_function_is_visible(p.oid)
ORDER BY 1, 2, 4;
你应该如何删除其中一个功能?好吧,如果您确定只应使用一个函数并且您拥有它的创建函数脚本,请删除所有并重新创建它。
您不能简单地发出 DROP function <functionname>
,这在这种情况下不起作用。您必须指定参数签名。
knayak=# DROP function myfunction; --Doesn't work
ERROR: function name "myfunction" is not unique
HINT: Specify the argument list to select the function unambiguously.
这些语句有效。
knayak=#
knayak=# DROP function myfunction(p);
DROP FUNCTION
knayak=# DROP function myfunction(timestamp);
DROP FUNCTION
删除后,重新运行 create function
脚本一次。它应该执行得很好。
我正在使用以下脚本创建函数
CREATE OR REPLACE FUNCTION public.fninsertreceipttransaction(
accountid1 integer,
customerid1 integer,
receiptid1 integer,
retailerid1 integer,
planid1 integer,
enteredat1 timestamp without time zone,
cardtype1 character varying,
last4digits1 integer,
receiptnumber1 character varying,
totalreceiptspend1 double precision,
transactiondate1 timestamp without time zone,
storeid1 integer,
title1 character varying,
message1 character varying,
enteredby1 character varying)
RETURNS typcounter
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
declare
counter typcounter;
planId1 int;
cardid1 int;
spendtargetmax1 double precision;
begin
-- insert receipt data
update tblreceipts
set
ReceiptIssuedAt = transactiondate1,
IsDownloaded = 't',
IsProcessed = 't',
IsVerified1 = 't',
IsVerified2 = 't',
DownloadedAt = current_timestamp,
ProcessedAt = current_timestamp,
VerifiedAt1 = current_timestamp,
VerifiedAt2 = current_timestamp,
DownloadedBy = 'user1',
ProcessedBy = 'user1',
VerifiedBy1 = 'user1',
VerifiedBy2 = 'user1'
where accountId = accountId1 and receiptId = receiptId1;
-- Check if there is active plan
-- when changing plan status, update actualCompletion date
-- Also update EOD process to include receipts
-- this should change depending on plan start and end condition
-- add transaction
select cardid into cardid1 from TblAccountCards
where accountid=accountid1
and cardtype=cardtype1
and last4digits=last4digits1;
update TblTransactions
set
RetailerId = retailerId1,
StoreId = storeid1,
TransactionAt = transactiondate1,
EnteredAt = enteredat1,
UpdatedAt = current_timestamp,
Subtotal = totalreceiptspend1,
CardId = cardid1
where accountId = accountId1 and receiptId = receiptId1;
-- roll up transactions to plan spent
update tblcustomerplans
set currentAmountSpent = (select sum(subtotal) from TblTransactions where
accountId = accountId1 and planId = planId1)
where
accountId = accountId1
and customerId = customerId1;
select spendtargetmax into spendtargetmax1 from tblcustomerplans
where accountid=accountid1
and customerid=customerid1
and planid=planid1;
update tblcustomerplans
set status = 'MarkComplete'
where
accountId = accountId1
and customerId = customerId1
and planId = planId1
and currentamountspent >= spendtargetmax1;
select cast(1 as bigint) into counter;
return counter;
end
$BODY$;
并使用以下查询执行函数
DO $$ BEGIN
PERFORM fninsertreceipttransaction(31, 24, 56, 10001, 53, '2018-11-16 20:03:28', 'Mastercard', '3434', '203', 200, '2018-11-17 00:00:00', 1,
'Receipt Trnasaction', 'Transaction Successfully Processed', 'Admin');
END $$;
获取错误:
ERROR: function fninsertreceipttransaction(integer, integer, integer, integer, integer, unknown, unknown, unknown, unknown, integer, unknown, integer, unknown, unknown, unknown) is not unique
我还使用静态数据回溯了所有查询
--------------------------------
update tblreceipts
set
ReceiptIssuedAt = '2018-11-17 00:00:00',
IsDownloaded = 't',
IsProcessed = 't',
IsVerified1 = 't',
IsVerified2 = 't',
DownloadedAt = current_timestamp,
ProcessedAt = current_timestamp,
VerifiedAt1 = current_timestamp,
VerifiedAt2 = current_timestamp,
DownloadedBy = 'user1',
ProcessedBy = 'user1',
VerifiedBy1 = 'user1',
VerifiedBy2 = 'user1'
where accountId = 31 and receiptId = 53;
------------------------------------
select cardid from TblAccountCards
where accountid=31
and cardtype='Mastercard'
and last4digits=3434;
---------------------------------------
update TblTransactions
set
RetailerId = 10001,
StoreId = 1,
TransactionAt = '2018-11-17 00:00:00',
EnteredAt = '2018-11-16 20:03:28',
UpdatedAt = current_timestamp,
Subtotal = 200,
CardId = 1
where accountId = 31 and receiptId = 53;
--------------------------------------------
update tblcustomerplans
set currentAmountSpent = (select sum(subtotal) from TblTransactions where
accountId = 31 and planId = 53)
where
accountId = 31 and customerId = 24;
------------------------------------------------------------------------
select spendtargetmax from tblcustomerplans
where accountid=31 and customerid=24 and planid=53;
--------------------------------
update tblcustomerplans
set status = 'MarkComplete'
where
accountId = 31
and customerId = 24
and planId = 53
and currentamountspent >= 550;
但不知道为什么问题会出现在执行函数时
发生这种情况是因为您已经创建了两个或更多函数,其名称为 fninsertreceipttransaction
且参数数量与执行期间传递的参数数量相同,而 Postgres 无法确定应调用哪个函数。
为了说明,让我们创建 2 个函数。
函数1
knayak= CREATE FUNCTION myfunction(p TIMESTAMP)
knayak- RETURNS BOOLEAN AS $$
knayak$ BEGIN
knayak$ RETURN true;
knayak$ END;
knayak$ $$ LANGUAGE plpgsql;
CREATE FUNCTION
函数2
knayak=
knayak=
knayak= CREATE FUNCTION myfunction(p ) --unknown type p
knayak- RETURNS INTEGER AS $$
knayak$ BEGIN
knayak$ RETURN 1;
knayak$ END;
knayak$ $$ LANGUAGE plpgsql;
CREATE FUNCTION
现在尝试通过传递一个字符串来执行函数
knayak= DO $$
knayak$ BEGIN
knayak$ PERFORM myfunction('2018-11-16 20:03:28');
knayak$ END$$;
我收到此错误是因为 Postgres 无法根据我的论点在两者之间做出决定。
ERROR: function myfunction(unknown) is not unique LINE 1: SELECT myfunction('2018-11-16 20:03:28') ^ HINT: Could not choose a best candidate function. You might need to add explicit type casts. QUERY: SELECT myfunction('2018-11-16 20:03:28') CONTEXT: PL/pgSQL function inline_code_block line 3 at PERFORM
现在,如何知道存在哪些函数?
如果您正在使用 psql
命令提示符,运行 这个简单的命令。
knayak=# \df myfunction
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+------------+------------------+-------------------------------+--------
public | myfunction | integer | p | normal
public | myfunction | boolean | p timestamp without time zone | normal
(2 rows)
您可以看到存在两个具有不同参数的函数。
如果您正在使用 PgAdmin,运行此查询应该会给您相同的结果。
SELECT n.nspname as "Schema",
p.proname as "Name",
pg_catalog.pg_get_function_result(p.oid) as "Result data type",
pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
CASE
WHEN p.proisagg THEN 'agg'
WHEN p.proiswindow THEN 'window'
WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
ELSE 'normal'
END as "Type"
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE p.proname OPERATOR(pg_catalog.~) '^(myfunction)$'
AND pg_catalog.pg_function_is_visible(p.oid)
ORDER BY 1, 2, 4;
你应该如何删除其中一个功能?好吧,如果您确定只应使用一个函数并且您拥有它的创建函数脚本,请删除所有并重新创建它。
您不能简单地发出 DROP function <functionname>
,这在这种情况下不起作用。您必须指定参数签名。
knayak=# DROP function myfunction; --Doesn't work
ERROR: function name "myfunction" is not unique
HINT: Specify the argument list to select the function unambiguously.
这些语句有效。
knayak=#
knayak=# DROP function myfunction(p);
DROP FUNCTION
knayak=# DROP function myfunction(timestamp);
DROP FUNCTION
删除后,重新运行 create function
脚本一次。它应该执行得很好。