【问题标题】:<column> is ambiguous in column comparison between two tables<column> 在两个表之间的列比较中不明确
【发布时间】:2017-12-08 18:20:03
【问题描述】:

我希望这个 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 行 返回查询

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

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

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

【问题讨论】:

    标签: sql postgresql plpgsql


    【解决方案1】:

    您的查询很好。歧义在returns table(match_id BIGINT) 中的match_id 上重命名它或在查询中使用表名作为列前缀

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

    没有测试代码。

    【讨论】:

    • 现在工作。谢谢!
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        更多:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-05
          • 1970-01-01
          • 1970-01-01
          • 2015-04-06
          相关资源
          最近更新 更多