Postgresql中null值和空字符串

news2025/1/18 9:05:29

NULL和空字符串不同数据库的表现

null和空字符串在不同的数据库中表现不一样,找了一张图,可以很清晰的对比了解。
在这里插入图片描述
首先null不是一个空字符串,也不是一个为零的值,上图,Oracle将NULL和空字符串都视为NULL。PostgreSQL将NULL视为NULL,将空字符串视为空字符串。与PostgreSQL类似,SQL Server也将NULL视为NULL,将空字符串视为空字符串。

Oracle需要一个字节来存储NULL。然而,PostgreSQL和SQL Server都不需要任何空间来存储NULL。

在Oracle中,存在唯一约束的列可以存储任意数量的NULL项和空字符串。
在SQL Server中,在一个列上存在唯一约束时,只允许插入一个NULL和一个空字符串。
在PostgreSQL中,允许插入多个类似于Oracle的NULL值。与SQL Server类似,PostgreSQL的列存在唯一约束时,只允许一个空字符串。

oracle和SQL Server不一一举例,pg中例子如下:

#pg中,列b虽然有唯一越苏,但可以插入多个null值
postgres=# create table tab(a bigint,b text, UNIQUE(b));
CREATE TABLE
postgres=# insert into tab values(1,null);
INSERT 0 1
postgres=# insert into tab values(1,null);
INSERT 0 1
#但是不能插入多个空字符串
postgres=# insert into tab values(2,'');
INSERT 0 1
postgres=# insert into tab values(2,'');
ERROR:  duplicate key value violates unique constraint "tab_b_key"
DETAIL:  Key (b)=() already exists.

从PostgreSQL 15开始,我们可以使用NULLS NOT DISTINCT子句来防止null值被处理为DISTINCT。这可以防止我们在具有唯一约束的列中插入多个空值。

支持以下可选项:
NULLS NOT DISTINCT null也被认为是等同于null的, unique字段不能存多个null值;
NULLS DISTINCT 保持向后兼容, unique字段可以存储多个null值.

创建索引也支持该选项
CREATE UNIQUE INDEX unique_idx1 ON unique_tbl (i) NULLS DISTINCT;
CREATE UNIQUE INDEX unique_idx2 ON unique_tbl (i) NULLS NOT DISTINCT;

看一下例子:

#创建测试表,插入null值,可见只能插入一个,再插违反唯一约束
postgres=# CREATE TABLE tab(a text, b text, UNIQUE NULLS NOT DISTINCT(a));
CREATE TABLE
postgres=# insert into tab values (null);
INSERT 0 1
postgres=# insert into tab values (null);
ERROR:  duplicate key value violates unique constraint "tab_a_key"
DETAIL:  Key (a)=(null) already exists.

判断和NULL值冲突的例子

有以下一张表,我们要确保a和b的组合是唯一的,并遵守以下两个规则:

  1. 如果b为NULL,那么a不能有重复的值插入
  2. 如果b不为NULL,是其它的不同值,那么a可以插入重复的值
CREATE TABLE tab (
   a integer NOT NULL,
   b integer
);

-- 可插入
INSERT INTO tab VALUES (1, NULL);
-- 由于规则1,不能插入,因为b为NULL
INSERT INTO tab VALUES (1, 2);
-- 可以插入
INSERT INTO tab VALUES (5, 2);
-- 可以插入,遵守规则2
INSERT INTO tab VALUES (5, 3);
-- 不能插入,违反规则1
INSERT INTO tab VALUES (5, NULL);
如果我们在a和b上建一个NULLS NOT DISTINCT的约束,可以实现上述要求吗?
#创建唯一索引,插入数据测试,NULLS NOT DISTINCT不符合我们想要的效果
create unique index idx_tab_a_b on tab (a,b) NULLS NOT DISTINCT;
postgres=# INSERT INTO tab VALUES (1, NULL);
INSERT 0 1
postgres=# INSERT INTO tab VALUES (1, 2);
INSERT 0 1
postgres=# INSERT INTO tab VALUES (5, 2);
INSERT 0 1
postgres=# INSERT INTO tab VALUES (5, 3);
INSERT 0 1
postgres=# INSERT INTO tab VALUES (5, NULL);
INSERT 0 1
使用Range Types实现目的
#Range Types几个实例,[]表示闭区间,包括边界,()表示开区间,不包括边界
SELECT '[2022-09-15 00:00:00,2022-09-16 00:00:00)'::tsrange;
 
                    tsrange                    
═══════════════════════════════════════════════
 ["2022-09-15 00:00:00","2022-09-16 00:00:00")
 
SELECT '[-10,10]'::int4range;
 
 int4range 
═══════════
 [-10,11)
 
SELECT '[0,)'::numrange;
 
 numrange 
══════════
 [0,)

使用排除约束替代唯一约束

# 排除约束是使用GiST索引实现的,而GiST索引又是b树索引的扩展,我们需要安装 btree_gist插件支持我们想要操作符
postgres=# CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE EXTENSION
postgres=# truncate tab ;
TRUNCATE TABLE

#解释一下下面的排它约束,该约束表示不允许插入,a相等,b构建的整数范围相重叠的行,另外int4range(b, b, '[]')表示如果b不为NULL, int4range函数将构造一个只包含b的整数范围。如果b为NULL,则得到的范围在两端都是无界的。所以这正是我们测试所需要的
postgres=# ALTER TABLE tab ADD CONSTRAINT null_unique
EXCLUDE USING gist (
   a WITH =,
   int4range(b, b, '[]') WITH &&
);
ALTER TABLE
postgres=# INSERT INTO tab VALUES (1, NULL);
INSERT 0 1
postgres=# INSERT INTO tab VALUES (1, 2);
ERROR:  conflicting key value violates exclusion constraint "null_unique"
DETAIL:  Key (a, int4range(b, b, '[]'::text))=(1, [2,3)) conflicts with existing key (a, int4range(b, b, '[]'::text))=(1, (,)).
postgres=# INSERT INTO tab VALUES (5, 2);
INSERT 0 1
postgres=# INSERT INTO tab VALUES (5, 3);
INSERT 0 1
postgres=# INSERT INTO tab VALUES (5, NULL);
ERROR:  conflicting key value violates exclusion constraint "null_unique"
DETAIL:  Key (a, int4range(b, b, '[]'::text))=(5, (,)) conflicts with existing key (a, int4range(b, b, '[]'::text))=(5, [2,3)).

由上可见:

  1. 在已知的情况下,不要使用NULL值表示任何含义,这将使得我们数据的操作更加复杂
  2. 如果使用B树索引的唯一约束不行,可以考虑使用GiST索引中通用的排它约束
  3. 范围数据类型的灵活使用

参考:
https://www.postgresql.org/docs/current/rangetypes.html
https://www.postgresql.org/docs/current/btree-gist.html
https://www.cybertec-postgresql.com/en/unique-constraint-null-conflicts-with-everything/
https://www.migops.com/blog/null-and-empty-string-in-oracle-vs-postgresql-vs-sql-server/

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

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

相关文章

UDP协议详解

目录 前言: 再谈协议 UDP协议 比较知名的校验和 小结: 前言: UDP和TCP作为传输层非常知名的两个协议,那么将数据从应用层到传输层数据是怎样进行打包的?具体都会增加一些什么样的报头,下面内容详细介绍…

洛谷——P1077 摆花

【题目描述】 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共 m 盆。通过调查顾客的喜好,小明列出了顾客最喜欢的 n 种花,从 1 到 n 标号。为了在门口展出更多种花,规定第 i 种花不能超过 …

快捷键被占用了,这能忍吗?赶紧使用 OpenArk 找出元凶并干掉它!!!

文章目录一、 问题:快捷键被占用了导致影响工作效率二、OpenArk2.1 OpenArk简介功能发布官方链接2.2 下载OpenArk2.3 运行OpenArk2.4 被占用的热键元凶到底是谁?三、总结一、 问题:快捷键被占用了导致影响工作效率 你是否遇到过,…

用ChatGPT构建网络设备表,并根据设备关系生成网络拓扑

构造一个数据表,存储包括交换机、路由器、防火墙、入侵检测、上网行为管理等设备的编号、序列号、IP、MAC、访问地址、用户名、密码、管理员、物理位置、上联设备ip等信息下面是一个示例数据表:Device IDSerial NumberIPMACAccess URLUsernamePasswordAd…

一文教会你如何选择远程桌面(五大主流远程软件全面讲解)

写在前面 作为程序员的我们,随时随地写代码改代码是我们的日常。刚回到家,就被老板、产品经理cue是常有的事。基于这种情况,一般都会随身携带电脑,随时备战,不过每天背着电脑上下班非常不方便。因此资深程序员的解决方…

高通开发系列 - linux kernel更新msm-3.18升至msm-4.9

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 linux kernel更新msm-3.18升至msm-4.9第一周处理的内容:第二周处理的内容第三周处理的内容linux kernel更新msm-3.18升至msm-4.9 第…

洗地机怎么选?洗地机品牌排行榜

洗地机的出现不仅能高效的清洁地面还能节省我们做家务的时间,对于上班族、有宠物的家庭以及宝妈来说简直不要太方便;目前市面上的洗地机有分有线款和无线款,无线款会比有线款操作更加方便;洗地机怎么选,其实洗地机的清洁能力主要是看吸力大小…

C++:map和set的认识和简单使用/关联式容器

关联式容器 关联式容器即是用来存储数据的&#xff0c;并且存储的是<Key&#xff0c;Value>结构的键值对&#xff0c;在数据检索时效率比序列式容器高。 序列式容器也就是vector、list、queue等容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面存储的是…

虹科案例 | 对症下药,零售行业BI解决方案及实操案例!

数据源多难以整合&#xff1f; 无法实时访问数据&#xff1f; 数据分析难、价值共享难&#xff1f; 面对大量的数据&#xff0c;企业愈发头疼&#xff0c;尤其是零售行业。虹科Domo商业智能分析工具“对症下药”&#xff0c;为零售企业海量数据问题提供解决方案。 一、零售行业…

如何使用CRM做好交付项目管理

在企业客户生命旅程中&#xff0c;项目实施期是最为关键的阶段之一。项目交付物是衡量实施过程质量的重要指标之一。项目交付物也是项目实施过程中体现项目成果的重要依据&#xff0c;项目交付物还是项目实施全生命周期过程管理的综合结晶&#xff0c;所以项目过程管理中项目交…

nslookup命令使用技巧

前言 nslookup是一个DNS查询工具&#xff0c;可以指定查询的类型&#xff0c;可以查到DNS记录的生存时间&#xff0c;还可以指定使用哪个DNS服务器进行解释。 一、缺省查询 不指定 dns-server&#xff0c;使用系统默认的 dns 服务器。 nslookup 域名 通过上述命令的执行结果…

设计「业务」与「技术」方案

三天研发&#xff0c;两天设计&#xff1b; 01【优先做设计方案】 职场中的那些魔幻操作&#xff0c;研发最烦的是哪个&#xff1f; 作为一个数年且资深的互联网普通开发&#xff0c;可以来说明一下为什么是&#xff1a;缺乏设计&#xff1b; 面对业务需求的时候&#xff0c…

使用Vuex实现商品列表的校验、添加、删除、统计

场景&#xff1a;使用Vuex实现一个商品列表的添加、删除以及利用Vuex中的getters属性计算商品列表的总数总价格 添加商品时判断当前商品列表中是否包含了相同的商品 添加商品时&#xff0c;对添加表单做了校验 Vuex的使用及原理已经在上篇文章中介绍过了 vue2.x中使用vuex_前端…

XLSX插件使用 — 导入导出(含中文表头)(React+Antd 对上传表格做数据格式验证)

需求说明 1.需要前端做数据导出&#xff08;非调用接口&#xff09; 2.需要对上传的表格数据做验证&#xff0c;不通过验证需要提示格式不正确&#xff0c;阻拦上传 技术栈介绍 ReactAntdesignXLSX js-xlsx 介绍 由SheetJS出品的js-xlsx是一款非常方便的只需要纯JS即可读取…

Kafka技术认知

文章目录概念理解名词解释基本架构工作流程Kafka的特性概念理解 Kafka是分布式的基于发布-订阅消息队列。是一个分布式、支持分区的、多副本的&#xff0c;基于 Zookeeper 协调的分布式消息中间件系统&#xff0c;它的最大的特性就是可以实时的处理大量数据以满足各种需求场景…

FISCO BCOS 搭建区块链,在SpringBoot中调用合约

一、搭建区块链 使用的是FISCO BCOS 和 WeBASE-Front来搭建区块链&#xff0c;详细教程&#xff1a; https://blog.csdn.net/yueyue763184/article/details/128924144?spm1001.2014.3001.5501 搭建好能达到下图效果即可&#xff1a; 二、部署智能合约与导出java文件、SDK证…

【C语言】程序环境和预处理

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情 &#x1f6f8;C语言专栏&#xff1a;https://blog.csdn.net/vhhhbb/category_12174730.html 小苏希望大家能从这篇文章中收获到许…

决策树和期望货币价值

1、决策树和期望货币价值&#xff08;决策树、表&#xff09;---风险管理决策树分析是风险分析过程中的一项常用技术。某企业在项目风险分析过程中&#xff0c;采用了决策树分析方法&#xff0c;并计算出了EMV&#xff08;期望货币值&#xff09;。以下说法中&#xff0c;正确的…

使用 OpenAI 的 ChatGPT 提高开发人员的工作效率

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 介绍 作为一名开发人…

第十天栈和队列

栈和队列的原理大家应该很熟悉了&#xff0c;队列是先进先出&#xff0c;栈是先进后出。首先大家要知道 栈和队列是STL&#xff08;C标准库&#xff09;里面的两个数据结构。接下来介绍的栈和队列也是SGI STL里面的数据结构&#xff0c; 知道了使用版本&#xff0c;才知道对应的…