行走日记 - 后端
type: channel
link: http://blog.baikeyang.com/category/backend/
description: Java，Spring Boot, Redis, 后端服务，MySQL, SQL Server
items: RabbitMQ 延迟消息完整指南
items: SQL Server 判断是否为数字
items: Debian安装MariaDB
items: 关于解决项目中Lombok的注解处理器没有生效的问题
items: 关于SQL Server 驱动在连接加密开启时验证服务器证书失败的问题
items: Linux下安装Redis
items: SpringBoot中关于spring-boot-devtools的介绍
items: Maven中Pom.xml里面的<optional>true</optional>作用
items: Maven中dependency的scope有哪些？
items: SQL Server中对JSON的处理

RabbitMQ 延迟消息完整指南
type: item
date: 2026-01-19T07:50:49+00:00
description: RabbitMQ 延迟消息完整指南1. 概述延迟消息是指在发送消息时指定一个延迟时间，消息不会立即投递给消费者，而是在延迟时间结束后才被投递给消费者处理。这在许多业务场景中非常有用，如订单超时处理、预约提醒、定时任务等。2. 实现方式2.1 延迟消息插件方式插件安装# 启用延迟消息插件 rabbitmq-plugins enable rabbitmq_delayed_message_exchange交换机配置@Bean public CustomExchange delayExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); // 指定延迟消息到期后的路由类型 return new CustomExchange("exchange.name", "x-delayed-message", true, false, args); }参数说明x-delayed-message: 交换机类型，表示这是一个延迟消息交换机x-delayed-type: 延迟消息到期后的路由类型，可选值包括：direct: 直连类型topic: 主题类型fanout: 广播类型headers: 头部类型消息发送// 发送延迟消息 MessageProperties properties = new MessageProperties(); properties.setHeader("x-delay", 5000); // 延迟5秒 Message delayedMessage = new Message(message.getBytes(), properties); rabbitTemplate.send(exchangeName, routingKey, delayedMessage);2.2 TTL + 死信队列方式当无法使用延迟消息插件时，可以使用 TTL（Time To Live）+ 死信队列的方式实现延迟消息。配置// 死信交换机 @Bean public DirectExchange deadLetterExchange() { return new DirectExchange("dead.letter.exchange"); } // 死信队列 @Bean public Queue deadLetterQueue() { return QueueBuilder.durable("dead.letter.queue") .withArgument("x-message-ttl", 5000) // 设置TTL .withArgument("x-dead-letter-exchange", "normal.exchange") // 死信转发交换机 .withArgument("x-dead-letter-routing-key", "routing.key") // 死信转发路由键 .build(); } // 绑定 @Bean public Binding deadLetterBinding() { return BindingBuilder.bind(deadLetterQueue()) .to(deadLetterExchange()) .with("dl.routing.key"); }2.3 消息级 TTL 方式在发送消息时单独设置 TTL：MessageProperties props = new MessageProperties(); props.setExpiration("5000"); // 5秒后过期 Message message = new Message(content.getBytes(), props);3. 优缺点对比方式优点缺点适用场景延迟消息插件使用简单，功能强大需要安装插件，服务器配置要求高高频延迟消息场景TTL+死信队列不需要额外插件，兼容性好配置复杂，灵活性较低对延迟精度要求不高的场景消息级TTL灵活性高不能动态修改TTL，功能有限单条消息个性化TTL需求4. 注意事项插件依赖：使用延迟消息插件方式需要确保 RabbitMQ 服务器已安装相应插件性能影响：大量延迟消息可能影响 RabbitMQ 性能可靠性：延迟消息期间若服务重启，可能导致消息丢失监控：需要监控延迟消息的处理状态，防止消息积压5. 实际应用场景订单超时处理：用户下单后一定时间内未支付则自动取消预约提醒：提前一定时间向用户发送提醒重试机制：消息处理失败后延迟重试定时任务：替代传统定时任务，更灵活高效这份文档涵盖了 RabbitMQ 延迟消息的主要知识点，希望能帮助您深入理解和应用这一重要功能。

SQL Server 判断是否为数字
type: item
date: 2025-09-12T06:13:07+00:00
description: 在SQL Server中，可以使用多种方法来判断一个字符串是否为数字。以下是几种常见的方法：使用ISNUMERIC()函数ISNUMERIC()函数可以判断一个字符串是否可以转换为数字。如果字符串是数字，则返回1，否则返回0。例如：SELECT ISNUMERIC('123') AS NumberStr, -- 返回1，表示字符串是数字 ISNUMERIC('123.45') AS DecimalStr, -- 返回1，表示字符串是数字 ISNUMERIC('abc') AS NonNumericStr -- 返回0，表示字符串不是数字需要注意的是，ISNUMERIC()函数有时会返回意外的结果，例如ISNUMERIC('23e4')和ISNUMERIC('23d4')都会返回1。使用PATINDEX()函数PATINDEX()函数返回第一个满足指定模式的位置，如果没有满足的则返回0。可以使用PATINDEX()函数来判断字符串是否为纯数字。例如：SELECT CASE WHEN PATINDEX('%[^0-9]%', '123') = 0 THEN 1 ELSE 0 END AS IsNumeric, -- 返回1，表示字符串是纯数字 CASE WHEN PATINDEX('%[^0-9]%', '123.45') = 0 THEN 1 ELSE 0 END AS IsDecimal, -- 返回0，表示字符串不是纯数字 CASE WHEN PATINDEX('%[^0-9]%', 'abc') = 0 THEN 1 ELSE 0 END AS IsNonNumeric -- 返回0，表示字符串不是纯数字对于支持小数点和正负数的写法，可以使用如下模式：PATINDEX('%[^0-9|.|-|+]%', expression)使用CAST()或CONVERT()函数CAST()和CONVERT()函数可以将一个字符串转换为数字类型。如果转换成功，则表示字符串是数字，否则表示字符串不是数字。例如：SELECT CASE WHEN CAST('123' AS INT) IS NOT NULL THEN 1 ELSE 0 END AS NumberStr, -- 返回1，表示字符串是数字 CASE WHEN CAST('123.45' AS DECIMAL(10,2)) IS NOT NULL THEN 1 ELSE 0 END AS DecimalStr, -- 返回1，表示字符串是数字 CASE WHEN CAST('abc' AS INT) IS NULL THEN 0 ELSE 1 END AS NonNumericStr -- 返回0，表示字符串不是数字使用正则表达式在SQL Server中，可以使用正则表达式来判断一个字符串是否为数字。例如：SELECT CASE WHEN '123' LIKE '%[^0-9]%' THEN 0 ELSE 1 END AS NumberStr, -- 返回1，表示字符串是数字 CASE WHEN '123.45' LIKE '%[^0-9.]%' THEN 0 ELSE 1 END AS DecimalStr, -- 返回1，表示字符串是数字 CASE WHEN 'abc' LIKE '%[^0-9]%' THEN 0 ELSE 1 END AS NonNumericStr -- 返回0，表示字符串不是数字以上几种方法都可以判断一个字符串是否为数字

Debian安装MariaDB
type: item
date: 2025-08-17T04:50:00+00:00
description: 1. 安装 MariaDBsudo apt install -y mariadb-server mariadb-client初始化安全配置：sudo mysql_secure_installation开始安装配置：// 输入root的当前密码（如无则输入） Enter current password for root (enter for none): // Unix Socket 身份验证 建议Y切换 Switch to unix_socket authentication [Y/n] y // 更新root密码 如果root密码为空，建议Y设置新的root密码 Change the root password? [Y/n] y // 输入root的新密码 New password: // 再次输入root的新密码 Re-enter new password: // 移除匿名用户 建议删除Y Remove anonymous users? [Y/n] y // 是否禁止root远程登陆 如有需要可以开启Y Disallow root login remotely? [Y/n] n // 移除测试数据库并禁止访问 测试数据库如无需要，可以删除 Remove test database and access to it? [Y/n] y // 重新加载权限表 如果有变更，建议Y Reload privilege tables now? [Y/n] y // 出现这个提示语表示MariaDB的安全配置已完成。 All done! If you've completed all of the above steps, your MariaDB installation should now be secure. Thanks for using MariaDB! 进入数据库并创建用户和库：sudo mysql -u root -p在 MariaDB 里执行：-- 创建数据库，并设置编码为utf8mb4,设置排序规则utf8mb4_unicode_ci CREATE DATABASE testdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建一个数据库用户devuser,只允许从localhost登陆，设置密码为devpass111 CREATE USER 'devuser'@'localhost' IDENTIFIED BY 'devpass111'; -- 授权所有权限（增删改查、建表、索引等） 作用在testdb数据库下的所有表，并把这些授权授予给devuser GRANT ALL PRIVILEGES ON testdb.* TO 'devuser'@'localhost'; -- 刷新权限 FLUSH PRIVILEGES; -- 退出 EXIT;2. 修改 MariaDB 配置文件，允许监听远程请求编辑配置文件：sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf找到：bind-address = 127.0.0.1改成：bind-address = 0.0.0.0保存退出，然后重启 MariaDB：sudo systemctl restart mariadb3. 开放防火墙端口（默认 3306）如果你启用了 ufw：sudo ufw allow 3306

关于解决项目中Lombok的注解处理器没有生效的问题
type: item
date: 2025-05-07T02:57:00+00:00
description: ❓ 发现问题我的项目POM文件内容如下：<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.13</version> <relativePath/> </parent> <groupId>com.you</groupId> <artifactId>mfd</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mfd</name> <description>mfd</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </path> </annotationProcessorPaths> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>以上配置，在plugin的maven-compiler-plugin中，如果注释掉configuration中的内容，即项目中的@Data注解有效，一旦将该配置释放开，即项目中的@Data就立马失效了。经过排查，发现是因为 Lombok 的注解处理器依赖没有加版本号，导致 maven-compiler-plugin 配置失效。? 根本原因我的 maven-compiler-plugin 中的配置是这样的（缺少 <version>）：<annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </path> </annotationPr…

关于SQL Server 驱动在连接加密开启时验证服务器证书失败的问题
type: item
date: 2025-05-07T02:34:00+00:00
description: 这是一个来自 SQL Server 驱动在连接加密开启时验证服务器证书失败，错误如下：com.microsoft.sqlserver.jdbc.SQLServerException: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target”。 ClientConnectionId:09fc584e-070a-4b08-bbd6-9de705bd6d21 at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:3680) ~[mssql-jdbc-10.2.3.jre8.jar:na] at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:2047) ~[mssql-jdbc-10.2.3.jre8.jar:na] at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:3204) ~[mssql-jdbc-10.2.3.jre8.jar:na] at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:2833) ~[mssql-jdbc-10.2.3.jre8.jar:na] at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:2671) ~[mssql-jdbc-10.2.3.jre8.jar:na] at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1640) ~[mssql-jdbc-10.2.3.jre8.jar:na] at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:936) ~[mssql-jdbc-10.2.3.jre8.jar:na] at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:364) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:476) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-4.0.3.jar:na] at com.mybatisflex.core.dialect.DbTypeUtil.getSqlserverDbType(DbTypeUtil.java:65) ~[mybatis-flex-core-1.10.9.jar:na] …

Linux下安装Redis
type: item
date: 2025-04-28T14:26:00+00:00
description: 下载Redis首先去官网下载：https://redis.io/downloads/(步骤此处省略)我下载的是6.2。所以下面就以6.2为例将下载的安装包上传至服务器的目录/usr/local下(步骤此处省略)进入目录解压，执行命令tar xf redis-6.2.14.tar：[root@iZ2ze2r04br2fslxv7dx4tZ local]# tar xf redis-6.2.14.tar [root@iZ2ze2r04br2fslxv7dx4tZ local]# ls aegis bin etc games include lib lib64 libexec redis-6.2.14 redis-6.2.14.tar sbin share src安装Redis所需环境及依赖安装gcc环境：由于Redis是用C语言编写的，它的运行需要C环境，因为需要我们先安装gcc：# yum install gcc-c++ 已加载插件：fastestmirror Loading mirror speeds from cached hostfile 正在解决依赖关系 --> 正在检查事务 ---> 软件包 gcc-c++.x86_64.0.4.8.5-44.el7 将被 安装 --> 正在处理依赖关系 libstdc++-devel = 4.8.5-44.el7，它被软件包 gcc-c++-4.8.5-44.el7.x86_64 需要 --> 正在检查事务 ---> 软件包 libstdc++-devel.x86_64.0.4.8.5-44.el7 将被 安装 --> 解决依赖关系完成 依赖关系解决 ================================================================================================================================= Package 架构 版本 源 大小 ================================================================================================================================= 正在安装: gcc-c++ x86_64 4.8.5-44.el7 base 7.2 M 为依赖而安装: libstdc++-devel x86_64 4.8.5-44.el7 base 1.5 M 事务概要 ================================================================================================================================= 安装 1 软件包 (+1 依赖软件包) 总下载量：8.7 M 安装大小：25 M Is this ok [y/d/N]: y Downloading packages: (1/2): libstdc++-devel-4.8.5-44.el7.x86_64.rpm | 1.5 MB 00:00:00 (2/2): gcc-c++-4.8.5-44.el7.x86_64.rpm | 7.2 MB 00:00:00 --------------------------------------------------------------------------------------------------------------------------------- 总计 26 MB/s | 8.7 MB 00:00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction 正在安装 : libstdc++-devel-4.8.5-44.el7.x86_64 1/2 正在安装 : gcc-c++-4.8.5-44.el7.x86_64 2/2 验证中 : gcc-c++-4.8.5-44.el7.x86_64 1/2 验证中 : libstdc++-devel-4.8.5-44.el7.x86_64 2/2 已安装: gcc-c++.x86_64 0:4.8.5-44.el7 作为依赖被安装: libstdc++-devel.x86_64 0:4.8.5-44.el7 完毕！ 编译并安装Redis进入到/usr/local/redis-6.2.14/目录下，运行make命令，进行编译：# …

SpringBoot中关于spring-boot-devtools的介绍
type: item
date: 2025-04-23T06:35:52+00:00
description: spring-boot-devtools 是 Spring Boot 提供的一个开发工具模块，主要用于提升开发效率。它通过提供热部署（Hot Reload）和其他开发时的便捷功能，帮助开发者快速迭代和调试代码。作用热部署（Hot Reload）自动检测类路径下的文件变化（如 Java 文件、配置文件等），并重新加载应用，无需手动重启。适用于开发环境，生产环境中默认禁用。LiveReload 支持内置 LiveReload 服务器，当资源文件（如 HTML、CSS、JavaScript 等）发生变化时，浏览器会自动刷新。默认禁用缓存在开发环境中，Spring Boot 会禁用模板引擎缓存（如 Thymeleaf、Freemarker 等），确保每次请求都能获取最新的模板内容。全局设置提供了一些全局配置选项，比如可以通过 spring.devtools.restart.enabled 控制是否启用热部署。具体使用方法1. 添加依赖在 pom.xml 中添加 spring-boot-devtools 依赖：<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency><optional>true</optional> 表示该依赖仅在当前项目中生效，不会传递到其他模块。2. 配置文件设置可以在 application.properties 或 application.yml 中进行相关配置：# 启用/禁用热部署 spring.devtools.restart.enabled=true # 设置需要监控的目录（默认监控类路径） spring.devtools.restart.additional-paths=src/main/java # 排除不需要监控的目录 spring.devtools.restart.exclude=static/**,public/** # 启用 LiveReload spring.devtools.livereload.enabled=true3. 使用方式代码修改后自动重启 修改 Java 文件或配置文件后，Spring Boot 会自动重启应用。你可以在控制台看到类似以下日志：Restarting application...浏览器自动刷新 如果修改了前端资源文件（如 HTML、CSS、JS），并且浏览器安装了 LiveReload 插件，页面会自动刷新。4. 注意事项生产环境禁用 spring-boot-devtools 默认不会被打包到生产环境的 JAR 文件中，因此不会影响生产性能。如果需要强制禁用，可以在打包时排除该依赖。IDE 配置 确保 IDE 的自动编译功能已启用：IntelliJ IDEA：勾选 Build project automatically（File -> Settings -> Build, Execution, Deployment -> Compiler）。Eclipse：默认支持自动编译。性能优化 如果项目较大，热部署可能会导致重启时间较长，可以使用 spring.devtools.restart.log-condition-evaluation-delta=false 关闭条件评估日志以提升速度。总结spring-boot-devtools 是一个非常实用的开发工具，能够显著提升开发效率。通过简单的配置，开发者可以享受到热部署和 LiveReload 带来的便利，同时避免手动重启应用的繁琐操作。

Maven中Pom.xml里面的<optional>true</optional>作用
type: item
date: 2025-04-23T06:13:00+00:00
description: 在 Maven 的 pom.xml 文件中，<optional>true</optional> 是用于标记依赖项的一个属性。以下是它的作用和影响的详细说明：1. optional 属性的作用当一个依赖被标记为 <optional>true</optional> 时，表示该依赖是可选的（非必须）。这意味着，使用该项目的其他模块或项目不会自动继承这个依赖。2. 具体行为（1）对于当前项目在当前项目中，标记为 <optional>true</optional> 的依赖仍然会被正常解析和使用。例如，在您的 pom.xml 中：<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>这里的 lombok 依赖会在当前项目的编译、运行过程中正常工作。（2）对于依赖当前项目的其他模块或项目如果其他模块或项目依赖了当前项目（holiday-club-service），它们不会自动继承标记为 <optional>true</optional> 的依赖。换句话说，其他模块如果需要使用 lombok，必须显式地在自己的 pom.xml 中声明对 lombok 的依赖。3. 为什么使用 optional？避免不必要的传递依赖：某些依赖可能只是当前项目的一部分功能所需，而不是所有功能都需要。通过设置 <optional>true</optional>，可以减少传递依赖的复杂性。灵活性：允许其他模块根据需要选择是否引入该依赖。4. 示例场景假设您有一个项目 A，它依赖了 lombok 并将其标记为 <optional>true</optional>。另一个项目 B 依赖了项目 A：如果项目 B 不需要使用 lombok，则无需额外配置。如果项目 B 需要使用 lombok，则必须在项目 B 的 pom.xml 中显式声明对 lombok 的依赖。5. 总结<optional>true</optional> 的主要作用是控制依赖的传递性，避免不必要的依赖被传递到其他模块或项目中。这种配置通常用于以下情况：依赖仅在特定场景下使用。希望减少传递依赖的复杂性，提高项目的灵活性。在您的 pom.xml 中，lombok 和 spring-boot-devtools 被标记为 <optional>true</optional>，这表明这些依赖并非所有模块都必需，其他模块可以根据需要自行决定是否引入它们。

Maven中dependency的scope有哪些？
type: item
date: 2025-04-13T02:04:00+00:00
description: 在 Maven 中，<dependency> 的 scope 用于控制依赖项在构建生命周期的不同阶段是否可用。共有 6 种标准 scope，每种适用于不同的场景：1. compile（默认值，未指定时使用）✅ 编译（compile）、测试（test）、运行（runtime） 均可用⚠️ 会包含在最终的打包（JAR/WAR）中? 适用场景：项目中绝大多数依赖（如 Spring Core、Lombok、Gson）2. provided✅ 编译（compile）、测试（test） 可用❌ 运行时（runtime）由目标环境（如JDK/Tomcat）提供，不会打到包里? 适用场景：Servlet API、JDBC API（javax.servlet:servlet-api、Java EE APIs）3. runtime❌ 编译时（compile）不可用（无法 import 使用）✅ 测试（test）、运行（runtime） 可用? 适用场景：JDBC 驱动、反射加载的实现类（mysql-connector-java）4. test✅ 仅在测试（test）和测试编译阶段 可用❌ 不会打包到发布版本（如生产环境 JAR 包）? 适用场景：JUnit、Mockito、TestNG5. system（已弃用）✅ 类似于 provided，但要显式指定 JAR 路径（systemPath）⚠️ 不推荐使用（易移植性差）? 适用场景：本地库文件（极少使用）6. import（仅适用于 <dependencyManagement>）✅ 用于 导入 BOM（Bill of Materials） 定义的依赖版本⚠️ 不实际引入依赖，只是版本管理? 适用场景：Spring Boot BOM（spring-boot-dependencies）总结对比表Scope编译（compile）可用？测试（test）可用？运行（runtime）可用？打包（package）是否包含？主要用途compile✅✅✅✅项目主要依赖（默认值）provided✅✅❌❌由运行时环境提供（如 Tomcat 的 Servlet API）runtime❌✅✅✅仅运行时需要（如 JDBC 驱动）test❌✅❌❌测试专用（JUnit、Mockito）system✅✅❌?（取决于配置）本地 JAR（已废弃）import----仅管理依赖版本（BOM 导入）其中，最常用的是 compile、provided、runtime、test，而 system 应避免使用，import 主要用于依赖管理。

SQL Server中对JSON的处理
type: item
date: 2025-02-27T02:07:00+00:00
description: 在 SQL Server 中，使用内置的 JSON 函数来解析和查询 JSON 数据。SQL Server 从 2016 版本开始支持 JSON 功能。以下是解析 JSON 数据的详细方法和示例：1. 检查 JSON 数据ISJSON()ISJSON 函数用于检查字符串是否为有效的 JSON。DECLARE @json NVARCHAR(MAX) = '{"name": "Alice", "age": 25}'; SELECT ISJSON(@json) AS is_valid_json;输出：is_valid_json1如果返回 1，表示字符串是有效的 JSON；返回 0，表示无效。2. 解析 JSON 对象JSON_VALUE()JSON_VALUE 用于从 JSON 中提取标量值（如字符串、数字）。DECLARE @json NVARCHAR(MAX) = '{"name": "Alice", "age": 25}'; SELECT JSON_VALUE(@json, '$.name') AS name, JSON_VALUE(@json, '$.age') AS age;输出：nameageAlice253. 解析 JSON 数组JSON_QUERY()JSON_QUERY 用于从 JSON 中提取数组或对象。DECLARE @json NVARCHAR(MAX) = '{"name": "Alice", "hobbies": ["reading", "swimming"]}'; SELECT JSON_QUERY(@json, '$.hobbies') AS hobbies;输出：hobbies["reading", "swimming"]4. 解析嵌套 JSONJSON_VALUE() 和 JSON_QUERY()对于嵌套的 JSON，可以组合使用 JSON_VALUE 和 JSON_QUERY。DECLARE @json NVARCHAR(MAX) = '{"user": {"name": "Alice", "age": 25}}'; SELECT JSON_VALUE(@json, '$.user.name') AS name, JSON_VALUE(@json, '$.user.age') AS age;输出：nameageAlice255. 解析 JSON 数组中的元素使用 OPENJSON 函数将 JSON 数组解析为表格形式。DECLARE @json NVARCHAR(MAX) = '[{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]'; SELECT * FROM OPENJSON(@json) WITH ( name NVARCHAR(50) '$.name', age INT '$.age' );输出：nameageAlice25Bob306. 解析嵌套 JSON 数组对于嵌套的 JSON 数组，可以多次调用 OPENJSON。DECLARE @json NVARCHAR(MAX) = '{"user": {"name": "Alice", "hobbies": ["reading", "swimming"]}}'; SELECT JSON_VALUE(@json, '$.user.name') AS name, value AS hobby FROM OPENJSON(JSON_QUERY(@json, '$.user.hobbies'));输出：namehobbyAlicereadingAliceswimming7. 查询 JSON 中的数据可以通过 WHERE 子句筛选 JSON 数据。DECLARE @json NVARCHAR(MAX) = '[{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]'; SELECT name, age FROM OPENJSON(@json) WITH ( name NVARCHAR(50) '$.name', age INT '$.age' ) WHERE age > 25;输出：nameageBob308. 将 JSON 数据插入到表中使用 OPENJSON 将 JSON 数据插入到表中。DECLARE @json NVARCHAR(MAX) = '[{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]'; INSERT INTO users (name, age) SELECT name, age FROM OPENJSON(@json) WITH ( nam…