<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:wfw="http://wellformedweb.org/CommentAPI/">
<channel>
<title>LuckyDu - 数据库</title>
<link>http://blog.anlucky.cn/index.php/tag/%E6%95%B0%E6%8D%AE%E5%BA%93/</link>
<atom:link href="http://blog.anlucky.cn/index.php/feed/tag/%E6%95%B0%E6%8D%AE%E5%BA%93/" rel="self" type="application/rss+xml" />
<language>zh-CN</language>
<description></description>
<lastBuildDate>Tue, 23 May 2023 20:26:11 +0800</lastBuildDate>
<pubDate>Tue, 23 May 2023 20:26:11 +0800</pubDate>
<item>
<title>缓存穿透，缓存击穿，缓存雪崩是什么如何解决</title>
<link>http://blog.anlucky.cn/index.php/programming/database/152</link>
<guid>http://blog.anlucky.cn/index.php/programming/database/152</guid>
<pubDate>Tue, 23 May 2023 20:26:11 +0800</pubDate>
<dc:creator>都依凡</dc:creator>
<description><![CDATA[1. 什么是缓存穿透缓存穿透指的是一个缓存系统无法缓存某个查询的数据，从而导致这个查询每一次都要访问数据库个人理解，缓存穿透是指要访问的数据既不在缓存中，也不在数据库中，导致请求在访问缓存时没有...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h2>1. 什么是缓存穿透</h2><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/2607391471.png" alt="150" title="150"></p><p>缓存穿透指的是一个缓存系统无法缓存某个查询的数据，从而导致这个查询每一次都要访问数据库</p><blockquote>个人理解，缓存穿透是指要访问的数据既不在缓存中，也不在数据库中，导致请求在访问缓存时没有找到对应的数据，再去请求数据库也没有找到数据，无法将数据写入缓存，这样一来缓存就变为了摆设，就会同时给缓存和数据库造成压力</blockquote><p>常见的Redis缓存穿透场景包括：</p><ol><li>查询一个不存在的数据，攻击者可能发送一些无效的查询来触发缓存穿透</li><li>查询一些非常热门的数据，如果一个数据被访问的非常频繁，那么可能会导致缓存系统无法处理这些请求，从而造成缓存穿透</li><li>查询一些异常数据：这种情况通常发生在数据服务出现故障或异常时，从而造成缓存系统无法访问相关数据，从而导致缓存穿透。</li></ol><h2>2. 如何解决缓存穿透</h2><h3>解决方案一</h3><p><strong>缓存空值或者缺省的值</strong></p><p>一旦发生缓存穿透，我们就可以针对查询的数据，再Redis中缓存一个空值或者确定的缺省值，（就是随便一个可以表示缺省的值），紧接着，发送后续的查询的时候就可以从缓存中获取到缺省值了，保证了数据库的正常运行</p><h3>解决方案二</h3><p><strong>使用布隆过滤器快速判断数据是否存在</strong></p><h2>3. 什么是缓存击穿</h2><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/383251894.png" alt="149" title="149"></p><p>缓存击穿往往出现在高并发访问的情况下，一个热点数据从缓存在查不存在，就要去数据库中查询，从而导致数据库的压力过大，导致系统性能下降</p><p>缓存击穿的原因通常有以下几种：</p><ol><li>缓存中不存在所需要的热点数据，每当系统中的某个热点数据需要频繁访问的时候，同时去访问数据库，给数据库造负担</li><li>缓存热点的数据过期，当一个热点数据过期，并且需要重新缓存时候，若此时有大量请求也会因为缓存中的数据过期而去数据库中查询，给数据库造成负担。</li></ol><h2>4. 如何解决缓存击穿</h2><h3>解决方案一</h3><p><strong>设置热点数据永不过期</strong></p><p>设置热点数据永不过期就是不给key设置过期的时间即可</p><p>还有第二种方式也可以达到key值永不过期，就是正常的给key值设置过期时间，在后台启动一个定时任务在他过期前去定时地更新这个缓存，并重新设置他的过期时间</p><h3>解决方案二</h3><p><strong>分布式锁并发更新</strong></p><p>锁的对象就是key，这样如果有大量请求并发进来时，只能有一个请求获取到锁，然后获取到锁的线程去查询数据库，将查询到的数据放入到缓存中，此时，缓存中已经有数据了，后面的请求就可以从缓存中获取到数据返回，并不会查询数据库</p><h2>5. 什么是缓存雪崩</h2><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/4252536129.png" alt="151" title="151"></p><p>缓存雪崩是指大量的请求无法在Redis中进行处理，紧接着大量的请求发送到数据库层，导致数据库压力过大</p><p>常见的缓存雪崩的场景：</p><ol><li>缓存服务器宕机，当缓存服务器宕机或者重启时，大量的访问请求直接命中数据库，在同一时间导致大量的数据查询，从而数据库的压力增大</li><li>缓存数据同时失效，在某个特定的时间点，缓存中的数据大量失效，并在同一个时间点，有大量的请求集中在一起</li></ol><h2>6. 如何解决缓存雪崩</h2><h3>解决方案一</h3><p>避免给大量的数据设置相同的过期时间，如果业务层有些数据同时失效，可以给每个数据设置一个较短的过期间隔，(在不影响业务的情况下，特殊情况特殊处理)</p><h3>解决方案二</h3><p><strong>缓存预热</strong></p><p>缓存预热就是在系统启动或者失效时，手动加载数据到缓存中，这样实际请求的时候就可以直接从缓存中获取数据</p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>http://blog.anlucky.cn/index.php/programming/database/152#comments</comments>
<wfw:commentRss>http://blog.anlucky.cn/index.php/feed/tag/%E6%95%B0%E6%8D%AE%E5%BA%93/</wfw:commentRss>
</item>
<item>
<title>Redis基础入门</title>
<link>http://blog.anlucky.cn/index.php/programming/database/147</link>
<guid>http://blog.anlucky.cn/index.php/programming/database/147</guid>
<pubDate>Mon, 15 May 2023 19:12:00 +0800</pubDate>
<dc:creator>都依凡</dc:creator>
<description><![CDATA[Redis基础入门0.为什么Redis是单线程还这么快？redis 是将所有的数据全部放在内存中的，所以说使用单线程去操作效率就是最高的，多线程 （CPU上下文会切换：耗时的操作！！！），对于内...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h1>Redis基础入门</h1><h2>0.为什么Redis是单线程还这么快？</h2><p>redis 是将所有的数据全部放在内存中的，所以说使用单线程去操作效率就是最高的，多线程 （CPU上下文会切换：耗时的操作！！！），对于内存系统来说，如果没有上下文切换效率就是最高 的！多次读写都是在一个CPU上的，在内存情况下，这个就是最佳的方案！</p><h2>1. Redis介绍</h2><p>Redis 是一个开源（BSD许可）的，内存中的数据结构存储系统，它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构，如 <a href="http://www.redis.cn/topics/data-types-intro.html#strings">字符串（strings）</a>， <a href="http://www.redis.cn/topics/data-types-intro.html#hashes">散列（hashes）</a>， <a href="http://www.redis.cn/topics/data-types-intro.html#lists">列表（lists）</a>， <a href="http://www.redis.cn/topics/data-types-intro.html#sets">集合（sets）</a>， <a href="http://www.redis.cn/topics/data-types-intro.html#sorted-sets">有序集合（sorted sets）</a> 与范围查询， <a href="http://www.redis.cn/topics/data-types-intro.html#bitmaps">bitmaps</a>， <a href="http://www.redis.cn/topics/data-types-intro.html#hyperloglogs">hyperloglogs</a> 和 <a href="http://www.redis.cn/commands/geoadd.html">地理空间（geospatial）</a> 索引半径查询。 Redis 内置了 <a href="http://www.redis.cn/topics/replication.html">复制（replication）</a>，<a href="http://www.redis.cn/commands/eval.html">LUA脚本（Lua scripting）</a>， <a href="http://www.redis.cn/topics/lru-cache.html">LRU驱动事件（LRU eviction）</a>，<a href="http://www.redis.cn/topics/transactions.html">事务（transactions）</a> 和不同级别的 <a href="http://www.redis.cn/topics/persistence.html">磁盘持久化（persistence）</a>， 并通过 <a href="http://www.redis.cn/topics/sentinel.html">Redis哨兵（Sentinel）</a>和自动 <a href="http://www.redis.cn/topics/cluster-tutorial.html">分区（Cluster）</a>提供高可用性（high availability）。</p><h2>2. 关系型数据库和非关系型数据库</h2><ul><li>关系型数据库（RDBMS）：表格 ，行 ，列</li></ul><pre><code>泛指非关系型数据库的，随着web2.0互联网的诞生！传统的关系型数据库很难对付web2.0时代！尤其
是超大规模的高并发的社区！
暴露出来很多难以克服的问题，NoSQL在当今大数据环境下发展的十分迅速，Redis是发展最快的，而
且是我们当下必须要掌握的一个技术！
很多的数据类型用户的个人信息，社交网络，地理位置。这些数据类型的存储不需要一个固定的格式！
不需要多余的操作就可以横向扩展的 ！ Map&lt;String,Object&gt; 使用键值对来控制</code></pre><ul><li>非关系型数据库(NOSQL)</li></ul><pre><code>NOSQL：不仅仅是SQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储，列存储，文档存储，图形数据库（社交关系）
- 最终一致性，
- CAP定理和BASE （异地多活） 初级架构师！</code></pre><h3>1. redis能做什么</h3><ol><li>内存存储、持久化，内存中是断电即失、所以说持久化很重要（rdb、aof）</li><li>效率高，可以用于高速缓存</li><li>发布订阅系统</li><li>地图信息分析</li><li>计时器、计数器（浏览量！）</li></ol><h3>2. redis特点</h3><ol><li>特性</li><li>多样的数据类型</li><li>持久化</li><li>集群</li><li>事务</li></ol><h2>3. Redis安装Linux</h2><p>中文官网：<a href="http://www.redis.cn/">CRUG网站 (redis.cn)</a></p><p>英文官网：<a href="https://redis.io/">Redis</a></p><p>在官网中下载Redis的最新稳定版本即可，Redis是建议安装的，Linux可以下载.gz压缩文件，将压缩包解压到Linux服务器即可安装成功（我们可以解压到linux服务器中的/opt/目录中）</p><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/1964958954.png" alt="142" title="142"></p><h2>4. 基本环境安装</h2><ol><li>下载C++环境</li></ol><pre><code>yum install gcc-c++
make
make install</code></pre><blockquote><ul><li>注意</li><li>安装 redis执行make命令报错struct redisServer’没有名为‘sentinel_mode’的成员</li></ul></blockquote><p>报错如图：</p><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/4133209040.png" alt="143" title="143"></p><h3>1.解决安装 redis执行make命令报错struct redisServer’没有名为‘sentinel_mode’的成员</h3><blockquote><ol><li>查看gcc的版本是否在 5.3以上 命令：gcc -v</li><li><p>\#升级到 5.3及以上版本命令：</p><ol start="3"><li>yum -y install centos-release-scl</li><li>yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils</li><li>scl enable devtoolset-9 bash</li></ol></li></ol></blockquote><pre><code>执行完毕之后去到src目录下执行make即可编译成功</code></pre><h2>5. 启动Redis</h2><p>目前我使用的Linux centos 7 和Redis 6.X</p><h3>1.普通方式启动Redis</h3><ol><li>使用 <code>cd</code> 命令进入Redis的安装目录，如：cd /opt/redis/src/</li><li>查询目录下是否拥有 <code>redis.server</code> 如果有直接执行命令：<code>./redis.server</code> 若没有可以去目录 ·<code>/usr/local/bin</code>查找，然后执行<code>./redis.server</code></li><li>见到如图就是启动成功了</li></ol><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/3561322472.png" alt="144" title="144"></p><blockquote>我们会发现无法使用命令进行操作，这是因为redis的启动占用了当前线程，紧接着介绍第二种启动方式，也就是后台启动，是最常用的启动方式</blockquote><h3>2. 后台线程方式启动Redis</h3><ol><li>进入redis安装目录寻找配置后台启动配置文件<code>redis.conf</code></li><li>使用<code>vi redis.conf</code>命令编辑配置文件</li><li>可以使用<code>/</code> 命令查找对应的配置字母，修改如下配置值为yes</li></ol><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/3929720457.png" alt="145" title="145"></p><ol start="4"><li>使用命令<code>wq</code> 保存退出</li><li>然后使用在安装目录使用命令<code>./src/redis-server redis.conf</code> （每个人的路径可能不一样，大概意思就是在启动方式1的基础上加上了配置文件的也叫配置文件启动方式）</li><li>查询是否启动成功<code>ps -ef | grep redis</code> 找到redis的进程即是启动成功</li></ol><h3>3. 关闭服务</h3><p>在可以直接使用Linux命令将线程<code>kill</code>掉，也可以在客户端工具中执行<code>shutdown</code>命令</p><h2>6. Redis客户端工具</h2><p>客户端工具的目录在Redis的安装目录中的/src/目录下，名称叫做<code>redis.cli</code></p><ul><li>启动命令</li></ul><pre><code>./redis.cli</code></pre><blockquote>当输入命令更改为：127.0.0.1:6379&gt; 即为进入客户端工具成功</blockquote><ul><li>退出</li></ul><p>可以使用<code>ctrl+c</code>直接强制退出</p><p>可以命令<code>ping</code> 查看是否可以正常执行，返回<code>PONG</code>即表示成功</p><h2>7. Redis基础命令</h2><h3>1. Redis的默认数据库</h3><ul><li>redis默认有16个数据库，默认使用的是第0个数据库，可以使用<code>select n</code> 进行切换数据库</li></ul><pre><code class="lang-sql">select 3 # 切换数据库到第三个
DBSIZE # 查看数据库的大小</code></pre><h3>2. 清空Redis数据库</h3><ul><li>清空当前数据库：<code>flushdb</code></li><li>清空全部数据库的内容：<code>flushall</code></li></ul><h3>3. 查看所有的key</h3><pre><code class="lang-sql">keys * # 查看所有的数据库</code></pre><h2>8. Redis String(字符串)命令</h2><h3>1. Setnx命令</h3><p>Redis Setnx（<strong>SET</strong> if <strong>N</strong>ot e<strong>X</strong>ists） 命令在指定的 key 不存在时，为 key 设置指定的值。</p><p>语法：</p><pre><code class="lang-sql">setnx &lt;k&gt; &lt;v&gt; # 如 key 为 name v 为 张三
setnx &lt;k&gt; &lt;v&gt; # 在第二次添加时，key为name时，不论值为什么都会添加失败</code></pre><h3>2. getRange命令截取</h3><p>getRange 命令用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。</p><p>语法：</p><pre><code class="lang-sql"># 设置一个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;</code></pre><h3>3. Mset命令</h3><p>Mset 命令用于同时设置一个或多个 key-value 对。</p><pre><code class="lang-sql"># 设置多个k v键值对
mset k1 &quot;Hello&quot; k2 &quot;World&quot;</code></pre><h3>4. Setex命令</h3><p>Setex 命令为指定的 key 设置值及其过期时间。如果 key 已经存在， Setex 命令将会替换旧的值。</p><pre><code class="lang-sql">setex k1 60 &quot;v1&quot;
# 设置 60秒过期的k1 值为 v1</code></pre><h3>5.set命令</h3><p>SET 命令用于设置给定 key 的值。如果 key 已经存储其他值， SET 就覆写旧值，且无视类型。</p><pre><code class="lang-sql"># 设置一个键值对 k1 v1
set k1 v1</code></pre><h3>6. get命令</h3><p>返回对应 key 的value值，如果 key 不存在时，返回 nil。 如果 key 不是字符串类型，那么返回一个错误</p><pre><code class="lang-sql">GET db # 不存在返回 nil</code></pre><h3>7. getBit命令</h3><p>Getbit 命令用于对 key 所储存的字符串值，获取指定偏移量上的位(bit)。</p><pre><code class="lang-sql"># 对不存在的 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) 1</code></pre><h3>8. setBit命令</h3><p>Setbit 命令用于对 key 所储存的字符串值，设置或清除指定偏移量上的位(bit)。</p><pre><code class="lang-sql">setbit bit 10086 1
getbit bit 10086</code></pre><h3>9.Decr命令</h3><p>Decr 命令将 key 中储存的数字值减一。</p><p>如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 DECR 操作。</p><p>如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。</p><pre><code class="lang-sql">set k1 10

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

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

set k3 &quot;hello&quot;

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

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

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

# 若k不存在返回 0</code></pre><h3>12. Msetnx命令</h3><p>Msetnx 命令用于所有给定 key 都不存在时，同时设置一个或多个 key-value 对。</p><p>当所有 key 都成功设置，返回 1 。 如果所有给定 key 都设置失败(至少有一个 key 已经存在)，那么返回 0</p><pre><code class="lang-sql"># 对不存在的 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
</code></pre><h3>13. ncrby命令</h3><p>Incrby 命令将 key 中储存的数字加上指定的增量值。</p><p>如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCRBY 命令。</p><p>如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。</p><p>本操作的值限制在 64 位(bit)有符号数字表示之内。</p><pre><code class="lang-sql"># 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 值不是数字，报错</code></pre><h3>14. Incrbyfloat命令</h3><p>Incrbyfloat 命令为 key 中所储存的值加上指定的浮点数增量值。</p><p>如果 key 不存在，那么 INCRBYFLOAT 会先将 key 的值设为 0 ，再执行加法操作。</p><pre><code class="lang-sql"># 值和增量都不是指数符号
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;</code></pre><h3>15.Setrange命令</h3><p>Setrange 命令用指定的字符串覆盖给定 key 所储存的字符串值，覆盖的位置从偏移量 offset 开始。</p><pre><code class="lang-sql">set k1 &quot;hello&quot; #设置k1 的值为 hello 
setrange k1 1 &quot;333&quot; # 将k1 从索引2开始替换三个位数的字符，会替换掉ell 会返回h333o</code></pre><h3>16. psetex命令</h3><p>Psetex 命令以毫秒为单位设置 key 的生存时间。</p><p>psetex的使用方法和setex的使用方法一样，只不过设置的过期时间是以毫秒为单位</p><h3>17. Append 命令</h3><p>Append 命令用于为指定的 key 追加值。</p><p>如果 key 已经存在并且是一个字符串， APPEND 命令将 value 追加到 key 原来的值的末尾。</p><p>如果 key 不存在， APPEND 就简单地将给定 key 设为 value ，就像执行 SET key value 一样。</p><pre><code class="lang-sql">append k1 &quot;test&quot; # 当k1不存在的时候会创建k1 值为 test等同于 set k1 &quot;test&quot;

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

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

HGET site redis # 输出结果&quot;redis.com&quot; 不存在返回nil</code></pre><h3>5. Hexists命令</h3><p>用于查看哈希表的指定字段是否存在。</p><p>如果哈希表含有给定字段，返回 1 。 如果哈希表不含有给定字段，或 key 不存在，返回 0 。</p><pre><code class="lang-sql">hset k1 fd1 fdv1 fd2 fdv2 fd3 fdv3 #添加数据

hgetall k1 # 查询数据

hexists k1 fd4 # 不存在返回0
hexists k1 fd1 # 存在返回 1</code></pre><h3>6. Hincrby命令</h3><p>Hincrby 命令用于为哈希表中的字段值加上指定增量值。</p><p>增量也可以为负数，相当于对指定字段进行减法操作。</p><p>如果哈希表的 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。</p><p>如果指定的字段不存在，那么在执行命令前，字段的值被初始化为 0 。</p><p>对一个储存字符串值的字段执行 HINCRBY 命令将造成一个错误。</p><p>本操作的值被限制在 64 位(bit)有符号数字表示之内。</p><pre><code class="lang-sql">hset k1 f1 20 # 添加一个key
hincrby k1 f1 1 # 给k1哈希表中的f1的值增加1
# 若不是数字类型，那么将报错</code></pre><h3>7. Hlen命令</h3><p>Hlen 命令用于获取哈希表中字段的数量。</p><pre><code class="lang-sql">hset k1 f1 v1 f2 v2
hlen k1 #返回 2 对应的k1哈希表中有两个字段分别是f1 f2,不存在返回0</code></pre><h3>8. Hdel命令</h3><p>Hdel 命令用于删除哈希表 key 中的一个或多个指定字段，不存在的字段将被忽略。</p><pre><code class="lang-sql">hset k1 f1 v1 f2 v2 #添加初始数据
hdel k1 f2 # 删除k1哈希表中的f2字段 返回 1成功
hget k1 f1 # 返回v1
hget k1 f2 # 返回 nil
hdel k1 f3 #返回 0删除失败</code></pre><h3>9.Hvals命令</h3><p>Hvals 命令返回哈希表所有字段的值。</p><pre><code class="lang-sql">hset k1 f1 v1 f2 v2
hvals k1 # 返回 v1 v2</code></pre><h3>10. Hincrbyfloat命令</h3><p>Hincrbyfloat 命令用于为哈希表中的字段值加上指定浮点数增量值。</p><p>如果指定的字段不存在，那么在执行命令前，字段的值被初始化为 0 。</p><pre><code class="lang-sql">hset k1 f1 20.1
hincrbyfloat k1 f1 1.1 # 返回 21.2</code></pre><h3>11. Hkeys命令</h3><p>Hkeys 命令用于获取哈希表中的所有字段名。</p><pre><code class="lang-sql">hset k1 f1 v1 f2 v2
hkeys k1 # 返回 f1 f2</code></pre><h3>12. Hsetnx 命令</h3><p>Hsetnx 命令用于为哈希表中不存在的的字段赋值 。</p><p>如果哈希表不存在，一个新的哈希表被创建并进行 HSET 操作。</p><p>如果字段已经存在于哈希表中，操作无效。</p><p>如果 key 不存在，一个新哈希表被创建并执行 HSETNX 命令。</p><pre><code class="lang-sql">hsetnx k1 f1 v1
hsetnx k1 f1 v2 # 操作无效，已经存在忽略
hget k1 f1 # 值是 v1</code></pre><h2>10. 其他命令</h2><p>其他命令可以进入官网进行自测</p><p>官网：<a href="http://www.redis.cn/commands.html">Redis命令中心（Redis commands） -- Redis中国用户组（CRUG）</a></p><p>更多Redis资料：<a href="https://www.runoob.com/redis/redis-tutorial.html">Redis 教程 | 菜鸟教程 (runoob.com)</a></p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>http://blog.anlucky.cn/index.php/programming/database/147#comments</comments>
<wfw:commentRss>http://blog.anlucky.cn/index.php/feed/tag/%E6%95%B0%E6%8D%AE%E5%BA%93/</wfw:commentRss>
</item>
<item>
<title>SpringBoot基础入门</title>
<link>http://blog.anlucky.cn/index.php/programming/java/141</link>
<guid>http://blog.anlucky.cn/index.php/programming/java/141</guid>
<pubDate>Sat, 13 May 2023 16:19:00 +0800</pubDate>
<dc:creator>都依凡</dc:creator>
<description><![CDATA[SpringBoot基础入门Spring Boot是由Pivotal团队提供的一套开源框架，可以简化spring应用的创建及部署。它提供了丰富的Spring模块化支持，可以帮助开发者更轻松快捷地...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h1>SpringBoot基础入门</h1><p>Spring Boot是由Pivotal团队提供的一套开源框架，可以简化spring应用的创建及部署。它提供了丰富的Spring模块化支持，可以帮助开发者更轻松快捷地构建出企业级应用。Spring Boot通过自动配置功能，降低了复杂性，同时支持基于JVM的多种开源框架，可以缩短开发时间，使开发更加简单和高效。（SpringBoot简化开发，可以快速部署SSM项目，整合了很多个配置，使用的时候只需要加上 Jar 包和对应的配置注解即可实现配置，Springboot内置了Tomcat）</p><h2>1. 构建SpringBoot项目</h2><blockquote>这里使用的IDEA编辑器，每个编辑器的构建方式可能有些不同，但是大致相同，使用别的编辑器的同学可以拿这篇文章作为参考</blockquote><h3>方式一：使用官网构建</h3><p>使用官网页面，直接下载springboot项目，使用流程如下</p><p>官网： <a href="https://start.spring.io/">https://start.spring.io/</a></p><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/4174152799.png" alt="137" title="137"></p><h3>方式二：使用IDEA构建</h3><blockquote>在IDEA中点击new project 创建新项目，然后根据需求构建项目</blockquote><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/3871765991.png" alt="138" title="138"></p><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/327866801.png" alt="139" title="139"></p><blockquote><p>注意：</p><p>​    使用此方法构建的SpringBoot和方式一构建的方式不同点在于一个是下载了一个压缩包文件，一个是直接在IDEA开发工具中下载，区别不大</p></blockquote><h3>方式三：自己配置</h3><blockquote><p>自己配置SpringBoot对于新手来说不太友好，要求对Jar包的熟悉程度比较高，个人不太推荐，大佬忽略，这里没有具体的配置方式</p><p>配置方式：</p><p>​    使用IDEA工具构建一个新的Maven工程，然后在POM文件中添加SpringBoot的相关依赖，自己创建Application启动类和配置文件</p></blockquote><pre><code>注意：
    Mybatis-Plus不可以直接勾选Jar包进行依赖引入，需要我们自己去官网选择版本引入</code></pre><h3>目录结构</h3><p><img src="http://blog.anlucky.cn/usr/uploads/2023/05/1552494730.png" alt="140" title="140"></p><h2>2. SpringBoot核心配置</h2><p>SpringBoot有两种配置文件结尾，<code>application.properties</code> <code>application.yml</code></p><p>yml 是一种 yaml 格式的配置文件，主要采用一定的空格、换行等格式排版进行配置。</p><p>yaml 是一种直观的能够被计算机识别的的数据序列化格式，容易被人类阅读，yaml 类似于 xml，但是语法比 xml 简洁很多，<strong>值与前面的冒号配置项必须要有一个空格</strong>， yml 后缀也可以使用 yaml 后缀。</p><blockquote><p>注意：</p><p>​    SpringBoot项目的配置文件必须使用<code>application</code>名称，否则不识别</p></blockquote><h3>1. SpringBoot基本配置</h3><pre><code class="lang-yml"># SpringBoot的核心配置文件
server:
  port: 8080  # 指定项目运行的端口
  servlet:
    context-path: /  # 指定项目的运行路径
    encoding:
      charset: utf-8 # 指定项目的编码集
spring:
  profiles:
    active: dev # 多环境下使用的环境是哪个，不写就默认 application</code></pre><h3>2. 多环境配置</h3><p>在实际开发的过程中，我们的项目会经历很多的阶段（开发-&gt;测试-&gt;上线），每个阶段的配置也会不 同，例如：端口、上下文根、数据库等，那么这个时候为了方便在不同的环境之间切换，SpringBoot 提供了多环境配置</p><blockquote><p>为每个环境创建一个配置文件，命名必须以 application-环境标识.properties|yml</p><p>例如：</p><ol><li><code>application-dev.yml</code></li><li><code>application-test.yml</code></li></ol></blockquote><h3>3. 自定义配置</h3><p>SpringBoot 的核心配置文件中，除了使用内置的配置项之外，我们还可以在自定义配置，然后采用注解去读取配置的属性值</p><p>如：</p><p>​    在<code>application.yml配置文件中</code>有如下配置</p><pre><code class="lang-yml">school:
  name: 清华大学
  address: 北京</code></pre><p>那么我们就可以在项目中使用</p><pre><code class="lang-java">    @Value(&quot;${school.name}&quot;) // 注入属性
    private String schoolName; </code></pre><h2>3. SpringBoot事务管理</h2><p>Spring Boot 使用事务非常简单，底层依然采用的是 Spring 本身提供的事务管理</p><p>在入口类中使用注解 @EnableTransactionManagement 开启事务支持</p><p>在访问数据库的 Service 方法上添加注解 @Transactional 即可</p><h2>4. SpringBoot整合mybatisPlus、thymeleaf、druid、redis、Dubbo配置</h2><pre><code class="lang-yml"># SpringBoot的核心配置文件
server:
  port: 8080  # 指定项目运行的端口
  servlet:
    context-path: /  # 指定项目的运行路径
    encoding:
      charset: UTF-8 # 指定项目的编码集
      enabled: true # 开启为 true
      force: true # 强制使用

# Spring 配置
spring:
  application:
    name: demo # spring项目名称
  profiles:
    active: dev # 使用的环境是哪个
  thymeleaf:
    cache: false # thymeleaf 不使用缓存
  datasource: # 数据库连接配置
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/ssm
    type: com.alibaba.druid.pool.DruidDataSource # 使用的数据库连接池需要导入 jar 包 druid-spring-boot-starter
    druid: # 可以不配置，有默认值
      initial-size: 5 # 初始化连接数
      min-idle: 5 # 最小连接数
      max-active: 20 # 最大连接数
      max-wait: 60000 # 获取数据库连接最大等待时间 单位毫秒
      time-between-eviction-runs-millis: 60000 # 配置多久进行一次检测，检测需要关闭的空闲连接 单位毫秒
  redis:  # redis 配置
    host: localhost
    port: 6379
#    password:  # redis密码，没有注释掉

# mybatis-plus 配置
mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml # 默认值，扫描mapper.xml文件
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 日志输出
  global-config:
    db-config:
      logic-delete-field: isDelete # 逻辑删除 需要加一个注解 @TableLogic
      logic-not-delete-value: 0 # 未删除逻辑值
      logic-delete-value: 1 # 已经删除逻辑值

# Dubbo服务提供者
#dubbo:
#  application:
#    name: provide
#  registry:
#    address: zookeeper://localhost:2181
#  scan:
#    base-packages: com.dyf # 这里配置Dubbo的注解所在包,扫描的是接口实现类


# Dubbo消费者
#dubbo:
#  application:
#    name: cosumer
#  registry:
#    address: zookeeper://localhost:2181
#  scan:
#    base-packages: com.dyf # 这里配置Dubbo的注解所在包,扫描的是controller</code></pre><h2>5. SpringBoot整合MybatisPlus分页插件配置类</h2><pre><code class="lang-java">@Configuration
public class MyBatisPlusConfig {
    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 这里需要指定数据库类型 这里使用的Mysql
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}</code></pre><h2>6. 整合所需要的 jar 包</h2><p>导入SpringBoot 父类项目</p><pre><code class="lang-xml">    &lt;parent&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
        &lt;version&gt;2.7.11&lt;/version&gt;
        &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
    &lt;/parent&gt;</code></pre><p>导入所需要的 Jar 包</p><pre><code class="lang-xml">    &lt;dependencies&gt;
        &lt;!--redis--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;!--springboot Web包--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;!--springBoot 测试包--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
        &lt;!--Druid 数据库连接池包--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;
            &lt;artifactId&gt;druid-spring-boot-starter&lt;/artifactId&gt;
            &lt;version&gt;1.2.16&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;!--mybatisPlus包--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.baomidou&lt;/groupId&gt;
            &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
            &lt;version&gt;3.5.3.1&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;!--redis Jar包--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;
        &lt;/dependency&gt;

        &lt;!--Dubbo Jar包--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.dubbo&lt;/groupId&gt;
            &lt;artifactId&gt;dubbo-spring-boot-starter&lt;/artifactId&gt;
            &lt;version&gt;2.7.8&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;!--zookeep包，注册中心，整合Dubbo时候使用--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.dubbo&lt;/groupId&gt;
            &lt;artifactId&gt;dubbo-dependencies-zookeeper&lt;/artifactId&gt;
            &lt;version&gt;2.7.8&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;!--取消引入这两个日志框架，若引入控制台会报错，Jar重复引入--&gt;
            &lt;exclusions&gt;
                &lt;exclusion&gt;
                    &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
                    &lt;artifactId&gt;slf4j-reload4j&lt;/artifactId&gt;
                &lt;/exclusion&gt;
                &lt;exclusion&gt;
                    &lt;groupId&gt;log4j&lt;/groupId&gt;
                    &lt;artifactId&gt;log4j&lt;/artifactId&gt;
                &lt;/exclusion&gt;
            &lt;/exclusions&gt;
        &lt;/dependency&gt;

    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;excludes&gt;
                        &lt;exclude&gt;
                            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
                            &lt;artifactId&gt;lombok&lt;/artifactId&gt;
                        &lt;/exclude&gt;
                    &lt;/excludes&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;</code></pre>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>http://blog.anlucky.cn/index.php/programming/java/141#comments</comments>
<wfw:commentRss>http://blog.anlucky.cn/index.php/feed/tag/%E6%95%B0%E6%8D%AE%E5%BA%93/</wfw:commentRss>
</item>
<item>
<title>Mysql数据库基础</title>
<link>http://blog.anlucky.cn/index.php/programming/database/39</link>
<guid>http://blog.anlucky.cn/index.php/programming/database/39</guid>
<pubDate>Sun, 16 Apr 2023 17:55:00 +0800</pubDate>
<dc:creator>都依凡</dc:creator>
<description><![CDATA[1. 什么是SQLSQL 是结构化查询语言( Structured  query language ) 适用于所有关系型数据库对数据进行增删改查的语言1.1按照SQL标准分类除了 SQL 标准之...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h2>1. 什么是SQL</h2><p>SQL 是结构化查询语言( Structured  query language ) </p><p>适用于所有关系型数据库对数据进行增删改查的语言</p><p><img src="http://blog.anlucky.cn/usr/uploads/2023/04/3930942210.png" alt="87" title="87"></p><h3>1.1按照SQL标准分类</h3><p>除了 SQL 标准之外，大部分 SQL 数据库程序都拥有它们自己的专有扩展！</p><h3>SQL标准</h3><p>关系型数据库通用的SQL语句就是SQL标准语句。</p><h3>SQL方言</h3><p>每个数据库管理系统都有各自的专属SQL语句，我们俗称方言，我们在实际开发的时候应该尽量避免使用每个数据库管理系统的专属SQL语句。</p><h2>2. 数据库管理系统的分类</h2><h3>关系型数据库（SQL）RDBMS</h3><pre><code>关系型数据库指的是使用关系模型（二维表格模型）来组织数据的数据库</code></pre><h3>常见的关系型数据库</h3><ol><li>Oracle</li><li>MySql</li><li>SQL Server    微软</li><li>SQLite</li><li>DB2   IBM</li></ol><h3>非关系型数据库（NoSQL）</h3><pre><code>非关系型数据库又被称为 NoSQL（Not Only SQL )，意为不仅仅是 SQL。通常指数据以对象的形式存储在数据库中，而对象之间的关系通过每个对象自身的属性来决定，常用于存储非结构化的数据</code></pre><h3>常见的非关系型数据库</h3><ol><li>键值数据库：Redis</li><li>文档数据库：MongoDB</li><li>图形数据库：Neo4j</li></ol><h2>3. MySQL介绍</h2><p>持久化(persistence)：把数据保存到可掉电式存储设备中以供之后使用。大多数情况下，特别是企 业级应用，数据持久化意味着将内存中的数据保存到硬盘上加以”固化”，而持久化的实现过程大多 通过各种关系数据库来完成。</p><p>持久化的主要作用是将内存中的数据存储在关系型数据库中，当然也可以存储在磁盘文件、XML数 据文件中。</p><h2>4. 数据类型</h2><h3>整数类型</h3><pre><code>* int / interage  4B  
* tinyint 1B
* bigint 8B</code></pre><h3>浮点类型</h3><pre><code class="lang-mysql">* 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为整数位数 </code></pre><h3>字符类型</h3><pre><code>* char 固定长度 char(10) 
    分配十个长度的存储空间，若不够10个长度，MySQL会自动补齐十个长度  char(n) n&lt;=4000
* varchar 可变长度 varchar(10) 
    分配十个长度的存储空间,传入长度不够时不会自动补齐
* text 64kb
* longtext 4GB</code></pre><h3>时间类型</h3><pre><code>1：time：只有时分秒： xx:xx:xx
2：date：只有年月日： xx/xx/xx
3：datetime：有年月日和时分秒: xx/xx/xx xx:xx:xx
4：timestamp：时间戳  毫秒值:</code></pre><h3>布尔类型</h3><pre><code>bool
boolean</code></pre><h3>字节类型</h3><pre><code>1：binary:255B
2：blob:64kB</code></pre><h2>5. DDL相关语句</h2><pre><code>data defined language:数据定义 对表结构的增删改查
关键字：create /drop /alter /show</code></pre><h3>1 对数据库的操作</h3><pre><code class="lang-mysql">-- 数据库相关的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;;</code></pre><h3>2 对表的操作</h3><pre><code class="lang-mysql">-- 数据表的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;</code></pre><h2>6. DML相关语句</h2><pre><code class="lang-mysql">-- 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);</code></pre><h2>7. 函数</h2><h3>1. 字符串相关</h3><p>MySQL中字符串索引是从1开始</p><table><thead><tr><th align="center">函数名</th><th align="center">函数使用方式</th><th align="center">函数表示意义</th><th> </th></tr></thead><tbody><tr><td align="center">ascii</td><td align="center">ASCII('a')       返回97</td><td align="center">获取字符串在编码表中的位置</td><td> </td></tr><tr><td align="center">char_length</td><td align="center">CHAR_LENGTH('abcdefg') 返回7</td><td align="center">获取字符串的长度 一共有多少个长度</td><td> </td></tr><tr><td align="center">lentgth</td><td align="center">LENGTH('abc你好啊') 返回12</td><td align="center">获取字符串所占的字节数 字符串占2个字节</td><td> </td></tr><tr><td align="center">concat</td><td align="center">CONCAT('abc','123','defg',可无限写) 返回 abc123defg</td><td align="center">字符串连接</td><td> </td></tr><tr><td align="center">format</td><td align="center">SELECT FORMAT(123123123,3);返回123,123,123.000</td><td align="center">将数字转换成金钱余额的形式 小数点保留位数可以指定</td><td> </td></tr><tr><td align="center">locate</td><td align="center">SELECT LOCATE('de','abcdefg')返回4</td><td align="center">获取字符串1在字符串2中第一次出现的位置</td><td> </td></tr><tr><td align="center">lower</td><td align="center">SELECT LOWER('ABCDefg123%$#!@&#039;)返回abcdefg123%$#!@</td><td align="center">将大写字符转换成小写字符其他字符不变</td><td> </td></tr><tr><td align="center">upper</td><td align="center">SELECT UPPER('abcdef123@$#&#039;)返回ABCDEF123@$#</td><td align="center">将小写字符转换成大写字符</td><td> </td></tr><tr><td align="center">trim</td><td align="center">TRIM('   --abc--   ')返回--abc--</td><td align="center">清除字符串两边空格</td><td> </td></tr><tr><td align="center">rtrim</td><td align="center">SELECT RTRIM('  --abc--  ');</td><td align="center">清除字符串右边空格</td><td> </td></tr><tr><td align="center">Ltrim</td><td align="center">SELECT LTRIM('  --abc--  ');</td><td align="center">清除字符串左边空格</td><td> </td></tr><tr><td align="center">space</td><td align="center">SELECT CONCAT('abc',SPACE(5),'def');</td><td align="center">获取n个空格</td><td> </td></tr><tr><td align="center">reverse</td><td align="center">SELECT REVERSE('abcdefgh');</td><td align="center">字符串反转，逆序字符串</td><td> </td></tr><tr><td align="center">replace</td><td align="center">SELECT REPLACE('abc123abc456abc','abc','-')</td><td align="center">将参数一中的参数二替换成参数三</td><td> </td></tr><tr><td align="center">position</td><td align="center">SELECT POSITION('abc' IN 'defabcgheabc');</td><td align="center">获取第一个字符串在第二个字符串中出现第一次的位置</td><td> </td></tr><tr><td align="center">repeat</td><td align="center">SELECT REPEAT('abc',4);</td><td align="center">获取当前字符串几次的拼接结果</td><td> </td></tr><tr><td align="center">strcmp</td><td align="center">SELECT STRCMP('def','eabc');</td><td align="center">字符串逐个比较前面大返回1后面大返回-1一样返回0</td><td> </td></tr><tr><td align="center">substring</td><td align="center">SELECT SUBSTRING('abcdef',2,3);</td><td align="center">从参数一中截取字符串索引是参数2截取个数是参数3</td><td> </td></tr></tbody></table><h3>2. 数学相关函数</h3><table><thead><tr><th align="center">函数名</th><th align="center">函数使用方式</th><th align="center">函数表示意义</th><th> </th></tr></thead><tbody><tr><td align="center">sum</td><td align="center">SELECT SUM(tscore) FROM tab_2;</td><td align="center">求和，忽略null值不算</td><td> </td></tr><tr><td align="center">min</td><td align="center">MIN(tscore)</td><td align="center">求最小值，忽略null值不算</td><td> </td></tr><tr><td align="center">max</td><td align="center">MAX(tscore)</td><td align="center">求最大值，忽略null值不算</td><td> </td></tr><tr><td align="center">avg</td><td align="center">AVG(tscore)</td><td align="center">求平均值，忽略null值不算</td><td> </td></tr><tr><td align="center">count</td><td align="center">COUNT(tscore)</td><td align="center">获取数据行数，忽略null值不算   COUNT(*)会获取所有行包含null</td><td> </td></tr><tr><td align="center">floor</td><td align="center">floor(19.5)  返回19</td><td align="center">向下取整</td><td> </td></tr><tr><td align="center">ceil</td><td align="center">CEIL(19.5)  返回20</td><td align="center">向上取整</td><td> </td></tr><tr><td align="center">round</td><td align="center">round(19.5)   round(19.5,2)</td><td align="center">四舍五入保留几位小数</td><td> </td></tr><tr><td align="center">pow</td><td align="center">pow(n,m)</td><td align="center">幂运算 n的m次方</td><td> </td></tr><tr><td align="center">sqrt</td><td align="center">SQRT(9)</td><td align="center">开平方</td><td> </td></tr><tr><td align="center">rand</td><td align="center">RAND()</td><td align="center">获取一个0到1之间的随机数字</td><td> </td></tr><tr><td align="center">truncate</td><td align="center">TRUNCATE(n,m)</td><td align="center">截取数字n，保留小数点后m位</td><td> </td></tr><tr><td align="center">UUID</td><td align="center">UUID()</td><td align="center">随机一个不重复的32位字符串d2f5b155-4a97-11ed-98ed-eff1eabffcb4</td><td> </td></tr><tr><td align="center">mod</td><td align="center">MOD(n,m)</td><td align="center">n%m  取余运算</td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr></tbody></table><h3>3. 日期相关函数</h3><table><thead><tr><th align="center">函数名</th><th align="center">函数使用方式</th><th align="center">函数表示意义</th><th> </th></tr></thead><tbody><tr><td align="center">now</td><td align="center">NOW()</td><td align="center">取当前系统时间    2022-08-13 09:42:41</td><td> </td></tr><tr><td align="center">curdate</td><td align="center">CURDATE()</td><td align="center">取当前系统日期 2022-08-13</td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr><tr><td align="center"> </td><td align="center"> </td><td align="center"> </td><td> </td></tr></tbody></table><h2>8. 数据操作</h2><h3>1. Insert 插入数据</h3><pre><code class="lang-mysql">INSERT INTO【表名称】(字段列表)values(值列表); </code></pre><ul><li>插入多条数据</li></ul><pre><code class="lang-mysql">INSERT INTO 【表名称】(字段列表)values(值列表),(值列表)...;</code></pre><h3>2. Select 查询数据</h3><pre><code class="lang-mysql">SELECT * FROM 【表名称】;   -- 查询该表所有字段的所有信息</code></pre><ul><li>查询指定字段的信息</li></ul><pre><code class="lang-mysql">SELECT 【字段列表】 FROM 【表名称】; -- 查询该表中指定字段信息</code></pre><h3>3. Where 条件查询</h3><ul><li>需要配合着select查询语句进行使用</li></ul><pre><code class="lang-mysql">SELECT 【字段列表】 FROM 【表名称】 where 【字段名】&lt;等于/大于/小于/不等于&gt; 某值;</code></pre><h3>4. Update 更新数据</h3><ul><li>修改指定条件的字段等于某个数据</li></ul><pre><code class="lang-mysql">UPDATE 【表名称】SET 【字段】=【某值】,【字段】=【某值】 where 【字段名】&lt;等于/大于/小于/不等于&gt; 某值;</code></pre><h3>5. Delete 删除数据</h3><ul><li>删除表中的数据</li></ul><pre><code class="lang-mysql">DELETE FROM【表名称】;</code></pre><ul><li>指定条件删除某条或多条数据</li></ul><pre><code class="lang-mysql">DELETE FROM 【表名称】 where 【字段名】&lt;等于/大于/小于/不等于&gt; 某值;</code></pre><h3>6. Like 模糊匹配</h3><ul><li>我们在使用where的时候只能匹配精准的数据，若使用我们的Like 的话就可以模糊匹配某条数据是否包含某些值</li></ul><pre><code class="lang-mysql">select 【字段名】 from 【表名】 where 【字段名】 Like &#039;匹配规则&#039;</code></pre><h4>匹配规则</h4><pre><code class="lang-mysql">以某值开头        &#039;【值】%&#039;;
以某值结尾        &#039;%【值】&#039;;
包含某值        &#039;%【值】%&#039;;</code></pre><h3>7. 获取到数据后排序</h3><p>使用 Oreder By 【字段名】 【排序规则 DESC 倒序/ASC 正序】</p><pre><code class="lang-mysql">SELECT * FROM 【表名称】 order by 【字段名】 DESC/ASC;</code></pre><p>### 8. 获取到的数据分组</p><p>使用 Group by 【字段名】</p><p>按照指定固定字段进行分组</p><p>注意：</p><p>​            分组之后的数据无法查询组员是谁，只可以查询组员的聚合信息 比如 成员数，求和，求最大值，求最小值，求平均值等聚合信息</p><p>聚合信息：</p><p>​             比如 成员数，求和，求最大值，求最小值，求平均值</p><pre><code class="lang-mysql">select 【聚合信息字段】 from 【字段名】 group by 【分组字段】;</code></pre><h2>9. 多表查询</h2><h3>1. 字段连接查询 UNION    /  Union all</h3><ul><li>查询两张表中的字段 放到一张表中显示</li><li>1 两张表连接起来的数据类型必须一致</li></ul><pre><code class="lang-mysql">SELECT 【字段名】,【字段名】 from 【表名】 union select 【字段名】,【字段名】 from 【表名】; -- 查询到的数据不包含null


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

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

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

# 错误的写法
    select * from student where address = null; # 此条语句返回一个空
    # 因null在参与比较的时候无论什么情况都返回一个null 所以会取不出我们查询的数据集</code></pre><p>此时我们要借助一个新的运算符进行和null比较 </p><p>&lt;=&gt;  安全等于</p><pre><code class="lang-mysql">select null&lt;=&gt; null from dual;
# 按照之前的逻辑比较来说null参与比较是必须返回一个null，但是使用到安全等于比较运算符的时候就可以判断出他是不是等于null</code></pre><h3>4. 使用关键字进行字符串比较</h3><p><img src="http://blog.anlucky.cn/usr/uploads/2023/04/1914240989.png" alt="37" title="37"></p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>http://blog.anlucky.cn/index.php/programming/database/39#comments</comments>
<wfw:commentRss>http://blog.anlucky.cn/index.php/feed/tag/%E6%95%B0%E6%8D%AE%E5%BA%93/</wfw:commentRss>
</item>
</channel>
</rss>