PostgreSQL基础用法
创建一个数据库
创建一个名为postgres的数据库
createdb postgres
操作数据库
创建表
创建表weather
CREATE TABLE weather (
city varchar(80),
temp_lo int, -- 最低温度
temp_hi int, -- 最高温度
prcp real, -- 湿度
date date
);
你可以在psql输入这些命令以及换行符。psql可以识别该命令直到分号才结束。
你可以在 SQL 命令中自由使用空白(即空格、制表符和换行符)。 这就意味着你可以用和上面不同的对齐方式键入命令,或者将命令全部放在一行中。两个划线(“–”)引入注释。 任何跟在它后面直到行尾的东西都会被忽略。SQL 是对关键字和标识符大小写不敏感的语言,只有在标识符用双引号包围时才能保留它们的大小写(上例没有这么做)。
varchar(80)指定了一个可以存储最长 80 个字符的任意字符串的数据类型。int是普通的整数类型。real是一种用于存储单精度浮点数的类型。date类型应该可以自解释(没错,类型为date的列名字也是date。 这么做可能比较方便或者容易让人混淆 — 你自己选择)。
PostgreSQL支持标准的SQL类型int、smallint、real、double precision、char(N)、varchar(N)、date、time、timestamp和interval,还支持其他的通用功能的类型和丰富的几何类型。PostgreSQL中可以定制任意数量的用户定义数据类型。因而类型名并不是语法关键字,除了SQL标准要求支持的特例外。
创建关联表cities
CREATE TABLE cities (
name varchar(80),
location point
);
删除表
DROP TABLE xxx;
DROP TABLE cites;
表插入数据
INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');
请注意所有数据类型都使用了相当明了的输入格式。那些不是简单数字值的常量通常必需用单引号(')包围,就象在例子里一样。date类型实际上对可接收的格式相当灵活,不过在本教程里,我们应该坚持使用这种清晰的格式。
point类型要求一个座标对作为输入,如下:
INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');
到目前为止使用的语法要求你记住列的顺序。一个可选的语法允许你明确地列出列:
INSERT INTO weather (city, temp_lo, temp_hi, prcp, date)
VALUES ('San Francisco', 43, 57, 0.0, '1994-11-29');
如果你需要,你可以用另外一个顺序列出列或者是忽略某些列, 比如说,我们不知道降水量:
INSERT INTO weather (date, city, temp_hi, temp_lo)
VALUES ('1994-11-29', 'Hayward', 54, 37);
你还可以使用COPY从文本文件中装载大量数据。这种方式通常更快,因为COPY命令就是为这类应用优化的, 只是比 INSERT少一些灵活性。比如:
COPY weather FROM '/home/user/weather.txt';
查询表
SELECT * FROM weather;
这里*是“所有列”的缩写。
因此等同于:
SELECT city, temp_lo, temp_hi, prcp, date FROM weather;
你可以在选择列表中写任意表达式,而不仅仅是列的列表。比如,你可以:
SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
一个查询可以使用WHERE子句“修饰”,它指定需要哪些行。WHERE子句包含一个布尔(真值)表达式,只有那些使布尔表达式为真的行才会被返回。在条件中可以使用常用的布尔操作符(AND、OR和NOT)。 比如,下面的查询检索旧金山的下雨天的天气:
SELECT * FROM weather
WHERE city = 'San Francisco' AND prcp > 0.0;
你可以要求返回的查询结果是排好序的:
SELECT * FROM weather
ORDER BY city;
在这个例子里,排序的顺序并未完全被指定,因此你可能看到属于旧金山的行被随机地排序。但是如果你使用下面的语句,那么就总是会得到上面的结果:
SELECT * FROM weather
ORDER BY city, temp_lo;
你可以要求在查询的结果中消除重复的行:
SELECT DISTINCT city
FROM weather;
结果行的顺序可能变化。你可以组合使用DISTINCT和ORDER BY来保证获取一致的结果:
SELECT DISTINCT city
FROM weather
ORDER BY city;
多表联查
到目前为止,我们的查询一次只访问一个表。查询可以一次访问多个表,或者用这种方式访问一个表而同时处理该表的多个行。 一个同时访问同一个或者不同表的多个行的查询叫连接查询。举例来说,比如你想列出所有天气记录以及相关的城市位置。要实现这个目标,我们需要拿 weather表每行的city列和cities表所有行的name列进行比较, 并选取那些在该值上相匹配的行对。
SELECT *
FROM weather, cities
WHERE city = name;
观察结果集的两个方面:
- 没有城市Hayward的结果行。这是因为在cities表里面没有Hayward的匹配行,所以连接忽略
weather表里的不匹配行。我们稍后将看到如何修补它。 - 有两个列包含城市名字。这是正确的, 因为weather和cities表的列被串接在一起。不过,实际上我们不想要这些,
因此你将可能希望明确列出输出列而不是使用*:
SELECT city, temp_lo, temp_hi, prcp, date, location
FROM weather, cities
WHERE city = name;
因为这些列的名字都不一样,所以规划器自动地找出它们属于哪个表。如果在两个表里有重名的列,你需要限定列名来说明你究竟想要哪一个,如:
SELECT weather.city, weather.temp_lo, weather.temp_hi,
weather.prcp, weather.date, cities.location
FROM weather, cities
WHERE cities.name = weather.city;
人们广泛认为在一个连接查询中限定所有列名是一种好的风格,这样即使未来向其中一个表里添加重名列也不会导致查询失败。
到目前为止,这种类型的连接查询也可以用下面这样的形式写出来:
SELECT *
FROM weather INNER JOIN cities ON (weather.city = cities.name);
我们想让查询干的事是扫描weather表, 并且对每一行都找出匹配的cities表行。如果我们没有找到匹配的行,那么我们需要一些“空值”代替cities表的列。 这种类型的查询叫外连接 (我们在此之前看到的连接都是内连接)。这样的命令看起来象这样:
SELECT *
FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);
我们也可以把一个表和自己连接起来。这叫做自连接。 比如,假设我们想找出那些在其它天气记录的温度范围之外的天气记录。这样我们就需要拿 weather表里每行的temp_lo和temp_hi列与weather表里其它行的temp_lo和temp_hi列进行比较。我们可以用下面的查询实现这个目标:
SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high,
W2.city, W2.temp_lo AS low, W2.temp_hi AS high
FROM weather W1, weather W2
WHERE W1.temp_lo < W2.temp_lo
AND W1.temp_hi > W2.temp_hi;
在这里我们把weather表重新标记为W1和W2以区分连接的左部和右部。你还可以用这样的别名在其它查询里节约一些敲键,比如:
SELECT *
FROM weather w, cities c
WHERE w.city = c.name;
本次分享到此结束,
下一章将会分享使用聚集函数进行查表