<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel rdf:about="https://blog.anlucky.cn/index.php/feed/rss/programming/database">
<title>LuckyDu - 数据库</title>
<link>https://blog.anlucky.cn/index.php/programming/database</link>
<description>Mysql数据库，SQL语法，约束，redis数据库，关系型数据库，非关系型数据库</description>
<items>
<rdf:Seq>
<rdf:li resource="https://blog.anlucky.cn/index.php/programming/database/168"/>
<rdf:li resource="https://blog.anlucky.cn/index.php/programming/database/166"/>
<rdf:li resource="https://blog.anlucky.cn/index.php/programming/database/152"/>
<rdf:li resource="https://blog.anlucky.cn/index.php/programming/database/147"/>
<rdf:li resource="https://blog.anlucky.cn/index.php/programming/database/127"/>
<rdf:li resource="https://blog.anlucky.cn/index.php/programming/database/39"/>
</rdf:Seq>
</items>
</channel>
<item rdf:about="https://blog.anlucky.cn/index.php/programming/database/168">
<title>Redis持久化策略</title>
<link>https://blog.anlucky.cn/index.php/programming/database/168</link>
<dc:date>2023-05-28T18:34:35+08:00</dc:date>
<description>Redis持久化策略1. RDB持久化策略RDB是redis持久化数据到磁盘的策略将内存以快照形式保存Redis数据库中的数据的方式，就是某一时刻，将Redis内存中的数据全量备份到磁盘，RDB就是redis DataBase的缩写备份会不会阻塞主线程Redis是单线程数据处理，Redis提供了两个命令来生成RDB，一个是save 一个是bgsavesave 保存：会阻塞Redis主线程，直到RDB文件备份完成为止，在这个期间，Redis不能处理客户端的任何请求bgSave 保存：不会阻塞主线程，会创建一个子线程，单独我负责RDB文件的数据备份，RDB的优势和劣势优势RDB文件紧凑，全量备份，适合进行备份和灾难恢复生成RDB文件的时候，Redis主进程会分叉一个子进程来处理保存数据，主进程不需要进程IO操作RDB在恢复文件的时候要比AOP速度快2. AOF持久化策略AOF持久化策略，以文件的形式存储Redis内存中的数据，他的文件格式是AOF，他存储的数据是客户端交给Redis执行的写命令因为AOF是在文件中追加写入，由于IO操作的阻塞性，会导致主线程挂起，在写入的时间中无法服务新的请求，因而吞吐量收到影响为了解决上述的问题，Redis并不会立即将数据写入到硬盘中，</description>
</item>
<item rdf:about="https://blog.anlucky.cn/index.php/programming/database/166">
<title>Redis和Mysql如何保证数据一致性</title>
<link>https://blog.anlucky.cn/index.php/programming/database/166</link>
<dc:date>2023-05-27T20:20:46+08:00</dc:date>
<description>Redis和Mysql如何保证数据一致性1. 导致数据不一致的原因当数据发生变化的时候，需要同时去更新Redis和Mysql，更新数据是有先后顺序的，在极端情况下就会出现数据一致性的问题。1. 先更新数据库再更新缓存如果先更新数据库，若是缓存中的数据更新失败，就会出现数据库和redis中的数据不一致问题2. 先删除缓存，再更新数据库先删除缓存再更新数据库，在理想情况删除了缓存，更新了数据库，再第二次请求的时候会发现缓存是空的，会去读取数据库将数据缓存起来。但是删除缓存和更新数据库不是一个原子操作，若是缓存删除了，此时，第二条线程抢到CPU时间轮片，开始读取数据，发现没有缓存，查询数据库，并将数据缓存起来，此时第一条线程拿到CPU时间轮片，开始更新数据库，这个情况下会导致数据库和缓存不一致采用最终一致性的方案解决1. 采用延迟双删除的策略具体步骤先删除缓存写入数据库休眠500毫秒（视情况而定）再次删除缓存具体实现public void write(String key,Object data){
     redis.delKey(key); // 删除缓存
     db.updateData(data); // 更新数据库
     Thread.sleep(500); // 睡眠延迟
     redis.delKey(key);// 再次删除缓存
 }2. 异步更新缓存（基于订阅Binlog）读取MysqlBinlog日志后分析，利用消息队列，推送更新到redis缓存中，这样一旦产生了新的写入，更新，删除等操作，就可以把相关的更新推送到redis中其实这种机制类似于Mysql的主从备份，Mysql的主从备份也是通过Binlog来实现数据一致性这里的消息推送工具可以使用Kafka、rabbitMQ等消息队列来实现

结合使用canal(阿里的一款开源框架)，通过该框架可以对MySQL的binlog进行订阅因为是最终一致性，所以业务如果无法接收短期不一致性的话就得更换策略</description>
</item>
<item rdf:about="https://blog.anlucky.cn/index.php/programming/database/152">
<title>缓存穿透，缓存击穿，缓存雪崩是什么如何解决</title>
<link>https://blog.anlucky.cn/index.php/programming/database/152</link>
<dc:date>2023-05-23T20:26:11+08:00</dc:date>
<description>1. 什么是缓存穿透缓存穿透指的是一个缓存系统无法缓存某个查询的数据，从而导致这个查询每一次都要访问数据库个人理解，缓存穿透是指要访问的数据既不在缓存中，也不在数据库中，导致请求在访问缓存时没有找到对应的数据，再去请求数据库也没有找到数据，无法将数据写入缓存，这样一来缓存就变为了摆设，就会同时给缓存和数据库造成压力常见的Redis缓存穿透场景包括：查询一个不存在的数据，攻击者可能发送一些无效的查询来触发缓存穿透查询一些非常热门的数据，如果一个数据被访问的非常频繁，那么可能会导致缓存系统无法处理这些请求，从而造成缓存穿透查询一些异常数据：这种情况通常发生在数据服务出现故障或异常时，从而造成缓存系统无法访问相关数据，从而导致缓存穿透。2. 如何解决缓存穿透解决方案一缓存空值或者缺省的值一旦发生缓存穿透，我们就可以针对查询的数据，再Redis中缓存一个空值或者确定的缺省值，（就是随便一个可以表示缺省的值），紧接着，发送后续的查询的时候就可以从缓存中获取到缺省值了，保证了数据库的正常运行解决方案二使用布隆过滤器快速判断数据是否存在3. 什么是缓存击穿缓存击穿往往出现在高并发访问的情况下，一个热点数据从缓存在查不存在，就要去数据库中查询，从而导致数据库的压力过大，导致系统性能下降缓存击穿的原因通常有以下几种：缓存中不存在所需要的热点数据，每当系统中的某个热点数据需要频繁访问的时候，同时去访问数据库，给数据库造负担缓存热点的数据过期，当一个热点数据过期，并且需要重新缓存时候，若此时有大量请求也会因为缓存中的数据过期而去数据库中查询，给数据库造成负担。4. 如何解决缓存击穿解决方案一设置热点数据永不过期设置热点数据永不过期就是不给key设置过期的时间即可还有第二种方式也可以达到key值永不过期，就是正常的给key值设置过期时间，在后台启动一个定时任务在他过期前去定时地更新这个缓存，并重新设置他的过期时间解决方案二分布式锁并发更新锁的对象就是key，这样如果有大量请求并发进来时，只能有一个请求获取到锁，然后获取到锁的线程去查询数据库，将查询到的数据放入到缓存中，此时，缓存中已经有数据了，后面的请求就可以从缓存中获取到数据返回，并不会查询数据库5. 什么是缓存雪崩缓存雪崩是指大量的请求无法在Redis中进行处理，紧接着大量的请求发送到数据库层，导致数据库压力过大常见的缓存雪崩的场景：缓存服务器宕机，当缓存服务器宕机或者重启时，大量的访问请求直接命中数据库，在同一时间导致大量的数据查询，从而数据库的压力增大缓存数据同时失效，在某个特定的时间点，缓存中的数据大量失效，并在同一个时间点，有大量的请求集中在一起6. 如何解决缓存雪崩解决方案一避免给大量的数据设置相同的过期时间，如果业务层有些数据同时失效，可以给每个数据设置一个较短的过期间隔，(在不影响业务的情况下，特殊情况特殊处理)解决方案二缓存预热缓存预热就是在系统启动或者失效时，手动加载数据到缓存中，这样实际请求的时候就可以直接从缓存中获取数据</description>
</item>
<item rdf:about="https://blog.anlucky.cn/index.php/programming/database/147">
<title>Redis基础入门</title>
<link>https://blog.anlucky.cn/index.php/programming/database/147</link>
<dc:date>2023-05-15T19:12:00+08:00</dc:date>
<description>Redis基础入门0.为什么Redis是单线程还这么快？redis 是将所有的数据全部放在内存中的，所以说使用单线程去操作效率就是最高的，多线程 （CPU上下文会切换：耗时的操作！！！），对于内存系统来说，如果没有上下文切换效率就是最高 的！多次读写都是在一个CPU上的，在内存情况下，这个就是最佳的方案！1. Redis介绍Redis 是一个开源（BSD许可）的，内存中的数据结构存储系统，它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构，如 字符串（strings）， 散列（hashes）， 列表（lists）， 集合（sets）， 有序集合（sorted sets） 与范围查询， bitmaps， hyperloglogs 和 地理空间（geospatial） 索引半径查询。 Redis 内置了 复制（replication），LUA脚本（Lua scripting）， LRU驱动事件（LRU eviction），事务（transactions） 和不同级别的 磁盘持久化（persistence）， 并通过 Redis哨兵（Sentinel）和自动 分区（Cluster）提供高可用性（high availability）。2. 关系型数据库和非关系型数据库关系型数据库（RDBMS）：表格 ，行 ，列泛指非关系型数据库的，随着web2.0互联网的诞生！传统的关系型数据库很难对付web2.0时代！尤其
是超大规模的高并发的社区！
暴露出来很多难以克服的问题，NoSQL在当今大数据环境下发展的十分迅速，Redis是发展最快的，而
且是我们当下必须要掌握的一个技术！
很多的数据类型用户的个人信息，社交网络，地理位置。这些数据类型的存储不需要一个固定的格式！
不需要多余的操作就可以横向扩展的 ！ Map&lt;String,Object&gt; 使用键值对来控制非关系型数据库(NOSQL)NOSQL：不仅仅是SQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储，列存储，文档存储，图形数据库（社交关系）
- 最终一致性，
- CAP定理和BASE （异地多活） 初级架构师！1. redis能做什么内存存储、持久化，内存中是断电即失、所以说持久化很重要（rdb、aof）效率高，可以用于高速缓存发布订阅系统地图信息分析计时器、计数器（浏览量！）2. redis特点特性多样的数据类型持久化集群事务3. Redis安装Linux中文官网：CRUG网站 (redis.cn)英文官网：Redis在官网中下载Redis的最新稳定版本即可，Redis是建议安装的，Linux可以下载.gz压缩文件，将压缩包解压到Linux服务器即可安装成功（我们可以解压到linux服务器中的/opt/目录中）4. 基本环境安装下载C++环境yum install gcc-c++
make
make install注意安装 redis执行make命令报错struct redisServer’没有名为‘sentinel_mode’的成员报错如图：1.解决安装 redis执行make命令报错struct redisServer’没有名为‘sentinel_mode’的成员查看gcc的版本是否在 5.3以上 命令：gcc -v\#升级到 5.3及以上版本命令：yum -y install centos-release-sclyum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutilsscl enable devtoolset-9 bash执行完毕之后去到src目录下执行make即可编译成功5. 启动Redis目前我使用的Linux centos 7 和Redis 6.X1.普通方式启动Redis使用 cd 命令进入Redis的安装目录，如：cd /opt/redis/src/查询目录下是否拥有 redis.server 如果有直接执行命令：./redis.server 若没有可以去目录 ·/usr/local/bin查找，然后执行./redis.server见到如图就是启动成功了我们会发现无法使用命令进行操作，这是因为redis的启动占用了当前线程，紧接着介绍第二种启动方式，也就是后台启动，是最常用的启动方式2. 后台线程方式启动Redis进入redis安装目录寻找配置后台启动配置文件redis.conf使用vi redis.conf命令编辑配置文件可以使用/ 命令查找对应的配置字母，修改如下配置值为yes使用命令wq 保存退出然后使用在安装目录使用命令./src/redis-server redis.conf （每个人的路径可能不一样，大概意思就是在启动方式1的基础上加上了配置文件的也叫配置文件启动方式）查询是否启动成功ps -ef | grep redis 找到redis的进程即是启动成功3. 关闭服务在可以直接使用Linux命令将线程kill掉，也可以在客户端工具中执行shutdown命令6. Redis客户端工具客户端工具的目录在Redis的安装目录中的/src/目录下，名称叫做redis.cli启动命令./redis.cli当输入命令更改为：127.0.0.1:6379&gt; 即为进入客户端工具成功退出可以使用ctrl+c直接强制退出可以命令ping 查看是否可以正常执行，返回PONG即表示成功7. Redis基础命令1. Redis的默认数据库redis默认有16个数据库，默认使用的是第0个数据库，可以使用select n 进行切换数据库select 3 # 切换数据库到第三个
DBSIZE # 查看数据库的大小2. 清空Redis数据库清空当前数据库：flushdb清空全部数据库的内容：flushall3. 查看所有的keykeys * # 查看所有的数据库8. Redis String(字符串)命令1. Setnx命令Redis Setnx（SET if Not eXists） 命令在指定的 key 不存在时，为 key 设置指定的值。语法：setnx &lt;k&gt; &lt;v&gt; # 如 key 为 name v 为 张三
setnx &lt;k&gt; &lt;v&gt; # 在第二次添加时，key为name时，不论值为什么都会添加失败2. getRange命令截取getRange 命令用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。语法：# 设置一个k v数据
SET mykey &quot;This is my test key&quot;
getrange mykey 0 3
# 输出 &quot;This&quot;
getrange mykey 0 -1
# 输出 &quot;This is my test key&quot;3. Mset命令Mset 命令用于同时设置一个或多个 key-value 对。# 设置多个k v键值对
mset k1 &quot;Hello&quot; k2 &quot;World&quot;4. Setex命令Setex 命令为指定的 key 设置值及其过期时间。如果 key 已经存在， Setex 命令将会替换旧的值。setex k1 60 &quot;v1&quot;
# 设置 60秒过期的k1 值为 v15.set命令SET 命令用于设置给定 key 的值。如果 key 已经存储其他值， SET 就覆写旧值，且无视类型。# 设置一个键值对 k1 v1
set k1 v16. get命令返回对应 key 的value值，如果 key 不存在时，返回 nil。 如果 key 不是字符串类型，那么返回一个错误GET db # 不存在返回 nil7. getBit命令Getbit 命令用于对 key 所储存的字符串值，获取指定偏移量上的位(bit)。# 对不存在的 key 或者不存在的 offset 进行 GETBIT， 返回 0
 
redis&gt; EXISTS bit
(integer) 0
 
redis&gt; GETBIT bit 10086
(integer) 0
 
 
# 对已存在的 offset 进行 GETBIT
 
redis&gt; SETBIT bit 10086 1
(integer) 0
 
redis&gt; GETBIT bit 10086
(integer) 18. setBit命令Setbit 命令用于对 key 所储存的字符串值，设置或清除指定偏移量上的位(bit)。setbit bit 10086 1
getbit bit 100869.Decr命令Decr 命令将 key 中储存的数字值减一。如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 DECR 操作。如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。set k1 10

decr k1 # 返回 9
# 对不存在的key值进行decr

decr k2 # 不存在赋值初始为0 再减一所以返回 -1

set k3 &quot;hello&quot;

decr k3 # 存在但不是数值的key会返回一个错误10. decrBy命令Decrby 命令将 key 所储存的值减去指定的减量值。如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 DECRBY 操作。如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。本操作的值限制在 64 位(bit)有符号数字表示之内。set k1 100

decrby k1 20 # K1 减去20 返回 80
# 其余的特点和decr一样11. Strlen命令Strlen 命令用于获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串值时，返回一个错误set k1 &quot;hello word&quot;

strlen k1 # 返回k1的字符串长度 11

# 若k不存在返回 012. Msetnx命令Msetnx 命令用于所有给定 key 都不存在时，同时设置一个或多个 key-value 对。当所有 key 都成功设置，返回 1 。 如果所有给定 key 都设置失败(至少有一个 key 已经存在)，那么返回 0# 对不存在的 key 进行 MSETNX
 
MSETNX rmdbs &quot;MySQL&quot; nosql &quot;MongoDB&quot; key-value-store &quot;redis&quot; # 添加多个k v键值对
 
MGET rmdbs nosql key-value-store # 查询多个k v 键值对
1) &quot;MySQL&quot;
2) &quot;MongoDB&quot;
3) &quot;redis&quot;
 
 
# MSET 的给定 key 当中有已存在的 key
 
Msetnx rmdbs &quot;Sqlite&quot; language &quot;python&quot;  # rmdbs 键已经存在，操作失败

# 因为 MSET 是原子性操作，language 没有被设置
 
GET rmdbs     # rmdbs 也没有被修改 输出 MySQL
13. ncrby命令Incrby 命令将 key 中储存的数字加上指定的增量值。如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCRBY 命令。如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。本操作的值限制在 64 位(bit)有符号数字表示之内。# key 存在且是数字值
 
SET rank 50 # 添加一个k

INCRBY rank 20 # rank存在添加20 返回70

# key 不存在时

INCRBY counter 30 # 不存在，初始化0返回30
 
# key 不是数字值时
SET book &quot;long long ago...&quot;
INCRBY book 200 # book 值不是数字，报错14. Incrbyfloat命令Incrbyfloat 命令为 key 中所储存的值加上指定的浮点数增量值。如果 key 不存在，那么 INCRBYFLOAT 会先将 key 的值设为 0 ，再执行加法操作。# 值和增量都不是指数符号
SET mykey 10.50 # 设置myke 值为10.50
 
incrbyfloat mykey 0.1 # mykey的值增加0.1
 
# 值和增量都是指数符号
 
SET mykey 314e-2 # 设置mykey值为 314e-2

GET mykey  # 用 SET 设置的值可以是指数符号&quot;314e-2&quot;
 
incrybyfloat mykey 0      # 但执行 INCRBYFLOAT 之后格式会被改成非指数符号
&quot;3.14&quot;
 
# 可以对整数类型执行
 
SET mykey 3

INCRBYFLOAT mykey 1.1 # 对整数类型数据增加1.1
# 后跟的 0 会被移除
SET mykey 3.0
GET mykey                                   # SET 设置的值小数部分可以是 0 显示 &quot;3.0&quot;
 
INCRBYFLOAT mykey 1.000000000000000000000    # 但 INCRBYFLOAT 会将无用的 0 忽略掉，有需要的话，将浮点变为整数
GET mykey 返回 &quot;4&quot;15.Setrange命令Setrange 命令用指定的字符串覆盖给定 key 所储存的字符串值，覆盖的位置从偏移量 offset 开始。set k1 &quot;hello&quot; #设置k1 的值为 hello 
setrange k1 1 &quot;333&quot; # 将k1 从索引2开始替换三个位数的字符，会替换掉ell 会返回h333o16. psetex命令Psetex 命令以毫秒为单位设置 key 的生存时间。psetex的使用方法和setex的使用方法一样，只不过设置的过期时间是以毫秒为单位17. Append 命令Append 命令用于为指定的 key 追加值。如果 key 已经存在并且是一个字符串， APPEND 命令将 value 追加到 key 原来的值的末尾。如果 key 不存在， APPEND 就简单地将给定 key 设为 value ，就像执行 SET key value 一样。append k1 &quot;test&quot; # 当k1不存在的时候会创建k1 值为 test等同于 set k1 &quot;test&quot;

set k2 &quot;demo&quot;
appent k2 &quot;add&quot; # 当k2存在的时候，会将字符添加到原来的值后面，会返回字符长度18. getSet命令Getset 命令用于设置指定 key 的值，并返回 key 旧的值。set name &quot;hello&quot; # 设置一个初始k
getset name &quot;word&quot; # 会返回显示hello，然后将name的值设置为word
get name #这个时候name的值是word19.  MgetMget 命令返回所有(一个或多个)给定 key 的值。 如果给定的 key 里面，有某个 key 不存在，那么这个 key 返回特殊值 nilset k1 &quot;v1&quot; # 添加
set k2 &quot;v2&quot; # 添加
mget k1 k2 k3 # 获取多个 不存在返回 nil

1) &quot;v1&quot;
2) &quot;v2&quot;
3) (nil)
20. Incr命令Incr 命令将 key 中储存的数字值增一。如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCR 操作。如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。本操作的值限制在 64 位(bit)有符号数字表示之内。set k1 20 
incr k1  # k1 加一
get k1 # 返回219.Redis 哈希(Hash)命令1.Hmset命令和Hset命令Hmset 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。此命令会覆盖哈希表中已存在的字段。如果哈希表不存在，会创建一个空哈希表，并执行 HMSET 操作hset k1 f1 &quot;k1-vf1&quot; f2 &quot;k1-vf2&quot;  # hmset和hset使用方式一样，不过hmset在官方文档中说已经弃用
hget k1 f1 # hget2. Hmget命令Hmget 命令用于返回哈希表中，一个或多个给定字段的值。如果指定的字段不存在于哈希表，那么返回一个 nil 值。hset k1 f1 &quot;k1-vf1&quot; f2 &quot;k1-vf2&quot;
hmget k1 f1 f2 # hmget可以通过多个fild 获取到值3. Hgetall命令命令用于返回哈希表中，所有的字段和值。在返回值里，紧跟每个字段名(field name)之后是字段的值(value)，所以返回值的长度是哈希表大小的两倍。hset k1 fd1 fdv1 fd2 fdv2 fd3 fdv3 #添加数据

hgetall k1 # 查询数据

# 输出结果 前面是fdkey 后面跟着他的fdvalue
1) &quot;fd1&quot;
2) &quot;fdv1&quot;
3) &quot;fd2&quot;
4) &quot;fdv2&quot;
5) &quot;fd3&quot;
6) &quot;fdv3&quot;4. Hget命令命令用于返回哈希表中指定字段的值。# 字段存在
HSET site redis redis.com

HGET site redis # 输出结果&quot;redis.com&quot; 不存在返回nil5. Hexists命令用于查看哈希表的指定字段是否存在。如果哈希表含有给定字段，返回 1 。 如果哈希表不含有给定字段，或 key 不存在，返回 0 。hset k1 fd1 fdv1 fd2 fdv2 fd3 fdv3 #添加数据

hgetall k1 # 查询数据

hexists k1 fd4 # 不存在返回0
hexists k1 fd1 # 存在返回 16. Hincrby命令Hincrby 命令用于为哈希表中的字段值加上指定增量值。增量也可以为负数，相当于对指定字段进行减法操作。如果哈希表的 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。如果指定的字段不存在，那么在执行命令前，字段的值被初始化为 0 。对一个储存字符串值的字段执行 HINCRBY 命令将造成一个错误。本操作的值被限制在 64 位(bit)有符号数字表示之内。hset k1 f1 20 # 添加一个key
hincrby k1 f1 1 # 给k1哈希表中的f1的值增加1
# 若不是数字类型，那么将报错7. Hlen命令Hlen 命令用于获取哈希表中字段的数量。hset k1 f1 v1 f2 v2
hlen k1 #返回 2 对应的k1哈希表中有两个字段分别是f1 f2,不存在返回08. Hdel命令Hdel 命令用于删除哈希表 key 中的一个或多个指定字段，不存在的字段将被忽略。hset k1 f1 v1 f2 v2 #添加初始数据
hdel k1 f2 # 删除k1哈希表中的f2字段 返回 1成功
hget k1 f1 # 返回v1
hget k1 f2 # 返回 nil
hdel k1 f3 #返回 0删除失败9.Hvals命令Hvals 命令返回哈希表所有字段的值。hset k1 f1 v1 f2 v2
hvals k1 # 返回 v1 v210. Hincrbyfloat命令Hincrbyfloat 命令用于为哈希表中的字段值加上指定浮点数增量值。如果指定的字段不存在，那么在执行命令前，字段的值被初始化为 0 。hset k1 f1 20.1
hincrbyfloat k1 f1 1.1 # 返回 21.211. Hkeys命令Hkeys 命令用于获取哈希表中的所有字段名。hset k1 f1 v1 f2 v2
hkeys k1 # 返回 f1 f212. Hsetnx 命令Hsetnx 命令用于为哈希表中不存在的的字段赋值 。如果哈希表不存在，一个新的哈希表被创建并进行 HSET 操作。如果字段已经存在于哈希表中，操作无效。如果 key 不存在，一个新哈希表被创建并执行 HSETNX 命令。hsetnx k1 f1 v1
hsetnx k1 f1 v2 # 操作无效，已经存在忽略
hget k1 f1 # 值是 v110. 其他命令其他命令可以进入官网进行自测官网：Redis命令中心（Redis commands） -- Redis中国用户组（CRUG）更多Redis资料：Redis 教程 | 菜鸟教程 (runoob.com)</description>
</item>
<item rdf:about="https://blog.anlucky.cn/index.php/programming/database/127">
<title>Mysql56个民族数据库</title>
<link>https://blog.anlucky.cn/index.php/programming/database/127</link>
<dc:date>2023-05-06T17:02:00+08:00</dc:date>
<description>Mysql 56个民族数据库表1. 创建数据库-- 创建数据库
create database [数据库名称] charset=utf8;
-- 使用数据库
use database [数据库名称];2. 创建民族表create table [表名称](
    `id` varchar(32) primary key comment &#039;民族id&#039;,
    `nation` varchar(64) comment &#039;民族名称&#039;
);3. 添加民族数据INSERT INTO `[表名称]` VALUES (&#039;1&#039;, &#039;汉族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;2&#039;, &#039;蒙古族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;3&#039;, &#039;回族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;4&#039;, &#039;藏族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;5&#039;, &#039;维吾尔族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;6&#039;, &#039;苗族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;7&#039;, &#039;彝族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;8&#039;, &#039;壮族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;9&#039;, &#039;布依族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;10&#039;, &#039;朝鲜族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;11&#039;, &#039;满族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;12&#039;, &#039;侗族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;13&#039;, &#039;瑶族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;14&#039;, &#039;白族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;15&#039;, &#039;土家族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;16&#039;, &#039;哈尼族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;17&#039;, &#039;哈萨克族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;18&#039;, &#039;傣族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;19&#039;, &#039;黎族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;20&#039;, &#039;傈僳族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;21&#039;, &#039;佤族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;22&#039;, &#039;畲族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;23&#039;, &#039;高山族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;24&#039;, &#039;拉祜族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;25&#039;, &#039;水族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;26&#039;, &#039;东乡族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;27&#039;, &#039;纳西族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;28&#039;, &#039;景颇族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;29&#039;, &#039;柯尔克孜族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;30&#039;, &#039;土族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;31&#039;, &#039;达翰尔族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;32&#039;, &#039;么佬族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;33&#039;, &#039;羌族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;34&#039;, &#039;布朗族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;35&#039;, &#039;撒拉族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;36&#039;, &#039;毛南族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;37&#039;, &#039;仡佬族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;38&#039;, &#039;锡伯族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;39&#039;, &#039;阿昌族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;40&#039;, &#039;普米族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;41&#039;, &#039;塔吉克族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;42&#039;, &#039;怒族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;43&#039;, &#039;乌孜别克族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;44&#039;, &#039;俄罗斯族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;45&#039;, &#039;鄂温克族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;46&#039;, &#039;德昂族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;47&#039;, &#039;保安族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;48&#039;, &#039;裕固族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;49&#039;, &#039;京族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;50&#039;, &#039;塔塔尔族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;51&#039;, &#039;独龙族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;52&#039;, &#039;鄂伦春族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;53&#039;, &#039;赫哲族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;54&#039;, &#039;门巴族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;55&#039;, &#039;珞巴族&#039;);
INSERT INTO `[表名称]` VALUES (&#039;56&#039;, &#039;基诺族&#039;);4. 使用技巧将添加的数据的语句复制到记事本中，使用记事本中的替换功能进行替换快捷键：Ctrl + h然后在数据库中执行SQL语句即可完成</description>
</item>
<item rdf:about="https://blog.anlucky.cn/index.php/programming/database/39">
<title>Mysql数据库基础</title>
<link>https://blog.anlucky.cn/index.php/programming/database/39</link>
<dc:date>2023-04-16T17:55:00+08:00</dc:date>
<description>1. 什么是SQLSQL 是结构化查询语言( Structured  query language ) 适用于所有关系型数据库对数据进行增删改查的语言1.1按照SQL标准分类除了 SQL 标准之外，大部分 SQL 数据库程序都拥有它们自己的专有扩展！SQL标准关系型数据库通用的SQL语句就是SQL标准语句。SQL方言每个数据库管理系统都有各自的专属SQL语句，我们俗称方言，我们在实际开发的时候应该尽量避免使用每个数据库管理系统的专属SQL语句。2. 数据库管理系统的分类关系型数据库（SQL）RDBMS关系型数据库指的是使用关系模型（二维表格模型）来组织数据的数据库常见的关系型数据库OracleMySqlSQL Server    微软SQLiteDB2   IBM非关系型数据库（NoSQL）非关系型数据库又被称为 NoSQL（Not Only SQL )，意为不仅仅是 SQL。通常指数据以对象的形式存储在数据库中，而对象之间的关系通过每个对象自身的属性来决定，常用于存储非结构化的数据常见的非关系型数据库键值数据库：Redis文档数据库：MongoDB图形数据库：Neo4j3. MySQL介绍持久化(persistence)：把数据保存到可掉电式存储设备中以供之后使用。大多数情况下，特别是企 业级应用，数据持久化意味着将内存中的数据保存到硬盘上加以”固化”，而持久化的实现过程大多 通过各种关系数据库来完成。持久化的主要作用是将内存中的数据存储在关系型数据库中，当然也可以存储在磁盘文件、XML数 据文件中。4. 数据类型整数类型* int / interage  4B  
* tinyint 1B
* bigint 8B浮点类型* float 小数点后面6-8位
    float(n,m); 
    n表示一共有多少位数 m表示小数部分保留几位
    此时整数部分位数：（n-m）位
* double 小数点后有效位数12位
    double(n,m) n表示一共有多少位数 m表示小数部分保留几位
    此时整数部分位数：（n-m）位
* decimal 用法和float和double相同  专用于表示钱相关的数字  
         decimal(n,m) m是小数位数 n-m为整数位数 字符类型* char 固定长度 char(10) 
    分配十个长度的存储空间，若不够10个长度，MySQL会自动补齐十个长度  char(n) n&lt;=4000
* varchar 可变长度 varchar(10) 
    分配十个长度的存储空间,传入长度不够时不会自动补齐
* text 64kb
* longtext 4GB时间类型1：time：只有时分秒： xx:xx:xx
2：date：只有年月日： xx/xx/xx
3：datetime：有年月日和时分秒: xx/xx/xx xx:xx:xx
4：timestamp：时间戳  毫秒值:布尔类型bool
boolean字节类型1：binary:255B
2：blob:64kB5. DDL相关语句data defined language:数据定义 对表结构的增删改查
关键字：create /drop /alter /show1 对数据库的操作-- 数据库相关的DDL语句
SHOW DATABASES; -- 显示所有数据库

SHOW VARIABLES LIKE &#039;%char%&#039;; -- 显示数据库的编码集

SHOW TABLES; -- 显示数据库所有表

CREATE DATABASE db_1; -- 创建一个数据库 名字：db_1

CREATE DATABASE db_1 CHARSET=&#039;utf8&#039;; -- 创建一个数据库 名字：db_1

USE db_1; -- 使用db_1 数据库

SELECT DATABASE(); -- 显示当前使用的数据库

DROP DATABASE db_1; -- 删除数据库 db_1

ALTER DATABASE db_1 CHARSET=&#039;gbk&#039;; -- 修改数据库的编码集为gbk
ALTER DATABASE db_1 CHARSET=&#039;utf8&#039;;2 对表的操作-- 数据表的DDL相关操作
CREATE TABLE tab_1(  -- 创建tab_1表 且必须传字段
    tid INT NOT NULL, -- 创建tid字段 数据类型是 int
    tname VARCHAR(4), -- 创建tname字段 数据类型varchar(4)
    tage TINYINT,
    tsex CHAR(1),
    tscort FLOAT(4,1),-- 数据类型float 整数长度4-1 小数1
    tbirthday DATE,
    tintime DATETIME  -- 最后一个不可以有逗号
);
SHOW TABLES; -- 显示所有表
DESC tab_1; -- 显示指定表的字段所有信息
DROP TABLE tab_1; -- 删除表

ALTER TABLE tab_1 RENAME TO tab_11; -- 修改表的名字
ALTER TABLE tab_11 RENAME TO tab_1;
ALTER TABLE tab_1 DROP tintime;    -- 删除一个字段
ALTER TABLE tab_1 ADD tintime DATETIME; -- 增加一个字段
ALTER TABLE tab_1 MODIFY tintime DATE; -- 修改字段的数据类型
ALTER TABLE tab_1 MODIFY tintime DATETIME;
ALTER TABLE tab_1 CHANGE tintime tin DATETIME; -- 修改字段名为tin数据类型为datetime
ALTER TABLE tab_1 CHANGE tin tintime DATE;6. DML相关语句-- DML相关语句
-- 对表记录的增删改：update insert delete
USE db_1;
DESC tab_1;
SELECT * FROM tab_1;
-- 添加信息
INSERT INTO tab_1 VALUES(1001,&#039;张三&#039;,19,&#039;男&#039;,19.9,&#039;1990/1/1&#039;,NOW());
INSERT INTO tab_1 VALUES(1002,&#039;李四&#039;,21,&#039;男&#039;,29.9,&#039;1993/3/4&#039;,NOW());
INSERT INTO tab_1 VALUES(1003,&#039;王五&#039;,24,&#039;男&#039;,2131.1,&#039;2001/4/133&#039;,NOW());
INSERT INTO tab_1(tid,tname,tage,tsex,tscort,tbirthday,tin)VALUES(1004,&#039;赵六&#039;,24,&#039;男&#039;,28.1,&#039;2002/3/14&#039;,NOW());
-- 添加一行信息 ，没有指定字段为null
INSERT INTO tab_1(tid,tname,tage,tsex,tscort)VALUES(1004,&#039;赵六&#039;,24,&#039;男&#039;,28.1);
-- 添加多行信息 没有指定的字段为null 
INSERT INTO tab_1(tid,tname,tage,tsex)VALUES(1004,&#039;王刚&#039;,24,&#039;女&#039;),(1004,&#039;小明&#039;,24,&#039;男&#039;);

UPDATE tab_1 SET tsex =&#039;妖&#039; WHERE tname = &#039;王刚&#039;;

UPDATE tab_1 SET tid = 1005 WHERE tbirthday = &#039;2002/3/14&#039;;
-- 删除数据 where 使用条件
DELETE FROM tab_1 WHERE tid = 1004;

INSERT INTO tab_1(tid,tname,tage,tsex)VALUES(1004,&#039;王刚&#039;,21,&#039;女&#039;);
-- tscort 是不是null 是null的话就是1不是null的话就是本身
UPDATE tab_1 SET tscort = IFNULL(tscort,1);7. 函数1. 字符串相关MySQL中字符串索引是从1开始函数名函数使用方式函数表示意义 asciiASCII('a')       返回97获取字符串在编码表中的位置 char_lengthCHAR_LENGTH('abcdefg') 返回7获取字符串的长度 一共有多少个长度 lentgthLENGTH('abc你好啊') 返回12获取字符串所占的字节数 字符串占2个字节 concatCONCAT('abc','123','defg',可无限写) 返回 abc123defg字符串连接 formatSELECT FORMAT(123123123,3);返回123,123,123.000将数字转换成金钱余额的形式 小数点保留位数可以指定 locateSELECT LOCATE('de','abcdefg')返回4获取字符串1在字符串2中第一次出现的位置 lowerSELECT LOWER('ABCDefg123%$#!@&#039;)返回abcdefg123%$#!@将大写字符转换成小写字符其他字符不变 upperSELECT UPPER('abcdef123@$#&#039;)返回ABCDEF123@$#将小写字符转换成大写字符 trimTRIM('   --abc--   ')返回--abc--清除字符串两边空格 rtrimSELECT RTRIM('  --abc--  ');清除字符串右边空格 LtrimSELECT LTRIM('  --abc--  ');清除字符串左边空格 spaceSELECT CONCAT('abc',SPACE(5),'def');获取n个空格 reverseSELECT REVERSE('abcdefgh');字符串反转，逆序字符串 replaceSELECT REPLACE('abc123abc456abc','abc','-')将参数一中的参数二替换成参数三 positionSELECT POSITION('abc' IN 'defabcgheabc');获取第一个字符串在第二个字符串中出现第一次的位置 repeatSELECT REPEAT('abc',4);获取当前字符串几次的拼接结果 strcmpSELECT STRCMP('def','eabc');字符串逐个比较前面大返回1后面大返回-1一样返回0 substringSELECT SUBSTRING('abcdef',2,3);从参数一中截取字符串索引是参数2截取个数是参数3 2. 数学相关函数函数名函数使用方式函数表示意义 sumSELECT SUM(tscore) FROM tab_2;求和，忽略null值不算 minMIN(tscore)求最小值，忽略null值不算 maxMAX(tscore)求最大值，忽略null值不算 avgAVG(tscore)求平均值，忽略null值不算 countCOUNT(tscore)获取数据行数，忽略null值不算   COUNT(*)会获取所有行包含null floorfloor(19.5)  返回19向下取整 ceilCEIL(19.5)  返回20向上取整 roundround(19.5)   round(19.5,2)四舍五入保留几位小数 powpow(n,m)幂运算 n的m次方 sqrtSQRT(9)开平方 randRAND()获取一个0到1之间的随机数字 truncateTRUNCATE(n,m)截取数字n，保留小数点后m位 UUIDUUID()随机一个不重复的32位字符串d2f5b155-4a97-11ed-98ed-eff1eabffcb4 modMOD(n,m)n%m  取余运算         3. 日期相关函数函数名函数使用方式函数表示意义 nowNOW()取当前系统时间    2022-08-13 09:42:41 curdateCURDATE()取当前系统日期 2022-08-13                         8. 数据操作1. Insert 插入数据INSERT INTO【表名称】(字段列表)values(值列表); 插入多条数据INSERT INTO 【表名称】(字段列表)values(值列表),(值列表)...;2. Select 查询数据SELECT * FROM 【表名称】;   -- 查询该表所有字段的所有信息查询指定字段的信息SELECT 【字段列表】 FROM 【表名称】; -- 查询该表中指定字段信息3. Where 条件查询需要配合着select查询语句进行使用SELECT 【字段列表】 FROM 【表名称】 where 【字段名】&lt;等于/大于/小于/不等于&gt; 某值;4. Update 更新数据修改指定条件的字段等于某个数据UPDATE 【表名称】SET 【字段】=【某值】,【字段】=【某值】 where 【字段名】&lt;等于/大于/小于/不等于&gt; 某值;5. Delete 删除数据删除表中的数据DELETE FROM【表名称】;指定条件删除某条或多条数据DELETE FROM 【表名称】 where 【字段名】&lt;等于/大于/小于/不等于&gt; 某值;6. Like 模糊匹配我们在使用where的时候只能匹配精准的数据，若使用我们的Like 的话就可以模糊匹配某条数据是否包含某些值select 【字段名】 from 【表名】 where 【字段名】 Like &#039;匹配规则&#039;匹配规则以某值开头        &#039;【值】%&#039;;
以某值结尾        &#039;%【值】&#039;;
包含某值        &#039;%【值】%&#039;;7. 获取到数据后排序使用 Oreder By 【字段名】 【排序规则 DESC 倒序/ASC 正序】SELECT * FROM 【表名称】 order by 【字段名】 DESC/ASC;### 8. 获取到的数据分组使用 Group by 【字段名】按照指定固定字段进行分组注意：​            分组之后的数据无法查询组员是谁，只可以查询组员的聚合信息 比如 成员数，求和，求最大值，求最小值，求平均值等聚合信息聚合信息：​             比如 成员数，求和，求最大值，求最小值，求平均值select 【聚合信息字段】 from 【字段名】 group by 【分组字段】;9. 多表查询1. 字段连接查询 UNION    /  Union all查询两张表中的字段 放到一张表中显示1 两张表连接起来的数据类型必须一致SELECT 【字段名】,【字段名】 from 【表名】 union select 【字段名】,【字段名】 from 【表名】; -- 查询到的数据不包含null


SELECT 【字段名】,【字段名】 from 【表名】 union all select 【字段名】,【字段名】 from 【表名】;-- 查询到的数据包含null2. 表连接查询方言SELECT 【别名1】.*, 【别名2】.* from 【表名1】 as 【别名1】,【表名2】 as 【别名2】 where 【查询条件】;标准 内连接 去除两张表中的NULL数据SELECT 【别名1】.* 【别名2】.* from 【表名1】 as 【别名1】 inner join 【表名2】 as 【别名2】 on 【查询条件】;标准 左连接SELECT 【别名1】.* 【别名2】.* from 【表名1】 as 【别名1】 left join 【表名2】 as 【别名2】 on 【查询条件】;标准 右连接SELECT 【别名1】.* 【别名2】.* from 【表名1】 as 【别名1】 right join 【表名2】 as 【别名2】 on 【查询条件】;10. SELECT(select) 查询select 字段1,字段2,......from 表名  # 查询当前表明指定字段的所有信息查询指定字段 来自哪个表中查询所有 select * from 表名  # 查询当前表中所有字段的所有信息SELECT 1+1,3*2;
SELECT 1+1,3*2 FROM DUAL
# dual 伪表
# 当前两种语句在执行的时候没有区别11. 别名 AS在我们查询的时候为了方便查看我们可以给字段 / 表头 起一个别名,这个别名只在这条语句执行的时候有效起别名的方式有两种1 在我们select选择字段的时候可以直接按下一个空格然后指定别名2 使用 AS 关键字 AS关键字后面写入你要起的别名使用双引号select id as &quot;学号&quot;,rname as &quot;姓名&quot; from student12. 去除重复 distinct使用场景：比如我们要查询员工表中都有哪些部门中有员工就可以使用关键字 distinctselect distinct department_id from employees;错误的情况 运行报错无法运行select salary,distinct department_id from employees;正确的情况：select distinct department_id,salary from employees;13. 着重号我们在给字段起名字的时候最好不要使用到MySQL的关键字，若真是使用到了关键字我们在查询的时候可以使用着重号来给这个词括起来然后再去运行我们的查询语句就可以了着重号就是~符号单点一下14. 显示表结构 describedescribe 表名;
desc 表名;显示表中所有字段的详细设置信息15. where 数据过滤select * from 表名 Where 过滤条件如我们想要查询一个学生信息表中学生分数大于60的可写下面语句select * from student where scort&gt;60;16. 算数运算select 100 + &#039;a&#039; from dual; # 此时计算结果为100
# 在mysql中 他并不会将字符转换成对应的整数进行计算

select 100 + &#039;1&#039; from dual; # 计算结果101

select 100 + null from dual; # 计算结果为null一个整数类型的值对整数进行加法和减法操作，结果还是一个整数；一个整数类型的值对浮点数进行加法和减法操作，结果是一个浮点数；加法和减法的优先级相同，进行先加后减操作与进行先减后加操作的结果是一样的；在Java中，+的左右两边如果有字符串，那么表示字符串的拼接。但是在MySQL中+只表示数 值相加。如果遇到非数值类型，先尝试转成数值，如果转失败，就按0计算。（补充：MySQL 中字符串拼接要使用字符串函数CONCAT()实现）一个数乘以整数1和除以整数1后仍得原数；一个数乘以浮点数1和除以浮点数1后变成浮8点数，数值与原数相等；一个数除以整数后，不管是否能除尽，结果都为一个浮点数；一个数除以另一个数，除不尽时，结果为一个浮点数，并保留到小数点后4位；乘法和除法的优先级相同，进行先乘后除操作与先除后乘操作，得出的结果相同。 在数学运算中，0不能用作除数，在MySQL中，一个数除以0为NULL。17. 比较运算符比较运算符用来对表达式左边的操作数和右边的操作数进行比较，比较的结果为真则返回1，比较的结果 为假则返回0，其他情况则返回NULL。 比较运算符经常被用来作为SELECT查询语句的条件来使用，返回符合条件的结果记录。1.字符串特殊情况字符串存在隐式转换，如果转换不成功 则给他当成0来看若是字符串和字符串进行比较那么将比较的是值不会将字符串转换为 0 进行比较若是字符串与数字进行比较那么将字符串转换为数字，若字符串不是数字的话默认当成0来看2. null特殊情况如果在比较中出现与null参与比较的时候比较返回也是一个nullselect null=null from dual;  # 结果返回一个null
select null = &#039;1&#039; from dual; # 结果返回一个null3. null 查询# 假设学生数据库中有地址字段address 其中有一部分学生的address是null 并没有添加地址信息，我们要查到这些学生使用sql语句

# 错误的写法
    select * from student where address = null; # 此条语句返回一个空
    # 因null在参与比较的时候无论什么情况都返回一个null 所以会取不出我们查询的数据集此时我们要借助一个新的运算符进行和null比较 &lt;=&gt;  安全等于select null&lt;=&gt; null from dual;
# 按照之前的逻辑比较来说null参与比较是必须返回一个null，但是使用到安全等于比较运算符的时候就可以判断出他是不是等于null4. 使用关键字进行字符串比较</description>
</item>
</rdf:RDF>