<column> 在两个表之间的列比较中不明确

<column> is ambiguous in column comparison between two tables

我想让这个 postgres 函数起作用:

CREATE OR REPLACE FUNCTION difference_of_match_ids_in_match_history_and_match_results() 
  returns table(match_id BIGINT) 
as 
$$ 
BEGIN   
  return QUERY 
  SELECT * 
  FROM sports.match_history     
  WHERE match_id NOT IN (SELECT match_id 
                         FROM sports.match_results); 
END $$   
LANGUAGE 'plpgsql';

这个独立的查询工作得很好:

SELECT * 
FROM sports.match_history   
WHERE match_id NOT IN (SELECT match_id FROM sports.match_results);

但是当我把它放到这个函数中并尝试 运行 它像这样:

select * 
from difference_of_match_ids_in_match_history_and_match_results();

我明白了:

SQL Error [42702]: ERROR: column reference "match_id" is ambiguous
Detail: It could refer to either a PL/pgSQL variable or a table column. Where: PL/pgSQL function difference_of_match_ids_in_match_history_and_match_results() line 3 at RETURN QUERY

我看到其他问题也有同样的错误,他们建议命名子查询以指定您所指的列的哪个实例,但是,这些示例使用联接并且我的查询在功能。

如果我确实需要为列命名,我将如何仅使用一个子查询来命名?

如果这不是问题所在,那么我假设我定义函数的方式有问题。

您的查询没问题。歧义在于 returns table(match_id BIGINT) 中的 match_id 重命名它或在查询

中使用 table 名称作为列前缀
CREATE OR REPLACE FUNCTION difference_of_match_ids_in_match_history_and_match_results() 
  returns table(new_name BIGINT) 
as 
$$ 
BEGIN   
  return QUERY 
  SELECT * 
  FROM sports.match_history     
  WHERE match_id NOT IN (SELECT match_id 
                         FROM sports.match_results); 
END $$   
LANGUAGE 'plpgsql';

CREATE OR REPLACE FUNCTION difference_of_match_ids_in_match_history_and_match_results() 
  returns table(match_id BIGINT) 
as 
$$ 
BEGIN   
  return QUERY 
  SELECT sports.match_history.match_id
  FROM sports.match_history     
  WHERE sports.match_history.match_id NOT IN (SELECT sports.match_results.match_id 
                         FROM sports.match_results); 
END $$   
LANGUAGE 'plpgsql';

没有测试代码。

结果集的结构必须与函数结果类型匹配。如果你只想得到 match_ids:

CREATE OR REPLACE FUNCTION difference_of_match_ids_in_match_history_and_match_results() 
  RETURNS TABLE(m_id BIGINT)    -- !!
AS 
$$ 
BEGIN   
  RETURN QUERY 
  SELECT match_id               -- !!
  FROM sports.match_history     
  WHERE match_id NOT IN (SELECT match_id 
                         FROM sports.match_results); 
END $$   
LANGUAGE 'plpgsql';

如果你想得到整行作为结果:

DROP FUNCTION difference_of_match_ids_in_match_history_and_match_results();
CREATE OR REPLACE FUNCTION difference_of_match_ids_in_match_history_and_match_results() 
  RETURNS SETOF sports.match_history    -- !!
AS
$$ 
BEGIN   
  RETURN QUERY 
  SELECT *                              -- !!
  FROM sports.match_history     
  WHERE match_id NOT IN (SELECT match_id 
                         FROM sports.match_results); 
END $$   
LANGUAGE 'plpgsql';

正如其他人回答的那样,结果定义和 PL/pgSQL 变量之间存在歧义。集合返回函数中的列名其实也是函数内部的一个变量

但是您首先不需要 PL/pgSQL。如果你使用普通的 SQL 函数,它会更有效,问题也会消失:

CREATE OR REPLACE FUNCTION difference_of_match_ids_in_match_history_and_match_results() 
  returns table(match_id BIGINT) 
as 
$$ 
  SELECT match_id --<< do not return * - only return one column
  FROM sports.match_history     
  WHERE match_id NOT IN (SELECT match_id 
                         FROM sports.match_results); 
$$   
LANGUAGE sql;

请注意,语言名称是一个标识符,根本不应该被引用。

列名和 plpgsql OUT 参数之间的命名冲突已得到解决。此处有更多详细信息:

我也会使用不同的查询方式。 NOT IN (SELECT ...) 通常是最慢的并且带有 NULL 值的陷阱。使用 NOT EXISTS 代替:

SELECT match_id
FROM   sports.match_history h 
WHERE  NOT EXISTS (
   SELECT match_id 
   FROM   sports.match_results
   WHERE  match_id = h.match_id
   );

更多:

  • Select rows which are not present in other table