Error updating database. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 不能将值 NULL 插入列 'ID',表 'ARDB_SJ.dbo.tSys_OperationLog';列不允许有 Null 值。INSERT 失败。 ### The error may involve com.zd.archives.admin.system.operationlog.TsysOperationlogMapper.insert-Inline ### The error occurred while setting parameters ### SQL: insert into TSYS_OPERATIONLOG (CUSER, CTIME, CPC, SPC, MEMO, OPTIME) values ( ?, ?, ?, ?, ?, ?) ### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 不能将值 NULL 插入列 'ID',表 'ARDB_SJ.dbo.tSys_OperationLog';列不允许有 Null 值。INSERT 失败。 ; SQL []; 不能将值 NULL 插入列 'ID',表 'ARDB_SJ.dbo.tSys_OperationLog';列不允许有 Null 值。INSERT 失败。; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: 不能将值 NULL 插入列 'ID',表 'ARDB_SJ.dbo.tSys_OperationLog';列不允许有 Null 值。INSERT 失败。 at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:102) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446) at com.sun.proxy.$Proxy42.insert(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:278) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:57)数据库升级之后一直报错
时间: 2025-03-25 10:13:43 浏览: 75
<think>好的,我现在需要解决用户遇到的数据库插入错误,具体是尝试将NULL值插入不允许为NULL的ID列的问题。用户提到数据库升级后一直报错,所以需要分析可能的原因和解决方案。
首先,错误信息显示在插入TSYS_OPERATIONLOG表时,ID列不能为NULL。这说明在插入语句中没有为ID列提供值,而该列又不允许NULL。可能的原因包括:
1. **ID列没有设置自增属性**:在数据库升级后,可能ID列的自增属性被移除了,导致插入时必须显式提供值。
2. **主键生成策略配置错误**:如果使用MyBatis或类似框架,可能主键的生成策略(如IDENTITY、序列等)配置不正确,导致框架没有自动生成ID。
3. **插入语句未包含ID列**:检查插入的SQL语句,是否漏掉了ID列,导致MyBatis没有处理该字段。
4. **数据库触发器或默认值失效**:升级后可能影响到触发器或默认值,原本依赖这些机制生成ID的方式失效了。
5. **代码逻辑问题**:可能在升级后,代码中手动设置ID的逻辑被修改或移除。
接下来需要一步步排查这些问题。首先检查数据库表结构,确认ID列是否自增。然后查看MyBatis的映射文件,确认主键生成策略是否正确。同时检查插入语句是否包含ID列,或者在实体类中是否有对应的字段。如果使用数据库的默认值或触发器,需要验证这些是否还存在并正常工作。
可能的解决方案包括启用自增属性、修正MyBatis的主键配置、修改插入语句包含ID或调整数据库的默认值。此外,还要考虑升级后的兼容性问题,比如驱动版本是否匹配,或者是否有其他配置变更影响了ID的生成。
用户是开发者,可能需要具体的SQL检查和代码调整步骤,以及如何验证配置是否正确。需要给出清晰的步骤,比如如何检查自增属性,如何修改MyBatis的XML配置,如何测试插入操作等。同时提醒用户注意备份和测试环境的重要性,避免直接在生产环境中修改。</think>---
### **问题根源**
数据库表 `tSys_OperationLog` 的 `ID` 列不允许为空值,但在插入数据时未显式提供 `ID` 值,且数据库未自动生成该值(例如自增未启用或主键生成策略失效)。
---
### **解决方案**
#### **1. 检查表结构**
确认 `ID` 列是否为自增主键:
```sql
-- 查看列属性
SELECT COLUMN_NAME, IS_NULLABLE, COLUMN_DEFAULT, COLUMNPROPERTY(OBJECT_ID('tSys_OperationLog'), 'ID', 'IsIdentity') AS IsIdentity
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tSys_OperationLog' AND COLUMN_NAME = 'ID';
-- 预期结果示例:
-- | COLUMN_NAME | IS_NULLABLE | COLUMN_DEFAULT | IsIdentity |
-- |-------------|-------------|----------------|------------|
-- | ID | NO | NULL | 1 |
```
- **若 `IsIdentity=0`**:说明自增未启用,需修复表结构。
- **若 `IsIdentity=1`**:说明自增已启用,问题出在代码生成策略。
---
#### **2. 修复自增配置**
如果自增未启用,通过以下 SQL 启用自增:
```sql
-- 删除原主键(假设主键名为 PK_tSys_OperationLog)
ALTER TABLE tSys_OperationLog DROP CONSTRAINT PK_tSys_OperationLog;
-- 重新创建自增主键
ALTER TABLE tSys_OperationLog
ALTER COLUMN ID INT IDENTITY(1,1) NOT NULL;
ALTER TABLE tSys_OperationLog
ADD CONSTRAINT PK_tSys_OperationLog PRIMARY KEY (ID);
```
---
#### **3. 检查 MyBatis 主键生成策略**
在实体类映射文件(如 `TsysOperationlogMapper.xml`)中,确保 `ID` 列配置了自增策略:
```xml
<insert id="insert" parameterType="TsysOperationlog">
<!-- 关键:声明使用数据库自增主键 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT SCOPE_IDENTITY()
</selectKey>
INSERT INTO TSYS_OPERATIONLOG (CUSER, CTIME, CPC, SPC, MEMO, OPTIME)
VALUES (#{cuser}, #{ctime}, #{cpc}, #{spc}, #{memo}, #{optime})
</insert>
```
- **注意**:`keyProperty="id"` 必须与实体类字段名严格匹配(区分大小写)。
---
#### **4. 检查实体类定义**
确认实体类 `TsysOperationlog` 中的 `ID` 字段是否被正确映射且未被忽略:
```java
public class TsysOperationlog {
private Integer id; // 必须与数据库列名匹配(注意大小写)
private String cuser;
private Date ctime;
// ...其他字段
// 必须提供 getter/setter 方法
}
```
---
#### **5. 临时解决方案(不推荐)**
如果无法修改表结构,可以显式插入 `ID` 值(需确保唯一性):
```sql
INSERT INTO TSYS_OPERATIONLOG (ID, CUSER, CTIME, CPC, SPC, MEMO, OPTIME)
VALUES ((SELECT ISNULL(MAX(ID)+1, 1) FROM TSYS_OPERATIONLOG), ?, ?, ?, ?, ?, ?)
```
但此方法存在并发风险,仅建议临时使用。
---
### **排查流程**
| 步骤 | 操作 | 预期结果 |
|------|------|----------|
| 1 | 检查 `ID` 列是否为自增 | `IsIdentity=1` |
| 2 | 检查 MyBatis 映射文件 | `<selectKey>` 正确配置 |
| 3 | 检查实体类字段 | 存在 `id` 字段且大小写匹配 |
| 4 | 测试插入操作 | 插入成功且 `ID` 自动生成 |
---
### **常见陷阱**
1. **驱动兼容性问题**
确保使用与 SQL Server 版本匹配的 JDBC 驱动(例如 SQL Server 2019+ 需使用 `mssql-jdbc-10.2.x.jre11.jar`)。
2. **字段名大小写敏感**
SQL Server 默认不区分大小写,但 MyBatis 严格匹配字段名(如 `id` vs `ID`)。
3. **事务未提交**
如果启用了手动事务,需确认插入操作后执行了 `commit()`。
---
### **扩展建议**
- **数据库版本回退检查**
如果问题在升级后出现,对比新旧版本的 `tSys_OperationLog` 表结构差异(使用工具如 **SQL Compare**)。
- **日志调试**
启用 MyBatis 的 SQL 日志,观察实际执行的语句:
```properties
# application.properties
logging.level.com.zd.archives.admin.system.operationlog=DEBUG
```
阅读全文
相关推荐


















