post mysql更新语句_PostgreSQL UPDATE 语句

本文介绍如何使用 PostgreSQL 的 UPDATE 语句来修改数据库表中的数据。通过具体实例展示了如何更新单个字段及多个字段,并解释了 WHERE 子句的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PostgreSQL UPDATE 语句

如果我们要更新在 PostgreSQL 数据库中的数据,我们可以用 UPDATE 来操作。

语法

以下是 UPDATE 语句修改数据的通用 SQL 语法:

UPDATE table_name

SET column1 = value1, column2 = value2...., columnN = valueN

WHERE [condition];

我们可以同时更新一个或者多个字段。

我们可以在 WHERE 子句中指定任何条件。

实例

创建 COMPANY 表(下载 COMPANY SQL 文件 ),数据内容如下:

runoobdb# select * from COMPANY;

id | name | age | address | salary

----+-------+-----+-----------+--------

1 | Paul | 32 | California| 20000

2 | Allen | 25 | Texas | 15000

3 | Teddy | 23 | Norway | 20000

4 | Mark | 25 | Rich-Mond | 65000

5 | David | 27 | Texas | 85000

6 | Kim | 22 | South-Hall| 45000

7 | James | 24 | Houston | 10000

(7 rows)

以下实例将更新 COMPANY 表中 id 为 3 的 salary 字段值:

runoobdb=# UPDATE COMPANY SET SALARY = 15000 WHERE ID = 3;

得到结果如下:

id | name | age | address | salary

----+-------+-----+------------+--------

1 | Paul | 32 | California | 20000

2 | Allen | 25 | Texas | 15000

4 | Mark | 25 | Rich-Mond | 65000

5 | David | 27 | Texas | 85000

6 | Kim | 22 | South-Hall | 45000

7 | James | 24 | Houston | 10000

3 | Teddy | 23 | Norway | 15000

从结果上看,COMPANY 表中的 id 为 3 的 salary 字段值已被修改。

以下实例将同时更新 salary 字段和 address 字段的值:

runoobdb=# UPDATE COMPANY SET ADDRESS = 'Texas', SALARY=20000;

得到结果如下:

id | name | age | address | salary

----+-------+-----+---------+--------

1 | Paul | 32 | Texas | 20000

2 | Allen | 25 | Texas | 20000

4 | Mark | 25 | Texas | 20000

5 | David | 27 | Texas | 20000

6 | Kim | 22 | Texas | 20000

7 | James | 24 | Texas | 20000

3 | Teddy | 23 | Texas | 20000

(7 rows)

<think>我们正在检查用户提供的代码片段,包括实体类、Mapper接口、Mapper XML文件、Service接口、Service实现类以及Controller类。 我们将逐一检查这些代码的语法和逻辑问题。 1. 实体类:EquTypeDomain - 使用了Lombok注解(@Data, @NoArgsConstructor, @AllArgsConstructor, @ToString),这些注解在编译时会生成代码,所以语法上没有问题。 - 字段定义:每个字段都有@TableField注解指定数据库字段名,类型匹配也合理(String和int)。 - 注意:`typeid`字段是int类型,而数据库中的`type_id`字段可能是整数类型,所以匹配没有问题。 - 逻辑问题:没有发现明显的逻辑问题。 2. Mapper接口:EquTypesMapper - 接口中定义了增删改查的方法,但注意:这个接口没有继承MyBatis-Plus的BaseMapper,而是自己定义的方法。这是允许的,但需要确保XML映射正确。 - 方法名和参数: add(EquTypeDomain domain) -> 插入 selectEquTypeByName(String name) -> 根据名称查询 delete(String id) -> 根据id删除 update(EquTypeDomain domain) -> 更新 getList(EquTypeDomain domain) -> 条件查询列表 - 语法正确。 3. Mapper XML:EquTypesMapper.xml - 命名空间指向正确的Mapper接口:`com.gongye.basic.mapper.EquTypesMapper` - 各个SQL语句的id与接口方法名一致。 - 插入语句: insert into equ_type(...) values (...) 使用uuid()生成id,注意:这里使用数据库的uuid函数,需要确保数据库支持(如MySQL的uuid()函数不存在,应改为UUID()或使用应用层生成)。这是一个潜在问题。 MySQL中生成UUID的函数是UUID(),不是uuid()(大小写敏感?在MySQL中函数名不区分大小写,但通常写作大写)。但注意,在MySQL中,函数名是不区分大小写的,所以uuid()和UUID()都可以。但是,如果数据库是其他类型(如PostgreSQL)则可能不同。不过,用户可能是MySQL且使用小写,但为了保险,通常使用大写UUID()。 另外,插入语句中字段名与实体类字段对应,但注意数据库表字段名是否与这里一致(如:create_nick_name,update_nick_name等)。 - 查询语句:selectEquTypeByName 参数类型是EquTypeDomain,但实际只需要一个name字符串。这里参数类型与方法参数类型不一致:方法参数是String,而XML中参数类型是EquTypeDomain。这会导致错误,因为MyBatis在解析参数时,如果方法参数是基本类型或String,那么应该使用参数名(如`#{name}`)直接引用。而这里如果参数类型是String,那么XML中应该写`#{name}`,并且参数类型应该是`String`(而不是EquTypeDomain)。因此,这里存在错误。 - 删除语句:delete 参数类型是EquTypeDomain,但方法参数是String(id)。同样的问题:XML中参数类型应该是String,然后使用`#{id}`引用。 - 更新语句update 参数类型正确(EquTypeDomain),但是更新语句中有一个错误:将`updatenickname`字段设置为NOW(),这明显不对,应该是更新时间字段(updatetime)设置为NOW(),而更新人昵称应该是传入的。另外,更新语句中设置`updatenickname = NOW()`,这显然是个错误,应该设置为`#{updatenickname}`。同时,我们注意到更新语句中并没有将`updatetime`更新为当前时间,而插入时创建时间和更新时间都是NOW(),更新时通常只更新更新时间。所以这里逻辑错误:更新时,应该将`updatetime`设置为NOW(),而`updatenickname`是传入的更新人昵称。 当前更新语句UPDATE equ_type SET name = #{name}, typeid = #{typeid}, createby = #{createby}, // 注意:更新时通常不更新创建人和创建时间 updateby = #{updateby}, createtime = #{createtime}, // 同样,创建时间也不应该更新 updatetime = #{updatetime}, // 这里应该设置为当前时间,但语句中并没有 createnickname = #{createnickname}, // 不应该更新 updatenickname = NOW(), // 错误:应该是传入的更新人昵称,而不是当前时间 remark = #{remark} WHERE id = #{id} 所以更新语句需要调整:更新时,不应该更新创建相关的字段(createby, createtime, createnickname),而更新时间字段(updatetime)应该设置为当前时间,更新人昵称(updatenickname)应该设置为传入的。 - 查询列表:getList 这个查询使用了INNER JOIN,连接equ_info表,条件是equ_type.id = equ_info.id。但是,这里存在逻辑问题:equ_type和equ_info通过id关联?这通常意味着equ_info表的主键也是equ_type表的主键,即它们是一对一的关系。但是,从表名看,equ_type是设备类型表,equ_info可能是设备信息表,那么设备信息表中的设备类型字段(typeid)应该是引用equ_type表的id。所以,这里应该是equ_info.typeid = equ_type.id?或者根本不需要连接?因为查询的是设备类型列表,为什么要连接设备信息表? 另外,在查询字段中,使用了`equ_info.typeid`,而返回结果映射到EquTypeDomain,这个对象有一个typeid字段(int类型)。但是,在equ_type表中本来就有typeid字段(在插入语句中也有),为什么还要从equ_info表取typeid?而且,如果连接了equ_info表,那么当一种设备类型对应多个设备信息时,会导致重复记录。所以,这个连接可能是多余的,或者逻辑错误。 此外,WHERE条件中使用了`typeid`和`name`,注意条件中的`typeid`是哪个表的?因为查询字段中指定了`equ_info.typeid`,而条件中写的是`typeid`,这会产生歧义(如果两个表都有typeid字段)。但这里equ_type表有typeid字段,而equ_info表也有typeid字段(假设)。所以,应该明确指定表名。 所以,这个查询可能需要重新考虑。根据方法名getList,应该是查询设备类型列表,那么直接查询equ_type表即可,不需要连接equ_info表。 4. Service接口:IEquTypesService - 方法定义与Mapper接口基本一致,但注意add方法声明了throws Exception,其他方法没有。 - 语法正确。 5. Service实现类:IEquTypesServiceImpl - 使用@Service注解,注入EquTypesMapper。 - add方法:先检查name是否为空,然后检查是否已存在,再插入。逻辑正确,但注意:检查已存在时,调用了equTypesMapper.selectEquTypeByName(domain.getName()),这个方法在Mapper中定义,但之前我们注意到Mapper XML中这个语句的参数类型错误,所以这里可能会出错(传入的是String,但XML中期望的是EquTypeDomain对象)。 - delete、update、getList方法直接调用Mapper,没有额外逻辑。 6. Controller:EquTypesController - 使用@RestController,映射路径为"/equ/types"。 - add方法:接收POST请求,参数为@RequestBody EquTypeDomain,调用service的add方法,返回AjaxResult。正常。 - getlist方法:GET请求,参数为EquTypeDomain(非@RequestBody,所以是URL参数绑定),使用分页(startPage()),调用getList,返回TableDataInfo(分页数据)。正常。 - delete方法:DELETE请求,路径变量id,调用delete方法。正常。 - update方法:PUT请求,@RequestBody EquTypeDomain,调用update方法。正常。 总结问题: 1. Mapper XML中: a. selectEquTypeByName 语句的参数类型应该是String,而不是EquTypeDomain。需要修改为: <select id="selectEquTypeByName" parameterType="java.lang.String" resultType="com.gongye.basic.domain.EquTypeDomain"> SELECT * FROM equ_type WHERE name = #{name} </select> b. delete 语句的参数类型应该是String,而不是EquTypeDomain。需要修改为: <delete id="delete" parameterType="java.lang.String"> DELETE FROM equ_type WHERE id = #{id} </delete> c. update 语句存在多个问题: - 更新了不应该更新的字段(创建人、创建时间、创建人昵称) - 更新时间字段(updatetime)没有更新为当前时间 - 更新人昵称(updatenickname)被错误设置为NOW() 应该修改为: <update id="update" parameterType="com.gongye.basic.domain.EquTypeDomain"> UPDATE equ_type SET name = #{name}, typeid = #{typeid}, updateby = #{updateby}, updatetime = NOW(), <!-- 更新时间为当前时间 --> updatenickname = #{updatenickname}, <!-- 更新人昵称 --> remark = #{remark} WHERE id = #{id} </update> d. getList 语句:连接equ_info表可能是不必要的,而且可能导致重复数据。如果目的是查询设备类型列表,应该去掉连接。如果确实需要连接,那么要明确连接条件(可能是equ_info.typeid=equ_type.id?)并且注意去重(使用DISTINCT或者改用左连接并处理重复)。另外,条件中的字段应该指定表名,避免歧义。 建议:如果不需要连接,则改为: <select id="getList" parameterType="com.gongye.basic.domain.EquTypeDomain" resultType="com.gongye.basic.domain.EquTypeDomain"> SELECT * FROM equ_type <where> <if test="typeid != null and typeid != ''">AND typeid = #{typeid}</if> <if test="name != null and name != ''">AND name LIKE CONCAT('%', #{name}, '%')</if> </where> </select> 2. Mapper接口:方法参数与XML中参数类型需要一致。上面已经指出,selectEquTypeByName和delete方法的参数类型在XML中需要修改。 3. Service实现类:在add方法中,调用了selectEquTypeByName,由于XML中该语句参数类型错误,会导致执行失败。修复XML后即可。 4. 插入操作:在XML的insert语句中,使用uuid()生成主键id。如果数据库MySQL,则应该使用UUID()函数(但MySQL中函数名不区分大小写,所以uuid()也可以)。但是,在应用层生成主键可能更好,因为这样可以在插入前知道主键。另外,如果使用自增主键,则可以使用MyBatis-Plus的注解。但这里用户使用的是String类型的主键,所以使用UUID是可以的。不过,注意在插入后,如果需要返回主键,可以使用`useGeneratedKeys`和`keyProperty`(但这里不是自增,所以不能使用)。可以使用`<selectKey>`来获取生成的UUID(如果数据库支持),但这里直接作为插入,所以没有返回。在Service层,插入后domain对象的id还是null,因为数据库生成的id没有回填。如果需要回填,可以修改插入语句,在插入前生成UUID(在Java中生成,使用UUID.randomUUID().toString()),然后设置到domain对象中,这样插入后就可以使用这个id了。 5. 更新操作:在Service实现类的update方法中,没有做任何校验(比如检查id是否存在,或者name是否重复)。根据业务需求,可能需要检查。但用户没有要求,所以可以忽略。 6. 另外,在实体类中,字段名采用驼峰命名,而数据库字段名使用下划线分隔,这是符合MyBatis-Plus的配置的(默认开启驼峰转下划线)。但是,在XML中,我们直接使用下划线字段名,这是正确的。 因此,主要问题集中在Mapper XML文件的参数类型和更新逻辑上,以及查询列表的连接问题。 建议修改: - 修改selectEquTypeByName和delete语句的参数类型。 - 修改update语句,只更新必要的字段,并正确设置更新时间。 - 重新考虑getList查询是否需要连接equ_info表,如果不需要则去掉连接。 如果用户确实需要在查询设备类型列表时关联设备信息表(比如统计每个类型的设备数量),那么应该使用分组查询,而不是简单的连接。但当前查询返回的是EquTypeDomain对象列表,所以连接equ_info表是不必要的。 修正后的Mapper XML文件(部分): <select id="selectEquTypeByName" parameterType="java.lang.String" resultType="com.gongye.basic.domain.EquTypeDomain"> SELECT * FROM equ_type WHERE name = #{name} </select> <delete id="delete" parameterType="java.lang.String"> DELETE FROM equ_type WHERE id = #{id} </delete> <update id="update" parameterType="com.gongye.basic.domain.EquTypeDomain"> UPDATE equ_type SET name = #{name}, typeid = #{typeid}, updateby = #{updateby}, updatetime = NOW(), updatenickname = #{updatenickname}, remark = #{remark} WHERE id = #{id} </update> <select id="getList" parameterType="com.gongye.basic.domain.EquTypeDomain" resultType="com.gongye.basic.domain.EquTypeDomain"> SELECT * FROM equ_type <where> <if test="typeid != null and typeid != ''">AND typeid = #{typeid}</if> <if test="name != null and name != ''">AND name LIKE CONCAT('%', #{name}, '%')</if> </where> </select> 这样修改后,逻辑应该正确了。 注意:在getList中,条件判断`<if test="typeid != null and typeid != ''">`,因为typeid是int类型,所以当typeid为0时,条件也会被跳过(因为0 != '' 会返回false?实际上,MyBatis在判断时,对于int类型的属性,如果传入0,那么`typeid != ''`会返回true,因为MyBatis会将空字符串转换为0,所以0 != '' 是true?但这样写可能有问题,因为int类型没有空字符串的概念。建议改为: <if test="typeid != null"> <!-- 对于基本类型int,传入的永远不为null,所以这个条件可能总是成立? --> 实际上,在MyBatis中,对于基本类型(int)的参数,如果传入的是null,那么会自动设为0(对于int)?所以这里用`typeid != null`对于基本类型是无效的,因为基本类型不可能为null。所以,如果用户想查询typeid为0的记录,那么这个条件就会被跳过(因为0 != '' 在OGNL表达式中:''会被转换为0,所以0!=0为false)。因此,建议将typeid改为Integer包装类型,这样就可以判断null。或者,如果一定要用int,那么可以去掉对空字符串的判断,只保留`typeid != 0`(但这样0就不会被查询)。或者,直接去掉这个条件中的`and typeid != ''`,只写`<if test="typeid != null">`,但基本类型永远不为null,所以这个条件总是成立?所以对于基本类型,这个条件判断是有问题的。 解决方案: 将EquTypeDomain中的typeid改为Integer类型,这样在条件中就可以判断null,并且0和''的问题也可以避免(因为Integer类型为0时,`typeid != ''`会将0与''比较,结果为false?所以0会被过滤掉?这不是我们想要的)。所以,更好的做法是: <if test="typeid != null"> <!-- 当typeid不为null时,才加入条件 --> 这样,如果传入的typeid为0(Integer对象),那么条件会加入(因为0!=null),这样就可以查询typeid=0的记录。同时,如果传入的typeid为null,则不加入条件。 因此,建议将EquTypeDomain中的typeid从int改为Integer。 但是,这个修改影响较大(涉及插入、更新等操作)。如果不想修改,那么可以这样写条件: <if test="typeid != 0">AND typeid = #{typeid}</if> 这样,当typeid为0时,条件不加入,即查询所有。但这样无法查询typeid=0的记录(因为条件被跳过了)。所以,如果0是有效,那么就不能这样写。 所以,权衡之后,最好将typeid改为Integer类型。 由于用户代码中typeid是int,我们暂时不修改,但需要知道这个条件在typeid=0时不会生效(即不会按typeid=0查询,而是忽略这个条件)。如果业务中0是有效,那么需要调整。 综上所述,除了Mapper XML的问题,还有条件查询中的类型问题需要注意。 由于用户没有提供完整的业务需求,我们只针对明显错误进行修正。</think>### 代码问题分析与修正建议 #### 1. **Mapper XML 文件问题** ##### (1) 参数类型不匹配 ```xml <!-- 错误:参数类型应为 String --> <select id="selectEquTypeByName" parameterType="com.gongye.basic.domain.EquTypeDomain"> ``` **问题**:`selectEquTypeByName` 方法参数是 `String name`,但 XML 中声明为 `EquTypeDomain` 类型。 **修正**: ```xml <select id="selectEquTypeByName" parameterType="java.lang.String" resultType="com.gongye.basic.domain.EquTypeDomain"> ``` ##### (2) 更新逻辑错误 ```xml <update id="update"> ... updatenickname = NOW(), <!-- 错误:此处应为字段 --> remark = #{remark} </update> ``` **问题**: - `updatenickname` 被错误设置为 `NOW()`(应为 `#{updatenickname}`) - 未更新 `updatetime` 字段(应设为当前时间) - 错误更新了只读字段(`createby`, `createtime` 等) **修正**: ```xml <update id="update" parameterType="com.gongye.basic.domain.EquTypeDomain"> UPDATE equ_type SET name = #{name}, typeid = #{typeid}, updateby = #{updateby}, updatetime = NOW(), <!-- 修正更新时间 --> updatenickname = #{updatenickname}, <!-- 修正为传入 --> remark = #{remark} WHERE id = #{id} </update> ``` ##### (3) 多表连接逻辑错误 ```xml <select id="getList"> FROM equ_type INNER JOIN equ_info ON equ_type.id = equ_info.id <!-- 错误连接条件 --> </select> ``` **问题**: - 连接条件 `equ_type.id = equ_info.id` 不合理(主表主键关联从表主键) - 实际业务应为 **设备类型表关联设备信息表的类型字段**,如 `equ_info.typeid = equ_type.id` **修正**: ```xml <select id="getList" resultType="com.gongye.basic.domain.EquTypeDomain"> SELECT equ_type.* <!-- 明确指定表字段 --> FROM equ_type <!-- 修正连接逻辑 --> <!-- 若需关联设备信息,使用:LEFT JOIN equ_info ON equ_info.typeid = equ_type.id --> </select> ``` #### 2. **Service 层问题** ##### 更新操作缺少校验 ```java // 缺失关键校验 public int update(EquTypeDomain domain) { return equTypesMapper.update(domain); // 未检查名称重复 } ``` **问题**:更新时未校验名称是否与其他记录重复。 **修正**: ```java public int update(EquTypeDomain domain) throws Exception { EquTypeDomain existing = equTypesMapper.selectEquTypeByName(domain.getName()); if (existing != null && !existing.getId().equals(domain.getId())) { throw new Exception("名称已存在"); } return equTypesMapper.update(domain); } ``` #### 3. **Controller 层问题** ##### 删除方法参数不匹配 ```java @DeleteMapping("/{id}") public AjaxResult deleteEquType(@PathVariable String id) { return toAjax(iEquTypesService.delete(id)); } ``` **Mapper 问题**: ```xml <delete id="delete" parameterType="com.gongye.basic.domain.EquTypeDomain"> DELETE FROM equ_type WHERE id = #{id} <!-- 参数类型错误 --> </delete> ``` **修正**: ```xml <delete id="delete" parameterType="java.lang.String"> DELETE FROM equ_type WHERE id = #{id} </delete> ``` ### 关键问题总结 | 位置 | 问题描述 | 严重性 | 修正建议 | |--------------|----------------------------|--------|---------------------------------| | Mapper XML | 参数类型不匹配 | 高 | 统一方法参数与XML parameterType | | Mapper XML | 更新语句字段错误 | 高 | 移除只读字段,修正错误赋 | | Mapper XML | 多表连接逻辑错误 | 中 | 调整关联条件为业务合理关系 | | Service 层 | 更新操作缺失业务校验 | 中 | 添加名称重复校验逻辑 | | Controller | 参数传递类型不一致 | 高 | 统一各层参数类型 | ### 语法问题排查结果 1. **无编译级语法错误**:代码符合 Java 基本语法规范 2. **Lombok 注解使用正确**:`@Data`, `@NoArgsConstructor` 等注解使用合理 3. **MyBatis 基础映射正确**:`@TableField` 注解与数据库字段匹配正确 4. **Spring 注解规范**:`@RestController`, `@Resource` 等使用符合标准 > **建议整体改进**: > 添加事务管理 `@Transactional` 在 Service 层,确保数据一致性[^1]。 > 使用 MyBatis-Plus 的 `BaseMapper` 可减少基础 SQL 编写(需调整 Mapper 继承)[^2]。 ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值