Он может ссылаться либо на переменную PL/pgSQL, либо на столбец таблицы

У меня есть функция в pgsql

CREATE OR REPLACE FUNCTION core.date_bs_from_ad(date_in_ad date)
  RETURNS character varying AS
$$
BEGIN
    RETURN(
        SELECT date_in_bs FROM core.date_conversion
        WHERE date_in_ad = $1
    );
END
$$

  LANGUAGE plpgsql;

Он создается без ошибок, но когда я использую эту функцию, он выполняет следующую ошибку:

ERROR:  column reference "date_in_ad" is ambiguous
LINE 3:   WHERE date_in_ad = $1
                ^
DETAIL:  It could refer to either a PL/pgSQL variable or a table column.
QUERY:  SELECT (
        SELECT MAX(date_in_bs) FROM core.date_conversion
        WHERE date_in_ad = $1
    )
CONTEXT:  PL/pgSQL function core.date_bs_from_ad(date) line 3 at RETURN
********** Error **********

ERROR: column reference "date_in_ad" is ambiguous
SQL state: 42702
Detail: It could refer to either a PL/pgSQL variable or a table column.
Context: PL/pgSQL function core.date_bs_from_ad(date) line 3 at RETURN

Ответ 1

Существует столкновение между идентификатором SQL и переменной PlpgSQL. Нет ничего чистого, чего ты хочешь. Вы написали предикат, который всегда ИСТИНА.

Полезно использовать:

  • префикс (обычно "_" ) для локальных переменных
  • квалифицированные имена во встроенном SQL - как table_name.column_name

поэтому оба метода (требуется только один)

CREATE OR REPLACE FUNCTION core.date_bs_from_ad(_date_in_ad date)
RETURNS character varying AS $$
BEGIN
  RETURN SELECT dc.date_in_bs
             FROM core.date_conversion dc
            WHERE dc.date_in_ad = _date_in_ad;
END
$$  LANGUAGE plpgsql;

Для этих функций одной строки лучше подходит язык SQL:

CREATE OR REPLACE FUNCTION core.date_bs_from_ad(_date_in_ad date)
RETURNS character varying AS $$
   SELECT dc.date_in_bs
      FROM core.date_conversion dc
     WHERE dc.date_in_ad = $1; 
$$  LANGUAGE sql;

Ответ 2

В таких случаях, когда код достаточно прост достаточно прост, иногда полезно полагаться на одну из этих специальных команд plpgsql в начале текста функции:

#variable_conflict error
#variable_conflict use_variable
#variable_conflict use_column

В этом случае он будет использоваться следующим образом:

CREATE OR REPLACE FUNCTION core.date_bs_from_ad(date_in_ad date)
  RETURNS character varying AS
$$
#variable_conflict use_column
BEGIN
    RETURN(
        SELECT date_in_bs FROM core.date_conversion
        WHERE date_in_ad = $1
    );
END
$$

Это особенно полезно для случаев, когда столкновение происходит не с параметрами, а с именами выходных столбцов, такими как:

CREATE OR REPLACE FUNCTION core.date_bs_from_ad(p_date_in_ad date)
  RETURNS TABLE (date_in_bs character varying) AS
$$
BEGIN
    RETURN QUERY
        SELECT date_in_bs FROM core.date_conversion
        WHERE date_in_ad = p_date_in_ad;
END;
$$

Вышеуказанная функция завершится неудачей, поскольку компилятор не может решить, является ли date_in_bs имя выходной переменной или один из столбцов core.date_conversion. Для таких задач команда #variable_conflict use_column может действительно помочь.