【PostgreSQL】从零开始:(三十一)数据类型-复合类型

复合类型

复合类型是一种由其他类型组成的类型。它可以是数组、结构体、联合体或指向这些类型的指针。复合类型允许将多个值组合成单个实体,以便更方便地处理和使用。复合类型在C语言中非常常见,用于表示复杂的数据结构和组织数据的方式。

数组是一种由相同类型的元素组成的复合类型。它有固定大小,并且可以通过索引访问其中的元素。数组在C语言中非常常用,用于存储和处理一组相同类型的数据。

结构体是一种由多个不同类型的成员组成的复合类型。结构体可以用于表示一个实体的多个属性或数据项。每个成员都可以具有不同的数据类型,结构体中的成员可以通过点运算符来访问。

联合体是一种特殊的结构体,它的所有成员共享同一块内存空间。只能同时存储一个成员的值,而且根据存储的数据类型来确定如何解释这块内存。

指针是一种特殊的复合类型,它保存了一个变量的内存地址。指针可以指向任何其他类型的数据,包括数组、结构体和函数。通过指针,可以间接访问指向的数据,并进行对数据的操作。

复合类型在C语言中提供了更多的灵活性和功能,使得程序员可以更好地组织和处理数据。

postgresql中的复合类型

PostgreSQL支持复合类型,也称为复合数据类型。复合类型是一种创建用户自定义数据类型的方式,它可以包含多个字段,每个字段可以有不同的数据类型。

CREATE TYPE complex AS (r       double precision,i       double precision
);CREATE TYPE inventory_item AS (name            text,supplier_id     integer,price           numeric
);

语法与 类似,只是只能指定字段名称和类型;目前不能包含任何约束(例如 )。请注意,关键字是必不可少的;没有它,系统会认为是另一种命令,你会得到奇怪的语法错误。CREATE TABLENOT NULLASCREATE TYPE

定义类型后,我们可以使用它们来创建表:

CREATE TABLE on_hand (item      inventory_item,count     integer
);INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000);

或功能:

CREATE TABLE inventory_item (name            text,supplier_id     integer REFERENCES suppliers,price           numeric CHECK (price > 0)
);

然后,上面所示的相同复合类型将作为副产品出现,并且可以像上面一样使用。但请注意当前实现的一个重要限制:由于没有约束与复合类型关联,因此表定义中显示的约束不适用于表外部的复合类型的值。若要解决此问题,请在复合类型上创建一个域,并将所需约束应用为域的约束。

构造复合值

若要将复合值写为文本常量,请将字段值括在括号内,并用逗号分隔。您可以在任何字段值两边加上双引号,如果它包含逗号或括号,则必须这样做。因此,复合常量的一般格式如下:

'( val1 , val2 , ... )'

例如:

'("fuzzy dice",42,1.99)'

这将是上面定义的类型的有效值。若要使字段为 NULL,请在列表中的位置完全不写入任何字符。例如,此常量指定 NULL 第三个字段:

'("fuzzy dice",42,)'

如果需要空字符串而不是 NULL,请写双引号:

'("",42,)'

这里第一个字段是非 NULL 空字符串,第三个字段是 NULL。
表达式语法还可用于构造复合值。在大多数情况下,这比字符串文字语法使用起来要简单得多,因为您不必担心多层引用。我们已经在上面使用了这种方法:ROW

ROW('fuzzy dice', 42, 1.99)
ROW('', 42, NULL)

只要表达式中有多个字段,ROW 关键字实际上是可选的,因此可以将其简化为:

ROW('fuzzy dice', 42, 1.99)
ROW('', 42, NULL)

只要表达式中有多个字段,ROW 关键字实际上是可选的,因此可以将其简化为:

('fuzzy dice', 42, 1.99)
('', 42, NULL)

访问复合类型

要访问复合列的字段,需要写入一个点和字段名称,就像从表名中选择字段一样。事实上,这很像从表名中进行选择,因此您经常必须使用括号来防止混淆解析器。例如on_hand,您可以尝试从示例表中选择一些子字段,如下所示:

SELECT item.name FROM on_hand WHERE item.price > 9.99;

这是行不通的,因为根据 SQL 语法规则,该名称是表名,而不是on_hand的列名。你必须这样写:

SELECT (item).name FROM on_hand WHERE (item).price > 9.99;

或者,如果您还需要使用表名(例如在多表查询中),如下所示:

SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99;

现在,括号中的对象被正确地解释为对列的引用,然后可以从中选择子字段。
每当从复合值中选择字段时,类似的语法问题都会适用。例如,要从返回复合值的函数的结果中只选择一个字段,您需要编写如下内容:

SELECT (my_func(...)).field FROM ...

如果没有额外的括号,这将生成语法错误。

修改复合类型

下面是插入和更新复合列的正确语法的一些示例。首先,插入或更新整个列:

INSERT INTO mytab (complex_col) VALUES((1.1,2.2));UPDATE mytab SET complex_col = ROW(1.1,2.2) WHERE ...;

第一个示例省略 ,第二个示例使用它;我们本可以以任何一种方式做到这一点。ROW

我们可以更新复合列的单个子字段:

UPDATE mytab SET complex_col.r = (complex_col).r + 1 WHERE ...;

请注意,这里我们不需要SET(实际上也不能)在紧接着出现的列名周围加上括号,但是在等号右侧的表达式中引用同一列时,我们确实需要括号。

我们也可以将子字段指定为INSERT的目标:

INSERT INTO mytab (complex_col.r, complex_col.i) VALUES(1.1, 2.2);

如果我们没有为列的所有子字段提供值,则其余子字段将填充 null 值。

查询复合类型

查询中存在与复合类型关联的各种特殊语法规则和行为。这些规则提供了有用的快捷方式,但如果您不知道它们背后的逻辑,可能会造成混淆。

在 PostgreSQL 中,查询中对表名(或别名)的引用实际上是对表当前行的复合值的引用。例如inventory_item,如果我们有一个如上所示的表,我们可以这样写:

SELECT c FROM inventory_item c;

此查询生成单个复合值列,因此我们可能会得到如下输出:

           c
------------------------("fuzzy dice",42,1.99)
(1 row)

但请注意,简单名称与表名之前的列名匹配,因此此示例之所以有效,是因为查询的表中没有命名的列。c

普通的限定列名语法table_name column_name可以理解为将字段选择应用于表当前行的复合值。(出于效率原因,它实际上不是以这种方式实现的。.

当我们写

SELECT c.* FROM inventory_item c;

然后,根据 SQL 标准,我们应该将表的内容扩展为单独的列:

    name    | supplier_id | price
------------+-------------+-------fuzzy dice |          42 |  1.99
(1 row)

就好像查询是

ELECT c.name, c.supplier_id, c.price FROM inventory_item c;

PostgreSQL 会将此扩展行为应用于任何复合值表达式,尽管如上所示,只要它不是简单的表名,您就需要在应用的值周围写括号。例如,如果是一个函数返回包含列. 、* 和myfunc()的复合类型,则这两个查询具有相同的结果:abc

SELECT (myfunc(x)).* FROM some_table;
SELECT (myfunc(x)).a, (myfunc(x)).b, (myfunc(x)).c FROM some_table;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/581732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python的二分查找库bisect,可用于简化繁琐的if条件分支

if条件分支的函数 之前实现了一个函数功能&#xff0c;大意是根据不同的时间天数&#xff0c;返回不同的值。 def analyse_value(days_num:int):if days_num 1:value RD1delif days_num > 1 and days_num < 7:value RD7delif days_num > 7 and days_num < 14:…

C++智能指针的简单实现,原理及应用

1. 为什么C引入了智能指针&#xff1f; 在C中&#xff0c;引入智能指针主要是为了解决原始指针在使用过程中可能出现的内存泄漏问题。内存泄漏是程序在申请内存后&#xff0c;无法释放已分配的内存&#xff0c;导致内存被无效占用&#xff0c;严重时可能导致系统运行缓慢甚至崩…

Redis6.0 Client-Side缓存是什么

前言 Redis在其6.0版本中加入了Client-side caching的支持&#xff0c;开启该功能后&#xff0c;Redis可以将指定的key-value缓存在客户端侧&#xff0c;这样当客户端发起请求时&#xff0c;如果客户端侧存在缓存&#xff0c;则无需请求Redis Server端。 Why Client-side Cac…

【每日一题】【12.24】 - 【12.28】

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 本周总结&#xff1a;本周的每日一题比较针对于数学问题的一个应用&#xff0c;如二元一次方程组的求解或者数组求和&#xff0c;同…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用UserSet功能保存和载入相机的各类参数(C++)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用UserSet功能保存和载入相机的各类参数&#xff08;C&#xff09; Baumer工业相机Baumer工业相机NEOAPISDK中UserSet的技术背景代码案例分享第一步&#xff1a;保存相机当前参数设置UserSet_Save第二步&#xff1a;载入已经保存…

C++第2关:文件读取和写入

任务描述 题目描述:从文件a.txt中读取三个整数&#xff0c;然后把这三个整数保存到b.txt中&#xff0c;两整数之间一个空格。 相关知识&#xff08;略&#xff09; 编程要求 根据提示&#xff0c;在右侧编辑器Begin-End处补充代码&#xff0c;完成本关要求。 格式如下: 10…

IDEA、VSCode等快速连接Github(Mac版)

问题描述 在本地书写✍️完代码后, 想要git push到Github上面, 出现延迟错误; 导致经常push不上去, 如下图所示; 解决方案 进入电脑终端; 输入下列命令; sudo vim /etc/hosts输入密码; 按下 I 键, 进行编辑操作; 将下列语句复制到空白区, 然后按下esc按键, 然后输入:wq即可…

矿泉水硝酸盐和溴酸盐超标解决工艺

在当今社会&#xff0c;人们对健康和优质生活的追求不断提升&#xff0c;使得瓶装饮用水的安全问题受到了广泛关注。溴酸盐和硝酸盐作为自然水体中常见的物质&#xff0c;若在矿泉水中含量过高&#xff0c;可能会对消费者的健康构成潜在威胁。因此&#xff0c;探究有效去除矿泉…

AR-HUD厂商发力下一代技术方案,vHOE为何赢得高度关注?

作为智能座舱的核心显示交互系统&#xff0c;AR-HUD正处于处于量产爆发前期&#xff0c;同时关于下一代技术方案的比拼也在全面升级。 根据《高工智能汽车研究院》数据显示&#xff0c;2023年1-9月&#xff0c;中国市场&#xff08;不含进出口&#xff09;乘用车前装标配W/AR …

区块链背后的秘密:从交易看故事

作者&#xff1a;shellyfootprint.network 在区块链的世界里&#xff0c;每一笔交易都是一个故事的开始。不只是数字的交换&#xff0c;更是用户行为、信念和决策的体现。 疯狂投机的背后&#xff0c;是短期的逐利还是长期的策略&#xff1f;协议分叉&#xff0c;真的分裂了社…

双向链表基本操作及顺序和链表总结

目录 基本函数实现 链表声明 总的函数实现声明 创建一个节点 初始化链表 打印 尾插 尾删 头插 头删 查找 pos前插入 删除pos位置 销毁链表 顺序表和链表总结 基本函数实现 链表声明 typedef int DLTDataType;typedef struct DListNode {struct DListNode* nex…

POLL机制

文章目录 一、POLL机制1、应用场景2、执行流程 二、程序1、驱动程序2、测试应用程序 三、总结 一、POLL机制 1、应用场景 使用休眠-唤醒的方式等待某个事件发生时&#xff0c;有一个缺点&#xff1a;等待的时间可能很久。我们可以加上一个超时时间&#xff0c;这时就可以使用…

CAN总线应用篇(c语言版)

一.概述 CAN&#xff08;Controller Area Network&#xff09;即控制器局域网&#xff0c;是一种能够实现分布式实时控制的串行通信网络。想到CAN就要想到德国的Bosch公司&#xff0c;因为CAN就是这个公司开发的&#xff08;和Intel&#xff09;CAN有很多优秀的特点&#xff0c…

百度CTO王海峰:文心一言用户规模破1亿

▶ 写在前面▶ 飞桨开发者已达1070万▶ 文心一言用户规模破亿&#xff0c;日提问量快速增长 ▶ 写在前面 “文心一言用户规模突破 1 亿。”12 月 28日&#xff0c;百度首席技术官、深度学习技术及应用国家工程研究中心主任王海峰在第十届 WAVE SUMMIT 深度学习开发者大会上宣布…

Python初学者必须吃透的69个内置函数!

所谓内置函数&#xff0c;就是Python提供的, 可以直接拿来直接用的函数&#xff0c;比如大家熟悉的print&#xff0c;range、input等&#xff0c;也有不是很熟&#xff0c;但是很重要的&#xff0c;如enumerate、zip、join等&#xff0c;Python内置的这些函数非常精巧且强大的&…

外贸网站建站怎么做?海洋建站有哪些步骤?

外贸网站建站需要哪些资料&#xff1f;如何选择外贸建站系统&#xff1f; 外贸企业越来越重视在线业务&#xff0c;而拥有一个专业、高效的外贸网站已经成为成功开展国际贸易的关键一步。海洋建站将为您详细介绍如何进行外贸网站建站&#xff0c;让您的企业在全球市场中脱颖而…

C++ Qt开发:QItemDelegate自定义代理组件

老规矩&#xff0c;首先推荐好书&#xff1a; Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍…

浏览器Post请求出现413 Request Entity Too Large (Nginx)

环境 操作系统 window server 2016 前端项目 Vue2 Nginx-1.25.3 一、错误信息 前端是vue项目&#xff0c;打包后部署在Nginx上&#xff0c;前端post请求出现Request Entity Too Large错误信息。 ​这种问题一般是请求实体太大&#xff08;包含参数&#xff0c;文件等&#xf…

SpringBoot集成etcd,实现实时监听,实现配置中心

etcd 是一个分布式键值对存储&#xff0c;设计用来可靠而快速的保存关键数据并提供访问。通过分布式锁&#xff0c;leader选举和写屏障(write barriers)来实现可靠的分布式协作。etcd集群是为高可用&#xff0c;持久性数据存储和检索而准备。 以下代码实现的主要业务是&#xf…

复试 || 就业day01(2023.12.27)算法篇

文章目录 前言两数之和存在重复元素 II好数对的数目总持续时间可被 60 整除的歌曲 前言 &#x1f4ab;你好&#xff0c;我是辰chen&#xff0c;本文旨在准备考研复试或就业 &#x1f4ab;文章题目大多来自于 leetcode&#xff0c;当然也可能来自洛谷或其他刷题平台 &#x1f4a…