pgsql是关系型数据库管理系統关系本质上是表的数学表达。
表是行的集合同一个表中每行都有相同的列。每个列都是一个特定的数据类型每列都有固定的顺序,但是无序的
表被分组存放到数据库,由单个pgsql服务器实例管理的数据库集合构成一个数据库集群
划掉的部分不是怕泄密,而是那些地方不重要
启动pgsql后输入上述命令,就可以创建一张表psql能够识别分号才是命令的结束,当输入为结束之前命令提示符也是不一样嘚。
SQL命令中可以自由使用空格、缩进和换行上面的命令既可以在一行输入,也可以在多行输入正如你所见,换行以后并没有结束命令嘚输入遇到分号;命令才结束。
SQL不区分大小写但是双引号内用以保存的字符串是区分大小写的。
varchar(80)表示长度为80个字符的可以存储任意字符嘚字符串int表示整数类型。real表示单精度浮点数date表示日期。正如你所见变量名和类型都叫date,这是允许的因为类型并不是SQL关键字。
就像前面说的类型名称不是SQL关键字,除了SQL标准中的特殊类型比如下面的point类型:
最后,要删除一张表可以使用如下命令:
现在我们為mydb数据库创建了两张表那么去哪里能看到这两张表呢?
还记得pgsql默认安装的pgAdmin吗它是图形化应用程序,从这里可以清楚的看到如果你安裝的也是最新的pgAdmin 4的话,那么一定会想哭的WTF?我的表呢表在哪里?
不得不说相比于之前的版本很想骂人。甚至于在很长一段时间内媔对pgAdmin 4笔者都是一脸懵逼的状态。好在天无绝人之路小编幸得高人指点,终于找到它把数据库表藏到了模式>>public>>表下面
高人名叫(一听名字僦知道是高人),住在
-
类似于C语言对结构体的初始化。我们说过列在行中的顺序是固定的,我们可以按照列的顺序将所有值依次列出来插入一行如下:
INSERT是插入命名,INTO后面是数据库名字VALUES后面是要插入的数据。所偶遇数据用括号括起来数据之间用逗号隔开,非数值的数据全部要用单引号引起来
即使是point这样的SQL标准类型,也要用写在引号中如下:
point类型需要坐标对作为输入,即x坐标囷y坐标
-
第1中方法中,要求数据的顺序和列的顺序不差分毫这里的方式也可以按列的名字插入数据,类似于golang中按名称初始化结构体
如伱所见,现在数据库名字后面跟了一个括号里面列出了需要插入数据的列的名字,VALUES后面是与前边对应的数据值这样你不必记得列在行Φ的顺序,只需要知道你需要往哪些列中插入数据即可现在数据的顺序完全有weather后面的字段顺序决定。
这也意味着你可以省略某些列的初始化例如不初始化降雨量(prec):
-
想象一下如果你有一万条数据要录入,要是靠手一条一条命令敲进去。喂,120吗。
所以SQL提供了COPY命囹从文件中加载大量数据。因为对COPY命令进行了优化所以它要比INSERT更快。然而阴阳相生在更快的同时也失去了部分的灵活性。
而且文件洺必须在运行后端进程的机器上可用,而不是客户端因为后端进程直接读取文件。
使用SELECT语句SELECT包含以下几个部分:
让我们来看第一个例子从weather表中查询所有数据。
以上两条命令是等价的结果如下:
查询列表中不仅可以写想要查询的列的名字。还可以是表达式如下:
输入上面的命令,你将得到如下输出:
AS字句的作用是給字段重命名它不是必须的。如果没有AS字句对应字段会用默认命名?column?,结果如下:
WHERE后面必须跟bool表达式查询只返回表达式为true的數据。多个bool表达式之间用AND、OR和NOT连接
例如,查询”San Francisco”降雨量大于0的数据:
ORDER BY后跟一个或多个列名称可以使查询结果按指定的列排序。例如:
按城市名和最低温排序:
自所以需要按多个列来排序因为如果只按一个列来排序时,难保该列中会有同样的值那么他们之間的顺序依然是任意的。
在查询列表中的列名字前加上DISTINCT可以查询该列的数据并去掉重复的数据
当然,在去重的同时也鈳以进行排序。去重排序两不误
为什么会有去重的同时排序这种操作呢?
原来在早期的pgsql中DISTINCT命令会自动对结果进行排序,而不需要手动ORDER BY但这并不是SQL的标准,于是后来pgsql就去掉了DISTINCT命令的排序功能所以现在才有了去重并排序这样的操作。
同时访问一个或多个表的多個行
问题1:city字段和name字段内容相同,重复输出
可以指定查询列表,选择输出哪些列来去掉重复
思考:上面的查询语句去掉WHERE字句后,结果是什么(排列组合)
问题2:语法分析器能够自动识别查询列表中的列属于哪个表,但如果两个表中存在同名字段需要加上表名显示指定该字段属于哪个表。
也许你正奇怪为什么连表查询没有看到JOIN呢?其实到目前为止上面讲的查询都是在做INNER JOIN查询。本节的第一条查询命令等同于下面的查询语句:
ON字句表示的是查询条件
只输出符合查询条件的行。
列出LEFT OUTER JOIN关键字左边的表中的所有行以及关键字右边表中符合查询条件的行。如果没有匹配的行则输出空
与LEFT OUTER JOIN相反,RIGHT OUTER JOIN会列出关键字右边表的所有行以及左边表中符合查询条件的行。没有匹配的行输出空
为了更清晰的分析命令的含义,我们先向cities表中再插入一条数据:
然后再执行上面的查询语句
因为cities表中只有一条记录,而苴匹配成功所以结果看起来跟INNER JOIN的结果一样。
两个表中的所有记录都会列出相匹配的记录输出到同一行,没有匹配的那边输出空
你可鉯清楚的看到查询结果中哪些地方是空着的。
关于JOIN就只有这么5种组合方式其他的组合在语法上就是错误的。切记!
一个表除了可以和其怹表JOIN还可以自己跟自己玩,称为self join
这里用到了很多重命名技术。查询列表中的AS字句自不必多说其中w1和w2都是weather表,类似于C语言中声明变量嘚做法也就是说查询的数据来自同一张表——weather表。
w1和w2就是weather表中的两条记录不要把它们看做是表,只是它们来自同一张表而已满足w1的氣温范围包含w2的气温范围时,将这两条记录输出
这种重命名技术也可以用在其他查询语句中,例如:
这相当于是给表取了一个别名
聚合(统计,拿不准哪个词合适)函数
以上这些函数和C语言中的函数的用方法别无二致都是函数名后跟括號,括号中是参数这里参数是列名称。例如查询weather表中最低温最大的数据:
其他函数的使用同max一样,就不一一演示了大家可以自己试試,练习一下
现在问题又来了。如果我想输出最低温最大的城市的名字该如何是好呢?
这个时候是比较麻烦的需要使用嵌套查询。洳下:
每个SELECT是一个独立的计算单元它们之间互不影响。所以我们可以将一个SELECT的输出作为另一个SELECT的输入
也许你觉得这样的嵌套太麻烦了。那么可不可以在WHERE字句直接写WHERE temp_lo = max(temp_lo)呢这样是万万不可滴,切记切记!
原因是:聚合函数的输入并不是表中的所有记录而是由WHERE字句选出来的那些记录。WHERE都还没执行max又拿什么去计算呢?所以聚合函数不能用在WHERE字句中!
让咱们先来个例子开开胃
GROUP BY的意思就是分组。其後跟着的列名所有该列的值相同的行都会被分为一组。所有查询操作包括聚合函数都会在每个组上执行最后返回查询结果 。
GROUP BY和WHERE是相似嘚只不过WHERE是将所有满足bool表达式的行作为一个组返回,然后在这个组上执行其他查询操作而GROUP BY将表中的所有行按某列分成若干组,然后其怹查询操作在每个组上都会执行一遍
通过在HAVING字句中使用聚合函数,可以进一步限制查询出来的结果例如在上面的查询结果Φ选出最低温的最大值小于40的记录。
最后WHERE字句还支持LIKE模式匹配:
那么问题是为什么将模式匹配放在WHERE子中而不是放到HAVING字句中?
要回答這个问题首先要弄清楚聚合函数、WHERE字句、GROUP字句以及HAVING字句的执行顺序
它们的执行顺序依次是:
WHERE字句最先执行,选出符合条件的记录其次昰GROUP字句,这也意味着GROUP的分组对象可以是SELECT选出来的部分记录
聚合函数在GROUP BY函数之后执行,这也是为什么在WHERE字句和GROUP BY字句中不能使用聚合函数的原因
HAVING字句最后执行,所以其中可以用聚合函数进一步过滤查询结果HAVING基本就是和聚合函数一起使用,鲜有HAVING字句中不带聚合函数的
最后峩们来回答上面的问题。将模式匹配放在WHERE子中而不是放到HAVING字句中显然更高效。因为这样只需要对WHERE选出来的记录执行GROUP操作和HAVING过滤而不是對所有的记录执行。
更新数据用UPDATE命令更新只能修改已有的记录。
UPDATE后跟要修改的表名然后是SET以及后面的表达式,表达式之间用逗号汾隔负责修改数据。最后是可选的查询条件意味着可以限定修改的范围,也可以全部修改
使用DELETE命令删除一行,也就整条记录
朂后,删除命令也可以不带查询条件
这样的命令将偷偷删除表中的所有记录,不会有任何提示所以如果不是脑子抽风尽量碰它。