SQLite -- 一个遵守君子协定的数据库

用惯了Oracle、PostgreSQL等数据库,今天接触到SQLite,简单尝试了下使用,顿感震惊!!!
与传统的关系型数据库(如 MySQL、PostgreSQL 等)相比,它的约束是真的宽松。具体来说:在 SQLite 中,数据类型没有严格的约束,这意味着 SQLite 不会强制执行列的类型约束,你可以向任何列插入任何类型的数据,而 SQLite 会根据数据的内容自动选择存储方式。

文章目录

      • 1. SQLite 的底层类型:五个存储类
      • 2. SQLite 的类型约束:宽松无力
      • 3. 列类型的亲和性规则:声明成底层类也不能保证数据类型
      • 4. 实例演示:数据类型有多宽松?!
      • 5. 如何让它有所约束?
        • 5.1 使用触发器(Triggers)进行类型检查
        • 5.2 使用 `CHECK` 约束
      • 6. 总结

1. SQLite 的底层类型:五个存储类

SQLite “底层”采用了所谓的 存储类(storage classes)而非传统意义上的数据类型。SQLite 中的存储类有以下几种:

  • NULL:表示无值。
  • INTEGER:用于存储整数。
  • REAL:用于存储浮点数(通常为 8 字节浮动点数)。
  • TEXT:用于存储文本数据(以 UTF-8 或 UTF-16 编码)。
  • BLOB:用于存储二进制数据。

2. SQLite 的类型约束:宽松无力

SQLite 支持在表中定义列的数据类型,但这并不是强制的,也不起约束作用,甚至你可以不指定或者随便起个名字。
SQLite 使用一种称为 类型亲和性(type affinity)的机制来决定如何存储数据。

  • 类型亲和性:列的数据类型与实际存储的类型可能并不完全匹配。SQLite 会根据列定义的类型和实际插入的数据类型来自动选择存储的格式。这意味着,即使你定义了一个列为 INTEGER 类型,实际上也可以向该列插入 TEXT 类型的字符串。

例如:

CREATE TABLE users (id INTEGER PRIMARY KEY,name TEXT
);

虽然 id 列被定义为 INTEGER,但是你仍然可以插入 TEXT 类型的值:

INSERT INTO users (id, name) VALUES ('string_id', 'Alice');

SQLite 会存储该值为文本,而不是整数。这是因为 SQLite 的类型系统更宽松,允许存储不同类型的数据,即使它与列定义的类型不匹配。

3. 列类型的亲和性规则:声明成底层类也不能保证数据类型

SQLite 会根据列的声明类型选择最适合存储数据的存储类,以下是 SQLite 的 类型亲和性规则

  • NULL 类型亲和性:列声明为 NULL 类型时,SQLite 不会强制约束数据类型,任何数据类型都可以插入。
  • INTEGER 类型亲和性:INTEGER 列优先接受整数值,但也可以接受其他类型的值,如 TEXTREAL 等,SQLite 会根据需要进行转换。
  • TEXT 类型亲和性:TEXT 列优先接受文本数据,但也可以接受整数、浮点数等类型,SQLite 会进行转换。
  • REAL 类型亲和性:REAL 列优先接受浮点数,但也可以接受整数或文本类型,SQLite 会进行转换。
  • BLOB 类型亲和性:BLOB 列用于存储原始二进制数据,不会进行任何转换。

4. 实例演示:数据类型有多宽松?!

假设我们创建了一个表,定义了不同类型的列:

CREATE TABLE test (id INTEGER,name helloWorld, -- 不指定也可以age INTEGER
);

你可以插入与列定义类型不匹配的数据:

-- 向 id 列插入字符串
INSERT INTO test (id, name, age) VALUES ('abc', 'Alice', 30);-- 向 age 列插入浮动数
INSERT INTO test (id, name, age) VALUES (1, 'Bob', 25.5);

上述 SQL 语句不会引发错误,因为 SQLite 允许插入与列类型不匹配的值,并会自动进行类型转换:

  • 在第一个插入中,'abc' 被存储为文本,而不是整数。
  • 在第二个插入中,25.5(浮点数)会存储为 REAL 类型,尽管 age 列被定义为 INTEGER 类型。

5. 如何让它有所约束?

虽然 SQLite 不会强制执行列的类型约束,但仍然可以通过以下几种方式来规范化:

5.1 使用触发器(Triggers)进行类型检查

可以使用触发器来检查数据的类型,并在不符合要求时触发错误。例如,假设你希望 age 列只接受整数,可以创建一个触发器来检查插入的数据类型:

CREATE TRIGGER check_age_type
BEFORE INSERT ON test
FOR EACH ROW
BEGIN-- 检查插入数据的 age 列是否为整数SELECTCASEWHEN NEW.age NOT LIKE '%[^0-9]%' THEN NULL  -- 确保 age 为数字ELSE RAISE(ABORT, 'age must be an integer') -- 否则中止END;
END;
5.2 使用 CHECK 约束

虽然 SQLite 对类型不强制约束,但可以使用 CHECK 约束来控制列的数据范围。例如,要求 age 列只允许正整数值:

CREATE TABLE test (id INTEGER,name TEXT,age INTEGER CHECK(age > 0) CHECK(typeof(age) = 'integer') 
);

这个 CHECK 约束可以确保 age 列只能插入大于 0 的整数,且保证不能随便插数据进去。

6. 总结

SQLite 的数据类型约束相对宽松,它采用的是动态类型系统。虽然你可以为列定义数据类型,但SQLite 不会严格地检查插入数据的类型。如果你定义一个 INTEGER 列,可以插入文本、浮点数、整数等类型的数据,SQLite 会根据需要自动转换这些数据。

这种宽松的设计使得 SQLite 非常灵活,适合嵌入式应用或轻量级的数据库需求,但也可能导致数据的一致性和准确性问题,特别是当你希望强制执行类型安全时。为了增强数据的正确性,开发者可以使用触发器和 CHECK 约束来手动控制数据类型。

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

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

相关文章

Linux 高级IO

学习任务: 高级 I/O:select、poll、epoll、mmap、munmap 要求: 学习高级 I/O 的用法,并实操 1、高级 I/O: 前置知识: 阻塞、I/O 多路复用 PS: 非阻塞 I/O ------ 非阻塞 I/O 阻塞其实就是进入了休眠状态&am…

JAVA WEB — HTML CSS 入门学习

本文为JAVAWEB 关于HTML 的基础学习 一 概述 HTML 超文本标记语言 超文本 超越文本的限制 比普通文本更强大 除了文字信息 还可以存储图片 音频 视频等标记语言 由标签构成的语言HTML标签都是预定义的 HTML直接在浏览器中运行 在浏览器解析 CSS 是一种用来表现HTML或XML等文…

ASRPRO 日历2

为避免与天问的ID冲突 ID前加10000 为使识别更顺畅 将 日期-月份 12月21日 合并 ;时间 10点25分 合并 通过串口获取日期 为使用常用词 计倒时 下周 明天,需通过串口获取当前日期 + 命令词 增加 我的 A的 B的 关系词 与任务 生日 买菜 增加 可自定义 任务 执行程序 双进…

Linux——Linux基础指令

Linux基本指令 文章目录 Linux基本指令1. 基础五指令(1) whoami(2) who(3) pwd(4) ls(5) clear 2. 文件常见命令(1) touch(2) mkdir(3) cp(4) mv(5) rm(6) cd 3. 常见IO命令(1) cat(2) tac(3) head(4) tail(5) more(6) less 4. 拓展命令(1) man手册(2) which(3) file(4) date(5…

雷池社区版 7.1.0 LTS 发布了

LTS(Long Term Support,长期支持版本)是软件开发中的一个概念,表示该版本将获得较长时间的支持和更新,通常包含稳定性、性能改进和安全修复,但不包含频繁的新特性更新。 作为最受欢迎的社区waf&#xff0c…

出海企业如何借助云计算平台实现多区域部署?

云计算de小白 如需进一步了解,请单击链接了解有关 Akamai 云计算的更多信息 在本文中我们将告诉大家如何在Linode云计算平台上借助VLAN快速实现多地域部署。 首先我们需要明确一些基本概念和思想: 部署多区域 VLAN 为了在多区域部署中在不同的 VLAN …

RDD转换算子:【map】

功能: 对RDD中每个元素调用一次参数中的函数,并将每次调用的返回值放入一个新的RDD中(一对一) 语法: def map(self , f: T -> U ) -> RDD[U]f:代表参数是一个函数 T:代表RDD中的每个元…

如何更好的crud

一、DDD是什么? DDD全名叫做Domins drives Design;领域驱动设计。再说的通俗一点就是:通过领域建模的方式来实现软件设计。 问题来了:什么是软件设计?为什么要进行软件设计? 软件开发最主要的目的就是&…

AI赋能酒店设计|莱佛士学生成功入围WATG设计大赛

近日,由Wimberly Allison Tong & Goo(WATG)主办的“用人工智能重新构想酒店行业的未来”设计比赛正式拉开帷幕。这场设计比赛,不仅是为了庆祝WATG即将步入80周年,更是为了激发年轻设计师们的创造力和探索实践精神&…

Netty原来就是这样啊(二)

前言: Netty其实最大的特点就是在于对于对NIO进行了进一步的封装,除此以外Netty的特点就是在于其的高性能 高可用性,下面就会一一进行说明。 高性能: 我在Netty原来就是这样啊(一)-CSDN博客 解释了其中的零拷贝的技术除此以外还有Reactor线程模型,这个Reactor线程模型的思想…

对于相对速度的重新理解

狭义相对论速度合成公式如下, 现在让我们尝试用另一种方式把它推导出来。 我们先看速度的定义, 常规的速度合成方式如下, 如果我们用速度的倒数来理解速度, 原来的两个相对速度合成, 是因为假定了时间单位是一样的&am…

idea 导入Spring源码遇到的坑并解决

1.下载相关文件 通过百度网盘分享的文件:Spring 链接:https://pan.baidu.com/s/1r9rkGOCaY9SFn9ecng5cIg?pwd8888 提取码:8888 2.配置gradle环境 gradle下载地址 需要翻墙下 https://services.gradle.org/distributions/ 我选择的是 grad…

红队-linux基础(1)

声明 通过学习 泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频,做出的文章如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 一.openssl 1、openssl passwd -1 123 openssl是一个开源的…

迈入国际舞台,AORO M8防爆手机获国际IECEx、欧盟ATEX防爆认证

近日,深圳市遨游通讯设备有限公司(以下简称“遨游通讯”)旗下5G防爆手机——AORO M8,通过了CSA集团的严格测试和评估,荣获国际IECEx及欧盟ATEX防爆认证证书。2024年11月5日,CSA集团和遨游通讯双方领导在遨游…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十八集补充:制作空洞骑士独有的EventSystem和InputModule

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、制作空洞骑士独有的EventSystem和InputModule总结 前言 hello大家好久没见,之所以隔了这么久才更新并不是因为我又放弃了这个项目,而…

你们要的App电量分析测试来了

Batterystats 是包含在 Android 框架中的一种工具,用于收集设备上的电池数据。您可以使用 adb 将收集的电池数据转储到开发计算机,并创建一份可使用 Battery Historian 分析的报告。Battery Historian 会将报告从 Batterystats 转换为可在浏览器中查看的…

<项目代码>YOLOv8 学生课堂行为识别<目标检测

YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…

如何在家庭网络中设置静态IP地址:一份实用指南

在家庭网络环境中,IP地址扮演着至关重要的角色。大多数家庭用户依赖路由器的DHCP(动态主机配置协议)来自动分配IP地址,但在某些情况下,手动设置静态IP地址能为家庭网络带来更多的便利性与稳定性,尤其是在涉…

编译cartographer和cartographer_ros 过程

环境 ros 版本 : noetic 工控机版本: firefly 工控机cpu类型: arm64 工控机系统: ubuntu 20.04 关于cartographer 如果是ros1中cartographer和cartographer_ros 都需要编译安装,并且在实际运行中cartographer和cartographer_ros 是有交互的。 而如果是在ros2中只…

vue系列==vue组件

vue系列vue组件 1、组件样式控制 1.1全局样式控制 1.2局部样式控制 1.3深度样式控制 2、组件通信 2.1组件父与子之间的通信props 2.1.1简单数组接收模式 2.1.2简单对象和复杂对象接受模式 2.2 组件通信之ref与defineExpose ref 的作用 defineExpose 的作用 运用 re…