列引用的歧义

Zak*_*har 2 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'
Run Code Online (Sandbox Code Playgroud)

但我得到的是

错误:列引用"city"不明确.

我的代码出了什么问题?

Phi*_*hil 6

如果我是你,我会稍微改变一下.

为了使事情规范化,我们将从cities表开始并进行一些更改:

create table cities (
    city_id     integer primary key,
    city_name   varchar(100), 
    location    point
);
Run Code Online (Sandbox Code Playgroud)

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

Create Table weather (
    city_id     integer,
    temp_lo     int,
    temp_hi     int,
    prcp        real,
    record_date  date
);
Run Code Online (Sandbox Code Playgroud)

请注意,我正在存储城市的ID而不是名称.此外,我已重命名date为在SQL保留字后命名列不是一个好主意.

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

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)');
Run Code Online (Sandbox Code Playgroud)

你的旧查询:

Select * From cities, weather Where city = 'A'
Run Code Online (Sandbox Code Playgroud)

名称不明确,因为两个表都有一city列,而数据库引擎不知道city你的意思(它不会自动知道它是否需要使用cities.city或weather.city).该查询还执行笛卡尔积,因为您没有将表一起加入.

使用我上面所做的更改,您需要以下内容:

Select * 
From cities, weather 
Where cities.city_id = weather.city_id
and city_name = 'A';
Run Code Online (Sandbox Code Playgroud)

或者,使用较新的连接语法:

Select * 
From cities
join weather on cities.city_id = weather.city_id
Where city_name = 'A';
Run Code Online (Sandbox Code Playgroud)

这两个查询在功能上是等价的 - 现在大多数人更喜欢第二个查询,因为它可以防止错误(例如:忘记实际加入该where子句).


EzL*_*zLo 5

这两个表cities,并weather有一个名为列city.在你的WHERE子句中你过滤city = 'A',它指的city是哪个表?

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

Select * From cities, weather Where cities.city = 'A'
Run Code Online (Sandbox Code Playgroud)

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

Select * 
From cities AS C, weather AS W 
Where C.city = 'A'
Run Code Online (Sandbox Code Playgroud)

但最重要的是,请确保将表连接在一起,除非您希望两个表中的所有记录都没有标准(笛卡尔积)匹配.你可以用明确的方式加入它们INNER JOIN:

Select 
    * 
From 
    cities AS C
    INNER JOIN weather AS W ON C.city = W.city
Where 
    C.city = 'A'
Run Code Online (Sandbox Code Playgroud)

在您提到的示例中,使用此查询:

SELECT *
FROM weather, cities
WHERE city = name;
Run Code Online (Sandbox Code Playgroud)

但在这里,cities表中有name列(而不是city它是一个使用).所以这个WHERE条款是连接weathercities表一起,因为cityweather列,namecities列,没有歧义,因为两列被命名为不同的.