以”0()”为起始的PostgreSQL

首先

对不起,这不是一篇从零开始学习PostgreSQL的入门文章。
很抱歉标题可能误导了。

我将在PostgreSQL中写关于0的故事。

最小的桌子设置

SQL是一种用于从多个表中获取一个表格的语言。
SQL所涉及的表格结构由行和列组成。

列1列2列3行1行1行1行2行2行2行3行3行3

最小的表格构成是什么?理论上来说,0行0列的表格是最小的表格构成。在这种情况下,0并不是指数组中的第一个元素[0],而是类似于长度为0的数组[]。

行0的桌子 de zhuō zi)

行数为0的表是非常常见的。在通常的搜索中,如果搜索条件不匹配,则会返回一个行数为0的结果表;而使用CREATE TABLE创建的表,行数也是0。

零列的表格

通常情况下,我们不会看到具有零列的表。因为零列的表无法存储任何值,所以没有必要特意创建它们。
在标准的SQL中,似乎无法创建零列的表,大多数关系型数据库也无法创建零列的表。

然而,在PostgreSQL中,您可以创建具有0列的表。

CREATE TABLE zero_column ();

PostgreSQL 7.4明确表示可以创建零列的表。

作为一种思考方式,通过使用 ALTER TABLE 表名 DROP COLUMN 列名 可以删除列并创建一个列数为0的表。因此,为了避免出现即使存在列也不成为列数为0的情况,PostgreSQL选择允许列数为0的情况。

因此,在其他编程语言中经常会创建一个空的可变长度数组(切片)并稍后向其中添加元素的便利性,理论上在PostgreSQL中也可以首先创建一个空表,然后逐步添加列。

CREATE TABLE add_user ();
ALTER TABLE add_user ADD COLUMN id SERIAL;
ALTER TABLE add_user ADD COLUMN name TEXT;
ALTER TABLE add_user ADD COLUMN age INT;

嗯,由于各种情况,通常情况下我们不这样做,对于数据库管理员来说可能会像是噩梦一样看待…

INSERT是否支持在第0列进行操作?

所以,也许你可能不明白这个意思,但是你也可以在列为0的表中添加行。
然而,你不能使用INSERT INTO zero_column VALUES ();或INSERT INTO zero_columns () VALUES ();来添加。
你知道该如何写吗?请想一想,我会折叠起来等你。

插入默认值到零列;
向零列插入默认值。

此外,现在也可以使用SELECT将列表清空(此功能从PostgreSQL 9.4版本开始)。

SELECT FROM anther_table;

那么,这是在第0列的表中添加行的另一种方法。

通过以下方法,在第0列插入行:
INSERT INTO zero_column SELECT FROM anther_table;使用这种方式可以创建一个有多行零列的表。

最小的选择

已知SELECT语句中可以省略FROM子句。由于SELECT列表也可以为空,因此最简单的SELECT语句如下:

SELECT;

如果在psql中执行这个命令,结果将如下所示。

postgres=# SELECT;
--
(1 row)

可能会有人对结果产生疑问。SELECT的结果不是一个0列0行的表,而是一个0列1行(row)的表。
当SELECT语句省略FROM子句时,通常用于返回类似SELECT ‘TEST’,1+2这样的常数。
换句话说,如果在SELECT语句中省略FROM子句,可以考虑生成1行(或更多)的表,因此会返回一个0列1行的表。

有多种方法可以将行变为0,当想要返回0列0行时(虽然有几种方法可选择),我想到了以下的解决方案。

从语句的角度来看,返回0列0行的SELECT语句会比返回0列1行更长,这是很有趣的。
顺便提一下,似乎在psql中,列数为0的表不会被显示出来(包括换行)。
SELECT FROM zero_column ;

(6 行)这是客户端显示方式的问题,如果用我的trdsql以JSON格式输出,将会显示如下:
$ trdsql -driver postgres -ojson “SELECT FROM zero_column”
[
{},
{},
{},
{},
{},
{}
]

PostgreSQL虽然支持零列,但根据SQL标准(除非内部的情况),不支持零列,因此是否支持零列取决于语法。接下来我们将对此进行讨论。

SELECT COUNT函数是否支持0列?

可以将 SELECT 列表设置为空,但是不能将 COUNT 函数设置为空。

SELECT count() FROM zero_column ;
ERROR:  42809: count(*) must be used to call a parameterless aggregate function
LINE 1: SELECT count() FROM zero_column ;
               ^
LOCATION:  ParseFuncOrColumn, parse_func.c:788

在使用COUNT(*)函数时,会正确返回行数。

SELECT count(*) FROM zero_column
 count 
-------
     6
(1 row)

我认为*是指列表的所有内容,但实际上更为复杂。手册中写道如下:

https://www.postgresql.jp/document/current/html/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS 这个链接介绍了在一些上下文中使用星号(*)来表示表行或复合类型的所有字段。此外,当用作聚合函数的参数时,它还有一个特殊的意义,即表示该聚合不需要显式参数。

COUNT是一个聚合函数,因此具有特殊的含义。

VALUES是否对应于第0列?

在PostgreSQL中,可以单独使用VALUES。VALUES用于将常量转换为表格,类似于省略SELECT语句的FROM子句时的情况。

VALUES(1,'a');
 column1 | column2 
---------+---------
       1 | a
(1 row)

我原以为可以使用VALUES来创建一个没有列的表,但是出现了错误。

VALUES();
ERROR:  42601: syntax error at or near ")"
LINE 1: values();
               ^
LOCATION:  scanner_yyerror, scan.l:1176

我找到了导致 INSERT INTO zero_column VALUES (); 出错的原因了。

DELETE对应于第0列吗?

如果省略WHERE子句,DELETE语句将正常工作并删除表中的所有行。

DELETE FROM zero_column ;
DELETE 6

假设有一个拥有6行的0列,能够删除第3行吗?

你在说什么?这个案子,我试着用最后的办法写了一下。

删除第0列的第3行DELETE从zero_column中选择ctid;
ctid
——–
(0,7)
(0,8)
(0,9) <– 想要删除这个
(0,10)
(0,11)
(0,12)
(6 行)

DELETE FROM zero_column WHERE ctid = ‘(0,9)’;
DELETE 1

我想到的其他方法都失败了。

更新是否支持第0列?

真的搞不懂。穆利。

总结

SELECT FROM オチ;
--
(1 rows)
广告
将在 10 秒后关闭
bannerAds