In PostgreSQL database I have 2 table: services and services_organizations_relationship. Each organization has a specific list of services.
My next function need to create new records in services table, then create relationship between services and organizations and finally return list of all new created services.
CREATE OR REPLACE FUNCTION test (
SERVICE_NAME_ARRAY VARCHAR[],
ACTIVE_ARRAY BOOLEAN[],
DESCRIPTION_ARRAY TEXT[],
ORGANIZATION_ID_ARRAY INT[]
) RETURNS TABLE (
ID UUID,
NAME VARCHAR,
ACTIVE BOOLEAN,
DESCRIPTION TEXT
) AS $$
BEGIN
RETURN QUERY
WITH RESULTS AS (
INSERT INTO SERVICES (NAME, ACTIVE, DESCRIPTION)
SELECT
UNNEST(ARRAY[SERVICE_NAME_ARRAY]) AS NAME,
UNNEST(ARRAY[ACTIVE_ARRAY]) AS ACTICE,
UNNEST(ARRAY[DESCRIPTION_ARRAY]) AS DESCRIPTION
RETURNING ID, NAME, ACTIVE, DESCRIPTION
),
GENERATE_SERVICES_ORGANIZATIONS_RELATIONSHIP AS
(
INSERT INTO SERVICES_ORGANIZATIONS_RELATIONSHIP (SERVICE_ID, ORGANIZATION_ID)
SELECT
UNNEST(ARRAY_AGG(ID)) AS SERVICE_ID,
UNNEST(ARRAY[ORGANIZATION_ID_ARRAY]) AS ORGANIZATION_ID
FROM RESULTS
ON CONFLICT ON CONSTRAINT SERVICES_ORGANIZATIONS_RELATIONSHIP_UNIQUE_KEY DO NOTHING
)
SELECT ID, NAME, ACTIVE, DESCRIPTION FROM RESULTS;
END;
$$ LANGUAGE plpgsql;
When I call this function:
SELECT * FROM test(ARRAY['SLOT', 'JTC'], ARRAY[TRUE, FALSE], ARRAY['SLOT', 'JTC'], ARRAY[30572, 30573]);
I see such error:
SQL Error [42702]: ERROR: column reference "id" is ambiguous
Details: It could refer to either a PL/pgSQL variable or a table column.
Where: PL/pgSQL function test(character varying[],boolean[],text[],integer[]) line 3 at RETURN QUERY
How to fix this problem?
This query runs perfectly well on postgress and returns 2 columns that I am looking for:
SELECT w.jobnr, w.ordernr
FROM
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=1) AS W
LEFT OUTER JOIN
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=2) AS P
ON W.Jobnr=P.Jobnr;
It returns:

But when I enclose this query in a function as under:
CREATE OR REPLACE FUNCTION userdata.test3()
RETURNS TABLE(jobnr character varying, ordernr character varying)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT w.jobnr, w.ordernr
FROM
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=1) AS W
LEFT OUTER JOIN
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=2) AS P
ON W.Jobnr=P.Jobnr;
END;
$function$
and execute it by SELECT * from userdata.test3()
I am getting following error:
ErrorCode: -2147467259
Severity: ERROR, Code: 42702, Line: 1076, Position:
ErrorMessage: column reference "jobnr" is ambiguous
Detail: It could refer to either a PL/pgSQL variable or a table column.
Any idea what is wrong here and how can I resolve it? Thanks
This query runs perfectly well on postgress and returns 2 columns that I am looking for:
SELECT w.jobnr, w.ordernr
FROM
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=1) AS W
LEFT OUTER JOIN
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=2) AS P
ON W.Jobnr=P.Jobnr;
It returns:

But when I enclose this query in a function as under:
CREATE OR REPLACE FUNCTION userdata.test3()
RETURNS TABLE(jobnr character varying, ordernr character varying)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT w.jobnr, w.ordernr
FROM
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=1) AS W
LEFT OUTER JOIN
(SELECT jobnr, ordernr FROM userdata.WIP_Data WHERE Year=2015 AND period=2) AS P
ON W.Jobnr=P.Jobnr;
END;
$function$
and execute it by SELECT * from userdata.test3()
I am getting following error:
ErrorCode: -2147467259
Severity: ERROR, Code: 42702, Line: 1076, Position:
ErrorMessage: column reference "jobnr" is ambiguous
Detail: It could refer to either a PL/pgSQL variable or a table column.
Any idea what is wrong here and how can I resolve it? Thanks
#sql #postgresql
Вопрос:
Пытаюсь упростить эту ВСТАВКУ и продолжаю получать эту неоднозначную ошибку ниже. Что я здесь делаю не так, нужен ли мне где-то псевдоним, которого мне не хватает?
<internal.PGError>: {
m: {
82: "scanRTEForColumn",
83: "ERROR",
86: "ERROR",
67: "42702",
77: "column reference "created_at" is ambiguous",
80: "3082",
70: "parse_relation.c",
76: "694",
},
}
Вот инструкция SQL, которую я использую:
INSERT INTO delivery_areas
SELECT
r.drn_id AS restaurant_drn_id,
'initial'::algorithm_name AS algorithm_name,
z.city_drn_id AS city_drn_id,
?::geometry AS delivery_area,
gen_random_uuid() AS drn_id,
?::timestamp AS created_at,
?::timestamp AS updated_at,
'custom'::delivery_area_type AS delivery_area_type
FROM restaurants r
JOIN neighborhood_zones nz ON (nz.hood_drn_id = r.hood_drn_id)
JOIN zones z ON (z.drn_id = nz.zone_drn_id)
WHERE r.drn_id = ?
GROUP BY restaurant_drn_id, algorithm_name, city_drn_id, created_at, updated_at, delivery_area_type
ON CONFLICT ON CONSTRAINT delivery_areas_pkey DO UPDATE
SET
delivery_area = EXCLUDED.delivery_area,
delivery_area_type = EXCLUDED.delivery_area_type,
updated_at = EXCLUDED.updated_at
RETURNING *
Создайте инструкции таблицы для областей доставки и ресторанов:
CREATE TYPE algorithm_name as ENUM ('initial');
CREATE TABLE delivery_areas (
restaurant_drn_id uuid NOT NULL,
algorithm_name algorithm_name NOT NULL DEFAULT 'initial',
city_drn_id uuid NOT NULL,
delivery_area geometry(MultiPolygon,4326) NOT NULL,
drn_id uuid NOT NULL DEFAULT gen_random_uuid(),
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
PRIMARY KEY (restaurant_drn_id, algorithm_name)
);
CREATE INDEX delivery_areas_algorithm_city_idx on delivery_areas (algorithm_name, city_drn_id);
CREATE INDEX delivery_areas_delivery_area_idx on delivery_areas USING gist(delivery_area);
ALTER TABLE delivery_areas ADD FOREIGN KEY (restaurant_drn_id) REFERENCES restaurants(drn_id);
CREATE TABLE restaurants (
drn_id uuid PRIMARY KEY,
hood_drn_id uuid NOT NULL,
delivery_range_delta_m int4 NOT NULL,
geo_lat double precision NOT NULL,
geo_long double precision NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
Комментарии:
1. Таким образом, все столбцы в delivery_areas находятся в инструкции select. И поскольку я не могу добавить псевдоним в инструкцию INSERT INTO, что я упускаю?
2. Квалифицируйте все ссылки на ваши столбцы, как
delivery_areaи должно бытьdelivery_areas.delivery_area. Одна или несколько ссылок на ваши столбцы разрешаются двумя или более таблицами, и база данных просит вас устранить эту двусмысленность.3. Что
?::geometry AS delivery_area,должно быть ? Заполнитель для позиционного аргумента?4.
?::geometry AS delivery_area,действительно ли заполнитель для позиционного аргумента да5. Я добавил
delivery_areas.в качестве префикса перед всеми именами полей справа внутри выбора, но теперь выдает следующую ошибку:<internal.PGError>: { 77: "syntax error at or near "."", ... }
Ответ №1:
Обратите внимание, что в вашем GROUP BY предложении у вас есть ссылка на created_at :
GROUP BY restaurant_drn_id, algorithm_name, city_drn_id, created_at, updated_at, delivery_area_type
Но этот столбец есть в нескольких ваших таблицах.
Префикс этой ссылки на столбец с правильной таблицей, например:
GROUP BY restaurant_drn_id, algorithm_name, city_drn_id, delivery_areas.created_at, updated_at, delivery_area_type
Я только догадался, на какую таблицу вы хотели сослаться. Это устранит эту ошибку, но это может быть не та дата/отметка времени, по которой вы хотели сгруппироваться.
Вот пример проблемы и решения, а также подробные сведения, которые следует указывать при задании такого рода вопросов:
CREATE TABLE delivery_areas (
id int
, created_at timestamp
);
CREATE TABLE restaurants (
drn_id int
, created_at timestamp
);
CREATE TABLE othertbl (
id int
, created_at timestamp
);
-- The following generates an error:
INSERT INTO delivery_areas
SELECT r.drn_id AS restaurant_drn_id
, current_timestamp AS created_at
FROM restaurants r
JOIN othertbl o
ON o.id = r.drn_id
GROUP BY restaurant_drn_id, created_at
;
-- ERROR: column reference "created_at" is ambiguous
-- LINE 7: GROUP BY restaurant_drn_id, created_at
-- The following is one way to resolve the error:
INSERT INTO delivery_areas
SELECT r.drn_id AS restaurant_drn_id
, current_timestamp AS created_at
FROM restaurants r
JOIN othertbl o
ON o.id = r.drn_id
GROUP BY restaurant_drn_id, r.created_at
;
Обратите внимание на r.created_at . r является определителем, разрешающим двусмысленность.
Вот ссылка на тестовый случай:
Полный рабочий тестовый случай
Комментарии:
1. Итак, у вас здесь противоречивые советы, я должен использовать
r.created_atилиdelivery_areas.created_at? Если я использую последнее, я получу это:72: "There is an entry for table "delivery_areas", but it cannot be referenced from this part of the query.",2. @Уильямроуз Нет, нет. Вы посмотрели ссылку на скрипку, которую я предоставил?
r.created_atбыл в тестовом примере, который я создал. Я также сослался на ваш запрос, добавленный в начало ответа. Вы знаете, какуюcreated_atколонку вы хотелиGROUP BY?3. Ааа, хорошо. Да, я хотел бы сгруппироваться по
delivery_areasверсии4. @WilliamRose Идеально. Тогда мое предположение должно сработать, пока не будет найдена следующая проблема.
5. @WilliamRose
SELECTСписок определяет, что будет вставлено.tbl.created_atВGROUP BYтермины не вставляется, но используется для определения того, какие строки выбраны. Мы могли бы поболтать, если хочешь. Я не уверен, что вы понимаете такоеGROUP BYповедение.
This works:
CREATE OR REPLACE FUNCTION sql_fun()
RETURNS TABLE (id UUID) AS $$
INSERT INTO foo DEFAULT VALUES
RETURNING id
$$ LANGUAGE SQL;
SELECT *
FROM sql_fun();
This doesn’t:
CREATE OR REPLACE FUNCTION plpgsql_fun()
RETURNS TABLE (id UUID) AS $$
BEGIN
RETURN QUERY
INSERT INTO foo DEFAULT VALUES
RETURNING id;
END
$$ LANGUAGE PLpgSQL;
SELECT *
FROM plpgsql_fun();
Is this a bug in PL/pgSQL? How can I fix this while keeping the return type as is?
asked Jun 9, 2020 at 16:13
![]()
0
The solution is to qualify all columns from RETURNING which have the same name as the columns from RETURNS TABLE with the name of the table which was INSERTED INTO:
CREATE OR REPLACE FUNCTION plpgsql_fun()
RETURNS TABLE (id UUID) AS $$
BEGIN
RETURN QUERY
INSERT INTO foo DEFAULT VALUES
RETURNING foo.id;
END
$$ LANGUAGE PLpgSQL;
If the name of the table is long and there are multiple columns, the name can be aliased:
CREATE OR REPLACE FUNCTION plpgsql_fun()
RETURNS TABLE (id UUID, foo INT, bar INT) AS $$
BEGIN
RETURN QUERY
INSERT INTO table_with_a_very_long_name AS x DEFAULT VALUES
RETURNING x.id, x.foo, x.bar;
END
$$ LANGUAGE PLpgSQL;
answered Jun 9, 2020 at 17:08
![]()
xehpukxehpuk
2472 silver badges11 bronze badges
1
хочу заполнить пустое поле таблицы 1 значениями, которые нахожу по коду из таблицы 1, в таблице 2
CREATE OR REPLACE FUNCTION public.add_soate(
)
RETURNS SETOF zagsmarriagelist
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
DECLARE
r zagsmarriagelist%rowtype;
DECLARE code varchar;
BEGIN
FOR r IN
SELECT id FROM zagsmarriagelist
LOOP
code := (select nullif(regexp_replace(r::varchar, 'D','','g'), ''));
UPDATE zagsmarriagelist
SET bridesoate = (select substring(a.code from 1 for 14) from ate_history a where a.ate::varchar=(select bridebirthaddress from zagsmarriagelist where id::varchar=code))
WHERE id::varchar=code;
RETURN NEXT r;
END LOOP;
RETURN;
END
$BODY$;
ALTER FUNCTION public.add_soate()
OWNER TO postgres;
select * from add_soate();
ошибка: ERROR: ОШИБКА: неоднозначная ссылка на столбец «code»
LINE 2: …ess from zagsmarriagelist z where z.id::varchar = code)) as …
^
DETAIL: Подразумевается ссылка на переменную PL/pgSQL или столбец таблицы.
QUERY: UPDATE zagsmarriagelist
SET bridesoate = (case when (select z.bridebirthaddress from zagsmarriagelist z where z.id::varchar = code) != » then cast((select substring(a.code from 1 for 14) from ate_history a where a.ate::varchar=(select z.bridebirthaddress from zagsmarriagelist z where z.id::varchar = code)) as integer) else NULL END),
groomsoate = (case when (select z.groombirthaddress from zagsmarriagelist z where z.id::varchar = code) != » then cast((select substring(a.code from 1 for 14) from ate_history a where a.ate::varchar=(select z.bridebirthaddress from zagsmarriagelist z where z.id::varchar = code)) as integer) else NULL END)
WHERE zagsmarriagelist.id::varchar=code
CONTEXT: функция PL/pgSQL add_soate(), строка 13, оператор SQL-оператор
SQL state: 42702
почему он не опознает переменную ‘code’ в подзапросе?
I have a function which:
-
compare two columns from different tables
-
make the insert
How can I get some improvement on this code because I get this error:
ERROR: column reference "fld_id" is ambiguous SQL state: 42702 line 17 at PERFORM
CREATE OR REPLACE FUNCTION "SA_PRJ".usp_add_timesheet_test(p_uid integer, p_project_id integer, p_allocated_time numeric, p_achieved_time numeric, p_task_desc character varying, p_obs character varying, p_date timestamp without time zone)
RETURNS void AS
$BODY$
BEGIN
DECLARE sum_alloc_time numeric;
DECLARE alloc_hours integer;
DECLARE fld_id integer;
SELECT @sum_alloc_time = SUM(fld_allocated_time)
from "SD_PRJ".tbl_project_timesheet
where fld_project_id = p_project_id;
SELECT @alloc_hours = p.fld_allocated_days, @fld_id = p.fld_id
FROM "SD_PRJ".tbl_project p
INNER JOIN "SD_PRJ".tbl_project_timesheet t
ON p.fld_id=t.fld_id
where t.fld_project_id = p_project_id;
IF @sum_alloc_time <= @alloc_hours THEN
INSERT INTO "SD_PRJ".tbl_project_timesheet(fld_emp_id, fld_project_id, fld_is_allocated,fld_allocated_time, fld_achieved_time, fld_task_desc, fld_obs, fld_date)
VALUES (p_uid,p_project_id,coalesce(alloc_id,0), p_allocated_time, p_achieved_time,p_task_desc, p_obs, p_date);
RAISE NOTICE 'INSERT OK!';
ELSE
RAISE NOTICE 'NOT OK';
END IF;
END;
$BODY$ LANGUAGE plpgsql;
There are two tables:
"SD_PRJ".tbl_project (
fld_id
,fld_allocated_days)
"SD_PRJ".tbl_project_timesheet (
fld_id
, fld_project_id
,fld_allocated_time)
I have a function which:
-
compare two columns from different tables
-
make the insert
How can I get some improvement on this code because I get this error:
ERROR: column reference "fld_id" is ambiguous SQL state: 42702 line 17 at PERFORM
CREATE OR REPLACE FUNCTION "SA_PRJ".usp_add_timesheet_test(p_uid integer, p_project_id integer, p_allocated_time numeric, p_achieved_time numeric, p_task_desc character varying, p_obs character varying, p_date timestamp without time zone)
RETURNS void AS
$BODY$
BEGIN
DECLARE sum_alloc_time numeric;
DECLARE alloc_hours integer;
DECLARE fld_id integer;
SELECT @sum_alloc_time = SUM(fld_allocated_time)
from "SD_PRJ".tbl_project_timesheet
where fld_project_id = p_project_id;
SELECT @alloc_hours = p.fld_allocated_days, @fld_id = p.fld_id
FROM "SD_PRJ".tbl_project p
INNER JOIN "SD_PRJ".tbl_project_timesheet t
ON p.fld_id=t.fld_id
where t.fld_project_id = p_project_id;
IF @sum_alloc_time <= @alloc_hours THEN
INSERT INTO "SD_PRJ".tbl_project_timesheet(fld_emp_id, fld_project_id, fld_is_allocated,fld_allocated_time, fld_achieved_time, fld_task_desc, fld_obs, fld_date)
VALUES (p_uid,p_project_id,coalesce(alloc_id,0), p_allocated_time, p_achieved_time,p_task_desc, p_obs, p_date);
RAISE NOTICE 'INSERT OK!';
ELSE
RAISE NOTICE 'NOT OK';
END IF;
END;
$BODY$ LANGUAGE plpgsql;
There are two tables:
"SD_PRJ".tbl_project (
fld_id
,fld_allocated_days)
"SD_PRJ".tbl_project_timesheet (
fld_id
, fld_project_id
,fld_allocated_time)
Dung Do Tien Oct 01 2021 643
I have a small project with Asp.Net Core 3.1 and using PostgreSQL database. Now I want to get all ticket of a member so I created a function database as below:
CREATE OR REPLACE FUNCTION public.func_ticket_getbymemberid (
_memberid integer,
_fromdate timestamp,
_todate timestamp
)
RETURNS TABLE (
id integer,
memberid integer,
createddate timestamp,
score integer
) AS
$body$
BEGIN
RETURN QUERY
SELECT id, memberid, createddate, score
FROM racinggameticket
WHERE memberid = _memberid AND createddate between _fromdate AND _todate;
END
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100 ROWS 1000;
And when I try to execute in code c# by using Dapper I got an exception throw 42702: column reference «id» is ambiguous.
42702: column reference "id" is ambiguous
at Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<<ReadMessage>g__ReadMessageLong|0>d.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<<ReadMessage>g__ReadMessageLong|0>d.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Threading.Tasks.ValueTask`1.get_Result()
at Npgsql.NpgsqlDataReader.<NextResult>d__46.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlDataReader.NextResult()
at Npgsql.NpgsqlCommand.<ExecuteDbDataReader>d__100.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at Npgsql.NpgsqlCommand.ExecuteReader()
at Project.Data.RacingGameTicket.RacingGameDal.GetTicketByMember(Int32 memberId, DateTime fromDate, DateTime toDate) in E:ProjectPhilipMainSource_NewAdminSourcegamefrontendAutoCoreProject.DataRacingGameTicketRacingGameDal.cs:line 53
at Project.BLL.RacingGameTicket.RacingGameBLL.GetTicketByMember(Int32 memberId, DateTime fromDate, DateTime toDate) in E:ProjectPhilipMainSource_NewAdminSourcegamefrontendAutoCoreProject.BLLRacingGameTicketRacingGameBLL.cs:line 27
at AutoPhilippine.Controllers.RacingGameController.GetTicketByMember() in E:ProjectPhilipMainSource_NewAdminSourcegamefrontendAutoPhilippineAutoPhilippineControllersRacingGameController.cs:line 89
This is my racinggameticket table
--- racinggameticket
-- id integer
-- memberid integer
-- createddate timestamp
-- score integer
My select command is very simple and the table does not have two id columns. So I really not understand why them ambiguous.
Thank you for any suggestions.
Have 2 answer(s) found.
-
Diego Ganchozo
Oct 01 2021In the PostgreSQL database, you have to define an alias for the table and using that alias to determine the columns of the table. You can change your database function as below:
SELECT r.id, r.memberid, r.createddate, r.score FROM racinggameticket r WHERE r.memberid = _memberid AND r.createddate between _fromdate AND _todate;I hope this answer is all you need.
-
Select command in Postgre database is not same with Mssql server database. In Mssql you do not need to define an alias for a table but Postgres is required. So you can add more alias as below:
SELECT game.id, game.memberid, game.createddate, game.score FROM racinggameticket game WHERE game.memberid = _memberid AND game.createddate between _fromdate AND _todate;And it worked for you.
Note: This issue is not related to Asp.net Core or Dapper.
Related Q&A May You Like
- The following sections have been defined but have not been rendered by the page
- Fix error: failed to push some refs to repository in Git
- Fatal: unable to access: SSL certificate problem: certificate has expired
- Could not load file or assembly System.Net.Http, Version=4.0.0.0 in .Net
- Error response from daemon unauthorized: HTTP Basic: Access denied CICD GitLab
- Error: The json property name for collides with another property in .Net 6
- Error: Sequence contains no matching element in C# Asp.Net
- Data is Null. This method or property cannot be called on Null values in Asp.Net and MySql
- Error: SSL Connection error in MySQL using C# Asp.Net 6
- Unable to make the session state request to the session state server in .Net
- Github error: src refspec master does not match any
- Unable to create an object of type ‘DbContext’ in EF Core
- GitHub remote: Support for password authentication was removed on August 13, 2021
- Error remote: Repository not found on GitHub when clone
- The SDK ‘Microsoft.NET.Sdk.Web’ specified could not be found
Leave An Answer
* NOTE: You need Login before leave an answer
* Type maximum 2000 characters.
* All comments have to wait approved before display.
* Please polite comment and respect questions and answers of others.