Меню

Ошибка неоднозначная ссылка на столбец postgresql

I keep getting this ERROR: column reference «person» is ambiguous.

It is required of me to return a TABLE (person integer). It works fine when I use SETOF integer but in this instance it doesn’t work. My other function recurse() returns a set of integers perfectly well.

CREATE OR REPLACE FUNCTION try(_group text) RETURNS TABLE (person integer) AS $$ 
DECLARE
     _init_id integer;
     _record integer;
BEGIN
     SELECT id INTO _init_id FROM egroups WHERE name = _group;

    FOR _record in SELECT person FROM egroupdata WHERE egroup IN (SELECT recurse(_init_id))
    LOOP
        RETURN NEXT;
    END LOOP;

END;
$$ language plpgsql stable;

Brian Tompsett - 汤莱恩's user avatar

asked May 25, 2012 at 8:01

ryantata's user avatar

1

Ambiguous column references are due to there being more than one column available of the same name. In this case I guess it’s a quirk of returning a table. Try changing the query to:

SELECT egroupdata.person FROM egroupdata WHERE egroup IN (SELECT recurse(_init_id))

This will disambiguate the column reference.

answered May 25, 2012 at 8:39

Philip Couling's user avatar

Philip CoulingPhilip Couling

13k4 gold badges51 silver badges80 bronze badges

0

I keep getting this ERROR: column reference «person» is ambiguous.

It is required of me to return a TABLE (person integer). It works fine when I use SETOF integer but in this instance it doesn’t work. My other function recurse() returns a set of integers perfectly well.

CREATE OR REPLACE FUNCTION try(_group text) RETURNS TABLE (person integer) AS $$ 
DECLARE
     _init_id integer;
     _record integer;
BEGIN
     SELECT id INTO _init_id FROM egroups WHERE name = _group;

    FOR _record in SELECT person FROM egroupdata WHERE egroup IN (SELECT recurse(_init_id))
    LOOP
        RETURN NEXT;
    END LOOP;

END;
$$ language plpgsql stable;

Brian Tompsett - 汤莱恩's user avatar

asked May 25, 2012 at 8:01

ryantata's user avatar

1

Ambiguous column references are due to there being more than one column available of the same name. In this case I guess it’s a quirk of returning a table. Try changing the query to:

SELECT egroupdata.person FROM egroupdata WHERE egroup IN (SELECT recurse(_init_id))

This will disambiguate the column reference.

answered May 25, 2012 at 8:39

Philip Couling's user avatar

Philip CoulingPhilip Couling

13k4 gold badges51 silver badges80 bronze badges

0

#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 поведение.

Я попробовал следующий выбор:

SELECT (id,name) FROM v_groups vg 
inner join people2v_groups p2vg on vg.id = p2vg.v_group_id
where p2vg.people_id =0;

и я получаю следующую ссылку на столбец с ошибкой id является неоднозначным.

Дело в том, что если я попробую то же самое SELECT но я только прошу name, а не для id Кроме того, это работает. Я новичок в этом, и, возможно, мне не хватает чего-то очевидного. Какие-либо предложения?

Благодарю.

4 ответы

Вам нужно имя / псевдоним таблицы в SELECT часть (возможно (vg.id, name)):

SELECT (vg.id, name) FROM v_groups vg 
inner join people2v_groups p2vg on vg.id = p2vg.v_group_id
where p2vg.people_id =0;

ответ дан 04 дек ’20, 12:12

Я предполагаю, что ваша таблица p2vg также имеет поле id, в этом случае postgres не может найти, если идентификатор в SELECT относится к vg или p2vg.

вы должны использовать SELECT(vg.id,vg.name) убрать двусмысленность

ответ дан 05 мая ’17, 15:05

SELECT (vg.id, name) FROM v_groups vg 
INNER JOIN people2v_groups p2vg ON vg.id = p2vg.v_group_id
WHERE p2vg.people_id = 0;

ответ дан 23 мар ’12, в 10:03

SELECT vg.id, 
       vg.name
  FROM v_groups vg INNER JOIN  
       people2v_groups p2vg ON vg.id = p2vg.v_group_id
 WHERE p2vg.people_id = 0;

Создан 25 сен.

Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками

sql
postgresql
select

or задайте свой вопрос.

У меня есть эта простая тестовая функция в Postgres (в моей схеме test).

CREATE OR REPLACE FUNCTION test.func_001
(
par_id int
)
RETURNS TABLE
(
id int
)

AS
$BODY$
DECLARE

    var_id int;

BEGIN

    update test.item    --- this is a table 
    set 
    id = 4
    WHERE
    id = 44;

return query 
select 1000 as id;

END;
$BODY$
LANGUAGE  plpgsql;

В таблице test.item есть единственный столбец идентификаторов.

Я получаю указанную ниже ошибку при попытке запустить функцию.

Query execution failed

Reason:
SQL Error [42702]: ERROR: column reference "id" is ambiguous
  Detail: It could refer to either a PL/pgSQL variable or a table column.
  Where: PL/pgSQL function test.func_001(integer) line 8 at SQL statement

Эта ошибка кажется странной, означает ли это, что Postgres обнаруживает конфликт / конфликт между столбцом test.item.id и столбцом id из возвращенной таблицы ?!
Как придешь? В этом нет никакого смысла.

Я не могу поверить в это, но я не вижу здесь других применений id.

Обратите внимание, что если я закомментирую только эту часть.

-- WHERE
-- id = 44;

Потом вдруг функция работает нормально.

Кажется, что Постгрес путает идентификатор в том, где
предложение с чем-то еще с именем id ?!

С чем?

Это совершенно нелогично и противоречит интуиции.

Может кто-нибудь объяснить?

Перейти к ответу
Данный вопрос помечен как решенный


Ответы
2

Существует конфликт имен между переменной id, которая определяется предложением RETURNS TABLE, и столбцом с тем же именем.

Подобные вещи вызывают проблемы во всех языках программирования, только PostgreSQL достаточно хорош, чтобы предупредить вас, а не делать что-то, что может быть не тем, что вы планировали.

Укажите ссылку на столбец следующим образом, чтобы устранить двусмысленность:

WHERE test.item.id = 44

Пункт FUNCTION fx() RETURNS TABLE(x int, y int, …) аналогичен пункту FUNCTION(OUT x int, OUT y int) RETURNS SETOF record. Итак, в вашем случае есть неявная переменная id, хотя вы не используете ее явно.

Дизайн PostgreSQL позволяет создавать строки без SQL.

CREATE OR REPLACE FUNCTION foo(a int)
RETURNS TABLE(b int, c int) AS $$
BEGIN
  FOR i IN 1..a
  LOOP
    b := i; c := i * 10;
    RETURN NEXT;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

См., Пожалуйста, документ следующий.

There is another way to declare a function as returning a set, which is to use the syntax RETURNS TABLE(columns). This is equivalent to using one or more OUT parameters plus marking the function as returning SETOF record (or SETOF a single output parameter’s type, as appropriate). This notation is specified in recent versions of the SQL standard, and thus may be more portable than using SETOF.

Другие вопросы по теме

я попробовал следующий выбор:

SELECT (id,name) FROM v_groups vg 
inner join people2v_groups p2vg on vg.id = p2vg.v_group_id
where p2vg.people_id =0;

и я получаю следующую ссылку на столбец ошибок » id » неоднозначна.

дело в том , что если я попробую тот же выбор, но я прошу только (имя), а не id, он работает.
Я новичок в этом, и, возможно, я упускаю что-то очевидное. Есть предложения?

спасибо.

4 ответов


вам нужно имя таблицы / псевдоним в SELECT часть (возможно (vg.id, name)):

SELECT (vg.id,name) FROM v_groups vg 
inner join people2v_groups p2vg on vg.id = p2vg.v_group_id
where p2vg.people_id =0;

Я полагаю, что ваша таблица p2vg также имеет поле id , в этом случае postgres не может найти, если id в SELECT относится к vg или p2vg.

вы должны использовать SELECT(vg.id,vg.name) удалить двусмысленность


SELECT (vg.id, name) FROM v_groups vg 
INNER JOIN people2v_groups p2vg ON vg.id = p2vg.v_group_id
WHERE p2vg.people_id = 0;

SELECT vg.id, 
       vg.name
  FROM v_groups vg INNER JOIN  
       people2v_groups p2vg ON vg.id = p2vg.v_group_id
 WHERE p2vg.people_id = 0;

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Ошибка необходимо установить принтер для выполнения операций adobe reader
  • Ошибка необходимо указать значение ads google