列引用含糊不清

时间:2018-08-08 13:16:24

标签: postgresql postgresql-9.6

我尝试运行一个简单的代码,如下所示:

Create Table weather (
    city        varchar(80),
    temp_lo     int,
    temp_hi     int,
    prcp        real,
    date        date
);
Insert Into weather Values ('A', -5, 40, 25, '2018-01-10');
Insert Into weather Values ('B', 5, 45, 15, '2018-02-10');

Create Table cities (
    city        varchar(80),
    location    point
);
Insert Into cities Values ('A', '(12,10)');
Insert Into cities Values ('B', '(6,4)');
Insert Into cities Values ('C', '(18,13)');

Select * From cities, weather Where city = 'A'

但是我得到的是

  

错误:列引用“城市”不明确。

我的代码有什么问题?

2 个答案:

答案 0 :(得分:6)

如果我是你,我会在建模方面略有不同。

为了使事情标准化,我们将从“ citys”表开始并进行一些更改:

cities

请注意,我使用整数表示表的ID和主键,并分别存储了城市名称。这为您提供了一个易于维护的很好的查找表。通过使用整数作为主键,我们在存储数据时还将在天气表中使用更少的空间。

create table cities (
    city_id     integer primary key,
    city_name   varchar(100), 
    location    point
);

请注意,我存储的是城市的ID,而不是名称。另外,我已重命名Create Table weather ( city_id integer, temp_lo int, temp_hi int, prcp real, record_date date ); ,因为在SQL reserved words之后命名列并不是一个好主意。

确保我们在测试数据中使用ID:

date

您的旧查询:

Insert Into weather Values (1, -5, 40, 25, '2018-01-10');
Insert Into weather Values (2, 5, 45, 15, '2018-02-10');

Insert Into cities Values (1,'A', '(12,10)');
Insert Into cities Values (2,'B', '(6,4)');
Insert Into cities Values (3,'C', '(18,13)');

名称不明确,因为两个表都有一个Select * From cities, weather Where city = 'A' 列,并且数据库引擎不知道您的意思是哪个city(它不会自动知道是否需要使用city.city。或weather.city)。该查询还会执行cartesian product,因为您尚未将表连接在一起。

使用我在上面所做的更改,您将需要执行以下操作:

city

或者,使用更新的联接语法:

Select * 
From cities, weather 
Where cities.city_id = weather.city_id
and city_name = 'A';

这两个查询在功能上是等效的-如今,大多数人都喜欢第二个查询,因为它可以防止出错(例如:忘记实际加入Select * From cities join weather on cities.city_id = weather.city_id Where city_name = 'A'; 子句)。

答案 1 :(得分:5)

citiesweather都有一个名为city的列。在您的WHERE子句中,过滤city = 'A',它所引用的是哪个表的city

您可以在列的表名之前告诉引擎要过滤的引擎:

Select * From cities, weather Where cities.city = 'A'

您还可以使用别名引用表:

Select * 
From cities AS C, weather AS W 
Where C.city = 'A'

但最重要的是,请确保您将表连接在一起,除非您希望两个表中的所有记录都没有条件(笛卡尔积)匹配。您可以将其与明确的INNER JOIN一起加入:

Select 
    * 
From 
    cities AS C
    INNER JOIN weather AS W ON C.city = W.city
Where 
    C.city = 'A'

在您提到的示例中,使用了以下查询:

SELECT *
FROM weather, cities
WHERE city = name;

但是在这里,cities表具有name列(而不是{<1>},这是您使用的 )。因此,此city子句将WHEREweather表链接在一起,因为citiescity列,而weathername列并且没有歧义,因为两个列的名称都不同。