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

时间:2017-12-08 18:20:03

标签: sql postgresql plpgsql

我希望这个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错误[42702]:错误:列引用“match_id”不明确
  细节:它可以指PL / pgSQL变量或表   柱。其中:PL / pgSQL函数   difference_of_match_ids_in_match_history_and_match_results()第3行   返回查询

我已经看到了同样错误的其他问题,他们建议命名子查询以指定您所引用的列的哪个实例,但是,这些示例使用连接并且我的查询在函数之外工作正常。

如果我确实需要为列命名,那么如何只使用一个子查询?

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

4 个答案:

答案 0 :(得分:1)

你查询没问题。歧义位于<tr> match_id重命名,或者在查询中使用表名称添加前缀

returns table(match_id BIGINT)

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';

没有测试代码。

答案 1 :(得分:1)

结果集的结构必须与函数结果类型匹配。如果您只想获得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';

答案 2 :(得分:1)

正如其他人所回答的那样,结果定义和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;

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

答案 3 :(得分:0)

已解决了列名和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
   );

更多: