Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
676b953e
authored
Aug 20, 2026
by
renyizhao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
spu 导入修改,表单去掉销量,销量自增
parent
f2e21d79
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
563 additions
and
183 deletions
+563
-183
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourcespu/ResourceSpuImportController.java
+1
-1
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourcespu/vo/ResourceSpuSaveReqVO.java
+1
-2
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/dal/mysql/resourcespu/ResourceSpuMapper.java
+10
-0
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourceorder/ResourceOrderServiceImpl.java
+38
-0
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourcespu/ResourceSpuImportServiceImpl.java
+53
-45
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourcespu/ResourceSpuServiceImpl.java
+4
-0
computility-module-compute/computility-module-compute-biz/src/main/resources/mapper/resourcespu/ResourceSpuMapper.xml
+14
-0
sql/migration/2026_08_17_add_config_compute.sql
+79
-14
sql/migration/2026_08_18_verify_api_calls_trend_v2.sql
+0
-121
sql/migration/2026_08_19_fix_missing_order_fields.sql
+98
-0
sql/migration/2026_08_19_fix_order_update_time_and_missing_fields.sql
+144
-0
sql/migration/2026_08_19_fix_snapshot_rename_columns.sql
+121
-0
No files found.
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourcespu/ResourceSpuImportController.java
View file @
676b953e
...
...
@@ -40,7 +40,7 @@ public class ResourceSpuImportController {
/** 固定列头 */
private
static
final
List
<
String
>
FIXED_HEADERS
=
List
.
of
(
"商品名称"
,
"商品分类"
,
"算力来源"
,
"商品简介"
,
"
封面图"
,
"商品销量"
,
"状态
"
);
"商品名称"
,
"商品分类"
,
"算力来源"
,
"商品简介"
,
"
服务器所在地
"
);
@Resource
private
ResourceSpuImportService
resourceSpuImportService
;
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/controller/admin/resourcespu/vo/ResourceSpuSaveReqVO.java
View file @
676b953e
...
...
@@ -37,8 +37,7 @@ public class ResourceSpuSaveReqVO {
@Schema
(
description
=
"商品轮播图地址,以逗号分隔,最多15张"
)
private
String
sliderPicUrls
;
@Schema
(
description
=
"商品销量"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
@NotNull
(
message
=
"商品销量不能为空"
)
@Schema
(
description
=
"商品销量(默认 0,由订单支付回调自动累加)"
)
private
Integer
sales
;
@Schema
(
description
=
"服务器所在地"
)
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/dal/mysql/resourcespu/ResourceSpuMapper.java
View file @
676b953e
...
...
@@ -128,4 +128,14 @@ public interface ResourceSpuMapper extends BaseMapperX<ResourceSpuDO> {
* 返回 [{areaId, compute}]
*/
List
<
Map
<
String
,
Object
>>
selectSumComputeByAreaId
();
/**
* 累加 SPU 销量(订单支付成功回调使用)
*
* @param id SPU 主键
* @param increment 增量(正数加、负数减;订单取消时传负数即可)
* @param updater 操作人
* @return 受影响行数
*/
int
incrSalesById
(
@Param
(
"id"
)
Long
id
,
@Param
(
"increment"
)
int
increment
,
@Param
(
"updater"
)
String
updater
);
}
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourceorder/ResourceOrderServiceImpl.java
View file @
676b953e
...
...
@@ -23,6 +23,7 @@ import com.luhu.computility.module.compute.dal.dataobject.resourcesku.ResourceSk
import
com.luhu.computility.module.compute.dal.dataobject.resourceordersnapshot.ResourceOrderSnapshotDO
;
import
com.luhu.computility.module.compute.dal.dataobject.resourcespuspecvalue.ResourceSpuSpecValueDO
;
import
com.luhu.computility.module.compute.dal.mysql.resourceorder.ResourceOrderMapper
;
import
com.luhu.computility.module.compute.dal.mysql.resourcespu.ResourceSpuMapper
;
import
com.luhu.computility.module.compute.dal.redis.no.ResourceOrderNoRedisDAO
;
import
com.luhu.computility.module.compute.enums.ResourceOrderInvoiceStatus
;
import
com.luhu.computility.module.compute.enums.ResourceOrderRefundStatus
;
...
...
@@ -91,6 +92,9 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
private
ResourceOrderMapper
resourceOrderMapper
;
@Resource
private
ResourceSpuMapper
resourceSpuMapper
;
@Resource
private
ResourceSkuService
resourceSkuService
;
@Resource
...
...
@@ -292,6 +296,37 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
updateOrder
.
setPayTime
(
LocalDateTime
.
now
());
resourceOrderMapper
.
updateById
(
updateOrder
);
// 4. 累加 SPU 销量(订单首次变为已支付时 +1,重复回调不重复累加)
incrementSpuSalesOnPaid
(
order
);
}
/**
* 订单支付成功时累加其 SPU 销量。
* 仅在订单从 UNPAID 跨到 PENDING_DELIVERY 时调用,重复回调因早期 return 不会进到这里。
* SKU 缺失 / SPU 缺失 / 已软删的 SPU 不会抛错,只记 warn 日志。
*/
private
void
incrementSpuSalesOnPaid
(
ResourceOrderDO
order
)
{
if
(
order
==
null
||
order
.
getSkuId
()
==
null
)
{
return
;
}
try
{
ResourceSkuDO
sku
=
resourceSkuService
.
getResourceSku
(
order
.
getSkuId
());
if
(
sku
==
null
||
sku
.
getSpuId
()
==
null
)
{
log
.
warn
(
"[incrementSpuSalesOnPaid] SKU 或 SPU ID 缺失,订单ID: {}"
,
order
.
getId
());
return
;
}
int
rows
=
resourceSpuMapper
.
incrSalesById
(
sku
.
getSpuId
(),
1
,
"system"
);
if
(
rows
==
0
)
{
log
.
warn
(
"[incrementSpuSalesOnPaid] SPU 不存在或已删除,订单ID: {}, SPU_ID: {}"
,
order
.
getId
(),
sku
.
getSpuId
());
}
else
{
log
.
info
(
"[incrementSpuSalesOnPaid] 订单 {} 支付成功,SPU {} 销量 +1"
,
order
.
getId
(),
sku
.
getSpuId
());
}
}
catch
(
Exception
e
)
{
// 不阻塞主流程,销量同步失败只记日志
log
.
error
(
"[incrementSpuSalesOnPaid] 累加 SPU 销量异常,订单ID: {}"
,
order
.
getId
(),
e
);
}
}
@Override
...
...
@@ -713,6 +748,9 @@ public class ResourceOrderServiceImpl implements ResourceOrderService {
resourceOrderMapper
.
updateById
(
updateResourceOrder
);
payOrderWpgjMapper
.
updateById
(
updatePayOrder
);
// 4.1 累加 SPU 销量(首次支付成功 +1,重复回调不重复累加)
incrementSpuSalesOnPaid
(
order
);
// 触发管理员新订单通知(钉钉群),失败仅记日志,不抛
smsNotifyService
.
notifyAdminsOnPurchase
(
order
);
...
...
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourcespu/ResourceSpuImportServiceImpl.java
View file @
676b953e
...
...
@@ -38,7 +38,7 @@ import static com.luhu.computility.module.compute.enums.ErrorCodeConstants.*;
*
* <p>Excel 模板列结构:
* <ul>
* <li>固定列:商品名称 / 商品分类 /
封面图
/ 商品销量 / 状态</li>
* <li>固定列:商品名称 / 商品分类 /
算力来源 / 商品简介 / 服务器所在地
/ 商品销量 / 状态</li>
* <li>动态列:根据字典 compute_resource_config_category 的 label 动态生成(如 CPU / GPU / RAM / Storage)</li>
* </ul>
*
...
...
@@ -76,8 +76,8 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
private
static
final
String
COL_SOURCE
=
"算力来源"
;
/** 固定列:商品简介 */
private
static
final
String
COL_INTRO
=
"商品简介"
;
/** 固定列:
封面图
*/
private
static
final
String
COL_
PIC_URL
=
"封面图
"
;
/** 固定列:
服务器所在地
*/
private
static
final
String
COL_
LOCATION
=
"服务器所在地
"
;
/** 固定列:商品销量 */
private
static
final
String
COL_SALES
=
"商品销量"
;
/** 固定列:状态 */
...
...
@@ -85,6 +85,8 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
/** 字典类型:算力资源配置类别 */
private
static
final
String
DICT_TYPE_CONFIG_CATEGORY
=
"compute_resource_config_category"
;
/** 字典类型:算力来源 */
private
static
final
String
DICT_TYPE_SOURCE
=
"compute_resource_source"
;
@Override
public
ResourceSpuImportRespVO
importSpuList
(
MultipartFile
file
)
throws
IOException
{
...
...
@@ -150,6 +152,9 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
DictDataRespDTO:
:
getValue
,
(
a
,
b
)
->
a
));
// 3.1 拿算力来源字典(label->value,例如 "合作" -> "cooperative")
List
<
DictDataRespDTO
>
sourceDictList
=
dictDataApi
.
getDictDataList
(
DICT_TYPE_SOURCE
);
// 4. 解析列索引
Map
<
String
,
Integer
>
fixedColIdx
=
new
HashMap
<>();
Map
<
Integer
,
String
>
specColIdxToCategory
=
new
HashMap
<>();
...
...
@@ -164,9 +169,7 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
case
COL_CATEGORY:
case
COL_SOURCE:
case
COL_INTRO:
case
COL_PIC_URL:
case
COL_SALES:
case
COL_STATUS:
case
COL_LOCATION:
fixedColIdx
.
put
(
col
,
i
);
break
;
default
:
...
...
@@ -178,8 +181,7 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
}
// 5. 校验固定列必须存在
if
(!
fixedColIdx
.
containsKey
(
COL_NAME
)
||
!
fixedColIdx
.
containsKey
(
COL_CATEGORY
)
||
!
fixedColIdx
.
containsKey
(
COL_PIC_URL
))
{
if
(!
fixedColIdx
.
containsKey
(
COL_NAME
)
||
!
fixedColIdx
.
containsKey
(
COL_CATEGORY
))
{
throw
exception
(
RESOURCE_SPU_IMPORT_HEADER_INVALID
);
}
...
...
@@ -197,13 +199,22 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
Map
<
String
,
Long
>
categoryNameCache
=
new
HashMap
<>();
// 缓存已查询/已创建的 specConfig(key=configCategory:value, value=configId)
Map
<
String
,
Long
>
specCache
=
new
HashMap
<>();
// 算力来源字典:label -> value(如 "合作" -> "cooperative")
Map
<
String
,
String
>
sourceLabelToValue
=
new
HashMap
<>();
Map
<
String
,
String
>
sourceValueToLabel
=
new
HashMap
<>();
if
(
CollUtil
.
isNotEmpty
(
sourceDictList
))
{
for
(
DictDataRespDTO
d
:
sourceDictList
)
{
sourceLabelToValue
.
put
(
d
.
getLabel
(),
d
.
getValue
());
sourceValueToLabel
.
put
(
d
.
getValue
(),
d
.
getLabel
());
}
}
for
(
int
rowIdx
=
0
;
rowIdx
<
dataRows
.
size
();
rowIdx
++)
{
List
<
String
>
row
=
dataRows
.
get
(
rowIdx
);
int
excelRow
=
rowIdx
+
2
;
// Excel 行号:表头占 1 行,数据行从第 2 行开始
String
rowName
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_NAME
));
try
{
processRow
(
row
,
fixedColIdx
,
specColIdxToCategory
,
nameInBatch
,
categoryValidCache
,
categoryNameCache
,
specCache
,
respVO
);
processRow
(
row
,
fixedColIdx
,
specColIdxToCategory
,
nameInBatch
,
categoryValidCache
,
categoryNameCache
,
s
ourceLabelToValue
,
sourceValueToLabel
,
s
pecCache
,
respVO
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"[importSpuList][第 {} 行导入失败:{}]"
,
excelRow
,
e
.
getMessage
());
respVO
.
getFailureRows
().
add
(
ResourceSpuImportRowVO
.
builder
()
...
...
@@ -226,16 +237,16 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
Set
<
String
>
nameInBatch
,
Map
<
Long
,
Boolean
>
categoryValidCache
,
Map
<
String
,
Long
>
categoryNameCache
,
Map
<
String
,
String
>
sourceLabelToValue
,
Map
<
String
,
String
>
sourceValueToLabel
,
Map
<
String
,
Long
>
specCache
,
ResourceSpuImportRespVO
respVO
)
{
// 1. 解析固定字段
String
name
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_NAME
));
String
categoryIdStr
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_CATEGORY
));
String
source
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_SOURCE
));
String
source
Raw
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_SOURCE
));
String
intro
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_INTRO
));
String
picUrl
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_PIC_URL
));
String
salesStr
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_SALES
));
String
statusStr
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_STATUS
));
String
location
=
getCellValue
(
row
,
fixedColIdx
.
get
(
COL_LOCATION
));
if
(
StrUtil
.
isBlank
(
name
))
{
throw
new
IllegalArgumentException
(
"商品名称不能为空"
);
...
...
@@ -265,9 +276,8 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
throw
exception
(
RESOURCE_SPU_IMPORT_NAME_DUPLICATE
);
}
// 5. 解析可选字段
Integer
sales
=
parseIntOrDefault
(
salesStr
,
0
);
Integer
status
=
parseStatusOrDefault
(
statusStr
,
ResourceSpuStatus
.
ONLINE
.
getValue
());
// 5. 算力来源:按字典 label 转 value(如 "合作" -> "cooperative"),兼容直接填 value
String
source
=
resolveSource
(
sourceRaw
,
sourceLabelToValue
,
sourceValueToLabel
);
// 6. 处理规格列:每列对应 (configCategory, configOption),查/建 spec
List
<
Long
>
specConfigIds
=
new
ArrayList
<>();
...
...
@@ -301,9 +311,10 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
saveReqVO
.
setCategoryId
(
categoryId
);
saveReqVO
.
setSource
(
source
);
saveReqVO
.
setIntro
(
intro
);
saveReqVO
.
setPicUrl
(
picUrl
);
saveReqVO
.
setSales
(
sales
);
saveReqVO
.
setStatus
(
status
);
saveReqVO
.
setLocation
(
location
);
// sales/status 不在模板里,给默认值
saveReqVO
.
setSales
(
0
);
saveReqVO
.
setStatus
(
ResourceSpuStatus
.
ONLINE
.
getValue
());
saveReqVO
.
setSpecConfigIds
(
specConfigIds
);
resourceSpuService
.
createResourceSpu
(
saveReqVO
);
...
...
@@ -348,6 +359,29 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
}
/**
* 解析算力来源:按字典 label 转 value,兼容用户直接填 value 的情况
*/
private
String
resolveSource
(
String
input
,
Map
<
String
,
String
>
sourceLabelToValue
,
Map
<
String
,
String
>
sourceValueToLabel
)
{
if
(
StrUtil
.
isBlank
(
input
))
{
return
null
;
}
String
trimmed
=
input
.
trim
();
// 1. 已经是字典 value(如 "cooperative"),原样返回
if
(
sourceValueToLabel
.
containsKey
(
trimmed
))
{
return
trimmed
;
}
// 2. 是字典 label(如 "合作"),转为 value
String
mapped
=
sourceLabelToValue
.
get
(
trimmed
);
if
(
mapped
!=
null
)
{
return
mapped
;
}
// 3. 字典里查不到,按原值落库(不阻断导入,保留用户输入)
return
trimmed
;
}
/**
* 查/建规格项:先按 (configCategory, configOption) 查 spec 表,不存在则新建
*/
private
Long
getOrCreateSpecId
(
String
configCategory
,
String
configOption
,
...
...
@@ -384,30 +418,4 @@ public class ResourceSpuImportServiceImpl implements ResourceSpuImportService {
return
row
.
get
(
idx
);
}
private
Integer
parseIntOrDefault
(
String
s
,
Integer
defaultVal
)
{
if
(
StrUtil
.
isBlank
(
s
))
{
return
defaultVal
;
}
try
{
return
Integer
.
parseInt
(
s
.
trim
());
}
catch
(
NumberFormatException
e
)
{
return
defaultVal
;
}
}
private
Integer
parseStatusOrDefault
(
String
s
,
Integer
defaultVal
)
{
if
(
StrUtil
.
isBlank
(
s
))
{
return
defaultVal
;
}
String
trimmed
=
s
.
trim
();
// 优先按 label 匹配
for
(
ResourceSpuStatus
st
:
ResourceSpuStatus
.
values
())
{
if
(
st
.
getLabel
().
equals
(
trimmed
))
{
return
st
.
getValue
();
}
}
// 退化为数字
return
parseIntOrDefault
(
trimmed
,
defaultVal
);
}
}
computility-module-compute/computility-module-compute-biz/src/main/java/com/luhu/computility/module/compute/service/resourcespu/ResourceSpuServiceImpl.java
View file @
676b953e
...
...
@@ -55,6 +55,10 @@ public class ResourceSpuServiceImpl implements ResourceSpuService {
if
(
CollUtil
.
isEmpty
(
createReqVO
.
getSpecConfigIds
()))
{
throw
exception
(
RESOURCE_SPU_SPEC_REQUIRED
);
}
// 1.1 销量表单不维护,默认 0(由订单支付回调自动累加)
if
(
createReqVO
.
getSales
()
==
null
)
{
createReqVO
.
setSales
(
0
);
}
// 2. 校验:所有 specConfigIds 在规格字典里存在
validateSpecConfigIdsExist
(
createReqVO
.
getSpecConfigIds
());
...
...
computility-module-compute/computility-module-compute-biz/src/main/resources/mapper/resourcespu/ResourceSpuMapper.xml
View file @
676b953e
...
...
@@ -55,4 +55,18 @@
GROUP BY spu.area_id
</select>
<!--
订单支付成功回调里调用,累加 SPU 销量。
increment: 正数加、负数减(按需扩展,如订单取消时扣减)。
只对未删除的 SPU 生效(避免误加到已软删的 SPU 上)。
-->
<update
id=
"incrSalesById"
>
UPDATE compute_resource_spu
SET sales = sales + #{increment},
updater = #{updater},
update_time = NOW()
WHERE id = #{id}
AND deleted = 0
</update>
</mapper>
sql/migration/2026_08_17_add_config_compute.sql
View file @
676b953e
-- ============================================================
-- 算力资源配置 · 算力字段扩展
-- 目标:为 compute_resource_config 表加 compute 字段
-- 算力资源配置 · 算力字段扩展 + update_time 默认值修复
-- 目标:
-- 1) 修复 compute_resource_config 表 update_time 字段的非法默认值
-- (原: DEFAULT '0000-00-00 00:00:00' 违反 MySQL 8.0 NO_ZERO_DATE)
-- (新: DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)
-- 2) 为 compute_resource_config 表加 compute 字段
-- 适用库:new_computility(线上库名若不同请修改下方 USE 那一行)
-- 前置:无
-- 配套:
...
...
@@ -14,17 +18,60 @@
-- - 默认 0,老数据不破坏
--
-- 生产环境安全说明:
-- - ALTER TABLE ... ADD COLUMN 是 MySQL 5.6+ 的 Online DDL,
-- - ALTER TABLE ... ADD
/MODIFY
COLUMN 是 MySQL 5.6+ 的 Online DDL,
-- 仅修改表元数据,不全表重建;ALGORITHM=INPLACE, LOCK=NONE
-- 期间允许 DML(不阻塞业务),但首尾仍需元数据锁几毫秒
-- - 适用于表数据量 1w 行以内秒级完成;若该表已超 50w 行,
-- 建议低峰期执行(22:00 之后)
-- - 本脚本幂等:
若已存在 compute 字段会跳过并提示
-- - 本脚本幂等:
update_time 已修复会跳过;compute 字段已存在会跳过
-- ============================================================
USE
`new_computility`
;
-- ---------- 幂等性检查 ----------
-- ============================================================
-- 步骤 1:探测 update_time 字段当前定义
-- ============================================================
-- 期望看到 COLUMN_DEFAULT = '0000-00-00 00:00:00' 表示待修复
-- 期望看到 COLUMN_DEFAULT = 'CURRENT_TIMESTAMP' 表示已修复
SELECT
COLUMN_NAME
,
COLUMN_TYPE
,
IS_NULLABLE
,
COLUMN_DEFAULT
,
EXTRA
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
'compute_resource_config'
AND
COLUMN_NAME
=
'update_time'
;
-- ============================================================
-- 步骤 2:修复 update_time 字段默认值(仅当尚未修复时执行)
-- ============================================================
-- 幂等性检查
SET
@
update_time_needs_fix
:
=
(
SELECT
COUNT
(
*
)
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
'compute_resource_config'
AND
COLUMN_NAME
=
'update_time'
AND
COLUMN_DEFAULT
=
'0000-00-00 00:00:00'
);
SET
@
msg
:
=
IF
(
@
update_time_needs_fix
>
0
,
'update_time 默认值为 0000-00-00 00:00:00,开始修复'
,
'update_time 默认值已正确或不存在问题,跳过修复'
);
SELECT
@
msg
AS
info
;
-- 仅在 update_time 默认值是 0000-00-00 时执行 MODIFY
-- 修复后: DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
SET
@
sql_update_time
:
=
IF
(
@
update_time_needs_fix
>
0
,
"ALTER TABLE `compute_resource_config`
MODIFY COLUMN `update_time` DATETIME NOT NULL
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
COMMENT '更新时间'"
,
"SELECT 'update_time 已修复,跳过' AS done"
);
PREPARE
stmt
FROM
@
sql_update_time
;
EXECUTE
stmt
;
DEALLOCATE
PREPARE
stmt
;
-- ============================================================
-- 步骤 3:探测 compute 字段是否已存在
-- ============================================================
SET
@
col_exists
:
=
(
SELECT
COUNT
(
*
)
FROM
INFORMATION_SCHEMA
.
COLUMNS
...
...
@@ -33,26 +80,44 @@ SET @col_exists := (
AND
COLUMN_NAME
=
'compute'
);
SET
@
msg
:
=
IF
(
@
col_exists
>
0
,
SET
@
msg
2
:
=
IF
(
@
col_exists
>
0
,
'compute 字段已存在,跳过本次新增'
,
'compute 字段不存在,开始执行新增'
);
SELECT
@
msg
AS
info
;
SELECT
@
msg
2
AS
info
;
-- ---------- 新增字段 ----------
-- ============================================================
-- 步骤 4:新增 compute 字段(仅当字段不存在时执行)
-- ============================================================
-- 使用 Online DDL:INPLACE 算法不重建表,NONE 锁允许并发 DML
ALTER
TABLE
`compute_resource_config`
SET
@
sql_add_compute
:
=
IF
(
@
col_exists
=
0
,
"ALTER TABLE `compute_resource_config`
ADD COLUMN `compute` DECIMAL(18,2) NOT NULL DEFAULT 0
COMMENT '算力值(TOPS),默认 0,由运营手动配置' AFTER `detail_remark`,
ALGORITHM
=
INPLACE
,
LOCK
=
NONE
;
ALGORITHM=INPLACE, LOCK=NONE"
,
"SELECT 'compute 字段已存在,跳过' AS done"
);
PREPARE
stmt
FROM
@
sql_add_compute
;
EXECUTE
stmt
;
DEALLOCATE
PREPARE
stmt
;
-- ---------- 验证 ----------
-- SHOW COLUMNS FROM `compute_resource_config` LIKE 'compute';
-- 期望结果:
-- compute | decimal(18,2) | NO | | 0.00 | 算力值(TOPS),默认 0,由运营手动配置
-- ============================================================
-- 步骤 5:验证
-- ============================================================
-- 期望结果 1:update_time 默认值 = CURRENT_TIMESTAMP
-- 期望结果 2:compute 字段存在,默认 0
SHOW
COLUMNS
FROM
`compute_resource_config`
LIKE
'update_time'
;
SHOW
COLUMNS
FROM
`compute_resource_config`
LIKE
'compute'
;
-- ============================================================
-- 回滚脚本(仅在确认要回滚时手动执行,默认不执行)
-- ============================================================
-- -- 1. 删除 compute 字段
-- ALTER TABLE `compute_resource_config`
-- DROP COLUMN `compute`,
-- ALGORITHM=INPLACE, LOCK=NONE;
--
-- -- 2. 还原 update_time 默认值(注意:这会把 update_time 默认值改回 0000-00-00,
-- -- 下次 ALTER TABLE 可能还会报错,但这是回滚到原始状态)
-- ALTER TABLE `compute_resource_config`
-- MODIFY COLUMN `update_time` DATETIME NOT NULL
-- DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP
-- COMMENT '更新时间';
sql/migration/2026_08_18_verify_api_calls_trend_v2.sql
deleted
100644 → 0
View file @
f2e21d79
-- ============================================================
-- 验证大屏"API 请求趋势"图表数据准确性(v2 - 修正表名)
-- 库:new_computility
-- 文件:2026_08_18_verify_api_calls_trend_v2.sql
-- 修正:原 v1 误用 infra_api_access_log,实际是 apihub_api_call_log
--
-- 【业务语义】
-- "API 请求趋势" = API 服务市场应用被用户调用的次数
-- 数据源表:apihub_api_call_log(项目自有的 apihub 模块)
-- 过滤字段:create_time(HomeIndexServiceImpl:213 setCreateTime)
-- 注意:表里还有 call_time 字段,但 service 实际按 create_time 过滤
--
-- 【与后端 service 对齐】
-- HomeIndexServiceImpl.getApiCallsData(dateType)
-- ├─ d (日): 近 7 天,截止到昨天
-- ├─ m (月): 近 30 天,截止到昨天
-- └─ y (年): 近 12 个月,截止到上月末
-- endTime = yesterday.atTime(23, 59, 59, 999_999_999)
-- ============================================================
USE
`new_computility`
;
-- ============================================================
-- 0) 今日日期确认 + 表数据健康检查
-- ============================================================
SELECT
CURDATE
()
AS
today
,
DATE_SUB
(
CURDATE
(),
INTERVAL
1
DAY
)
AS
yesterday
;
SELECT
COUNT
(
*
)
AS
total_cnt
,
MIN
(
create_time
)
AS
min_ct
,
MAX
(
create_time
)
AS
max_ct
FROM
apihub_api_call_log
;
-- 如果 total_cnt = 0,说明 API 服务市场还没人调用过,图表必然为 0
-- 如果 max_ct 早于昨天,说明可能没新调用
-- ============================================================
-- 1) d(日)维度验证:近 7 天,截止到昨天
-- 假设今天是 2026-08-18 → 窗口 2026-08-11 ~ 2026-08-17
-- ============================================================
SELECT
DATE
(
create_time
)
AS
day
,
COUNT
(
*
)
AS
cnt
FROM
apihub_api_call_log
WHERE
create_time
>=
DATE_SUB
(
CURDATE
(),
INTERVAL
7
DAY
)
AND
create_time
<
CURDATE
()
AND
create_time
>=
'1970-01-01'
GROUP
BY
DATE
(
create_time
)
ORDER
BY
day
;
-- 期望 7 行,每行 day + cnt 对应图表日维度的 x + y
-- ============================================================
-- 2) m(月)维度验证:近 30 天,截止到昨天
-- 假设今天是 2026-08-18 → 窗口 2026-07-19 ~ 2026-08-17
-- ============================================================
SELECT
DATE
(
create_time
)
AS
day
,
COUNT
(
*
)
AS
cnt
FROM
apihub_api_call_log
WHERE
create_time
>=
DATE_SUB
(
CURDATE
(),
INTERVAL
30
DAY
)
AND
create_time
<
CURDATE
()
AND
create_time
>=
'1970-01-01'
GROUP
BY
DATE
(
create_time
)
ORDER
BY
day
;
-- 期望 30 行,对应图表月维度的 x + y
-- ============================================================
-- 3) y(年)维度验证:近 12 个月,截止到上月末
-- 假设今天是 2026-08-18 → 上月末 2026-07-31
-- 时间窗口 2025-08-01 00:00:00 ~ 2026-07-31 23:59:59.999999
-- ============================================================
SELECT
DATE_FORMAT
(
create_time
,
'%Y-%m'
)
AS
month
,
COUNT
(
*
)
AS
cnt
FROM
apihub_api_call_log
WHERE
create_time
>=
DATE_FORMAT
(
DATE_SUB
(
CURDATE
(),
INTERVAL
12
MONTH
),
'%Y-%m-01'
)
AND
create_time
<
DATE_FORMAT
(
CURDATE
(),
'%Y-%m-01'
)
AND
create_time
>=
'1970-01-01'
GROUP
BY
DATE_FORMAT
(
create_time
,
'%Y-%m'
)
ORDER
BY
month
;
-- 期望 12 行(每个月末一天),对应图表年维度的 x + y
-- 注意:图表 x 显示 "yyyy-MM" 格式(如 "2025-08"),不是月末日期
-- ============================================================
-- 4) 总数校验
-- ============================================================
SELECT
CURDATE
()
AS
today
,
(
SELECT
COUNT
(
*
)
FROM
apihub_api_call_log
WHERE
create_time
>=
DATE_SUB
(
CURDATE
(),
INTERVAL
7
DAY
))
AS
cnt_7d
,
(
SELECT
COUNT
(
*
)
FROM
apihub_api_call_log
WHERE
create_time
>=
DATE_SUB
(
CURDATE
(),
INTERVAL
30
DAY
))
AS
cnt_30d
,
(
SELECT
COUNT
(
*
)
FROM
apihub_api_call_log
)
AS
cnt_total
;
-- cnt_7d 应等于 d 维度 7 行 cnt 之和
-- cnt_30d 应等于 m 维度 30 行 cnt 之和
-- cnt_total 是整张表总数
-- ============================================================
-- 5) 抽样验证:看最近 10 条记录
-- ============================================================
SELECT
id
,
user_id
,
api_endpoint_name
,
call_time
,
response_status
,
create_time
FROM
apihub_api_call_log
ORDER
BY
create_time
DESC
LIMIT
10
;
-- 用来:
-- (a) 确认有真实数据流入
-- (b) 看 create_time 与 call_time 是否一致(绝大多数应一致,差几毫秒)
-- (c) 看 response_status 分布(0=成功,其他=异常)
-- ============================================================
-- 6) 按用户/接口维度统计(辅助排查"为什么是这个数字")
-- ============================================================
SELECT
api_endpoint_name
,
COUNT
(
*
)
AS
cnt
FROM
apihub_api_call_log
WHERE
create_time
>=
DATE_SUB
(
CURDATE
(),
INTERVAL
7
DAY
)
AND
create_time
<
CURDATE
()
GROUP
BY
api_endpoint_name
ORDER
BY
cnt
DESC
LIMIT
20
;
-- 用来确认是哪些 API 贡献了大部分调用量
-- 也帮助理解图表上某个高点为什么突增
sql/migration/2026_08_19_fix_missing_order_fields.sql
0 → 100644
View file @
676b953e
-- 算力资源订单 - 补齐线上缺失字段(紧急修复)
-- 库:new_computility
-- 背景:本地已加 2026_08_11 阶段 A/D 字段,线上漏执行,触发 getAllDashboardData 报 500
-- 本脚本:幂等版本(INFORMATION_SCHEMA.COLUMNS 探测,缺则加,不缺则跳过)
--
-- 涉及字段(基于错误堆栈 + 已知迁移文件):
-- - 阶段 A(商家发货):delivery_ip, delivery_username, delivery_password,
-- delivered_time, deliver_operator_id, deliver_operator_name
-- - 阶段 D(人工退款):refund_time
USE
`new_computility`
;
-- =====================================================
-- 工具:检查并 ADD COLUMN(缺则加,不缺则跳过)
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
add_column_if_missing
;
DELIMITER
//
CREATE
PROCEDURE
add_column_if_missing
(
IN
p_table
VARCHAR
(
64
),
IN
p_column
VARCHAR
(
64
),
IN
p_definition
TEXT
)
BEGIN
DECLARE
v_exists
INT
DEFAULT
0
;
SELECT
COUNT
(
*
)
INTO
v_exists
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
p_table
AND
COLUMN_NAME
=
p_column
;
IF
v_exists
=
0
THEN
SET
@
sql
=
CONCAT
(
'ALTER TABLE `'
,
p_table
,
'` ADD COLUMN `'
,
p_column
,
'` '
,
p_definition
);
PREPARE
stmt
FROM
@
sql
;
EXECUTE
stmt
;
DEALLOCATE
PREPARE
stmt
;
SELECT
CONCAT
(
'[ADD] '
,
p_table
,
'.'
,
p_column
)
AS
action
;
ELSE
SELECT
CONCAT
(
'[SKIP] '
,
p_table
,
'.'
,
p_column
,
' 已存在'
)
AS
action
;
END
IF
;
END
//
DELIMITER
;
-- =====================================================
-- 1. compute_resource_order 补齐字段
-- =====================================================
-- 1.1 阶段 A 发货字段
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivery_ip'
,
"VARCHAR(64) DEFAULT NULL COMMENT '发货 IP(商家发货时填写)' AFTER `pay_channel_code`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivery_username'
,
"VARCHAR(64) DEFAULT NULL COMMENT '发货初始用户名' AFTER `delivery_ip`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivery_password'
,
"VARCHAR(128) DEFAULT NULL COMMENT '发货初始密码' AFTER `delivery_username`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivered_time'
,
"DATETIME DEFAULT NULL COMMENT '发货时间(也是租赁开始时间)' AFTER `delivery_password`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'deliver_operator_id'
,
"BIGINT DEFAULT NULL COMMENT '发货操作人 ID' AFTER `delivered_time`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'deliver_operator_name'
,
"VARCHAR(64) DEFAULT NULL COMMENT '发货操作人姓名(冗余)' AFTER `deliver_operator_id`"
);
-- 1.2 阶段 D 退款时间
CALL
add_column_if_missing
(
'compute_resource_order'
,
'refund_time'
,
"DATETIME DEFAULT NULL COMMENT '退款时间(客服标已退款时填写)' AFTER `refund_price`"
);
-- =====================================================
-- 清理
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
add_column_if_missing
;
-- =====================================================
-- 验证
-- =====================================================
SELECT
COLUMN_NAME
,
COLUMN_TYPE
,
COLUMN_DEFAULT
,
IS_NULLABLE
,
COLUMN_COMMENT
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
'compute_resource_order'
AND
COLUMN_NAME
IN
(
'delivery_ip'
,
'delivery_username'
,
'delivery_password'
,
'delivered_time'
,
'deliver_operator_id'
,
'deliver_operator_name'
,
'refund_time'
)
ORDER
BY
ORDINAL_POSITION
;
-- =====================================================
-- 回滚脚本(如需)
-- =====================================================
-- ALTER TABLE `compute_resource_order`
-- DROP COLUMN `delivery_ip`,
-- DROP COLUMN `delivery_username`,
-- DROP COLUMN `delivery_password`,
-- DROP COLUMN `delivered_time`,
-- DROP COLUMN `deliver_operator_id`,
-- DROP COLUMN `deliver_operator_name`,
-- DROP COLUMN `refund_time`;
sql/migration/2026_08_19_fix_order_update_time_and_missing_fields.sql
0 → 100644
View file @
676b953e
-- 算力资源订单 - update_time 修复 + 补齐缺失字段(紧急修复)
-- 库:new_computility
-- 背景:
-- 1. 线上 compute_resource_order.update_time 默认值是 '0000-00-00 00:00:00',
-- 违反 MySQL 8.0 严格模式 NO_ZERO_DATE,导致任何 ALTER TABLE 失败
-- 2. 修复 update_time DEFAULT 为 CURRENT_TIMESTAMP 后,再 ADD COLUMN 补齐缺失字段
-- 3. 字段来源:2026_08_11_resource_order_delivery_fields.sql(阶段 A)
-- + 2026_08_11_resource_order_refund_time.sql(阶段 D)
--
-- 脚本:纯存储过程版本,幂等,可重复执行
USE
`new_computility`
;
-- =====================================================
-- 存储过程 1:修复 update_time 字段默认值
-- 仅当 DEFAULT 为 '0000-00-00 00:00:00' 时才 MODIFY
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
fix_update_time_default
;
DELIMITER
//
CREATE
PROCEDURE
fix_update_time_default
(
IN
p_table
VARCHAR
(
64
)
)
BEGIN
DECLARE
v_default
VARCHAR
(
64
)
DEFAULT
NULL
;
SELECT
COLUMN_DEFAULT
INTO
v_default
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
p_table
AND
COLUMN_NAME
=
'update_time'
;
IF
v_default
=
'0000-00-00 00:00:00'
THEN
SET
@
sql
=
CONCAT
(
'ALTER TABLE `'
,
p_table
,
'` '
,
'MODIFY COLUMN `update_time` DATETIME NOT NULL '
,
'DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP '
,
'COMMENT
''
更新时间
''
'
);
PREPARE
stmt
FROM
@
sql
;
EXECUTE
stmt
;
DEALLOCATE
PREPARE
stmt
;
SELECT
CONCAT
(
'[FIX] '
,
p_table
,
'.update_time DEFAULT updated to CURRENT_TIMESTAMP'
)
AS
action
;
ELSE
SELECT
CONCAT
(
'[SKIP] '
,
p_table
,
'.update_time DEFAULT is OK ('
,
IFNULL
(
v_default
,
'NULL'
),
')'
)
AS
action
;
END
IF
;
END
//
DELIMITER
;
-- =====================================================
-- 存储过程 2:检查并 ADD COLUMN(缺则加,不缺则跳过)
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
add_column_if_missing
;
DELIMITER
//
CREATE
PROCEDURE
add_column_if_missing
(
IN
p_table
VARCHAR
(
64
),
IN
p_column
VARCHAR
(
64
),
IN
p_definition
TEXT
)
BEGIN
DECLARE
v_exists
INT
DEFAULT
0
;
SELECT
COUNT
(
*
)
INTO
v_exists
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
p_table
AND
COLUMN_NAME
=
p_column
;
IF
v_exists
=
0
THEN
SET
@
sql
=
CONCAT
(
'ALTER TABLE `'
,
p_table
,
'` ADD COLUMN `'
,
p_column
,
'` '
,
p_definition
);
PREPARE
stmt
FROM
@
sql
;
EXECUTE
stmt
;
DEALLOCATE
PREPARE
stmt
;
SELECT
CONCAT
(
'[ADD] '
,
p_table
,
'.'
,
p_column
)
AS
action
;
ELSE
SELECT
CONCAT
(
'[SKIP] '
,
p_table
,
'.'
,
p_column
,
' 已存在'
)
AS
action
;
END
IF
;
END
//
DELIMITER
;
-- =====================================================
-- 步骤 1:先修 update_time 字段
-- =====================================================
CALL
fix_update_time_default
(
'compute_resource_order'
);
-- =====================================================
-- 步骤 2:补齐缺失字段
-- =====================================================
-- 2.1 阶段 A 发货字段
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivery_ip'
,
"VARCHAR(64) DEFAULT NULL COMMENT '发货 IP(商家发货时填写)' AFTER `pay_channel_code`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivery_username'
,
"VARCHAR(64) DEFAULT NULL COMMENT '发货初始用户名' AFTER `delivery_ip`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivery_password'
,
"VARCHAR(128) DEFAULT NULL COMMENT '发货初始密码' AFTER `delivery_username`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'delivered_time'
,
"DATETIME DEFAULT NULL COMMENT '发货时间(也是租赁开始时间)' AFTER `delivery_password`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'deliver_operator_id'
,
"BIGINT DEFAULT NULL COMMENT '发货操作人 ID' AFTER `delivered_time`"
);
CALL
add_column_if_missing
(
'compute_resource_order'
,
'deliver_operator_name'
,
"VARCHAR(64) DEFAULT NULL COMMENT '发货操作人姓名(冗余)' AFTER `deliver_operator_id`"
);
-- 2.2 阶段 D 退款时间
CALL
add_column_if_missing
(
'compute_resource_order'
,
'refund_time'
,
"DATETIME DEFAULT NULL COMMENT '退款时间(客服标已退款时填写)' AFTER `refund_price`"
);
-- =====================================================
-- 清理存储过程
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
fix_update_time_default
;
DROP
PROCEDURE
IF
EXISTS
add_column_if_missing
;
-- =====================================================
-- 验证
-- =====================================================
SELECT
COLUMN_NAME
,
COLUMN_TYPE
,
COLUMN_DEFAULT
,
IS_NULLABLE
,
COLUMN_COMMENT
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
'compute_resource_order'
AND
COLUMN_NAME
IN
(
'update_time'
,
'delivery_ip'
,
'delivery_username'
,
'delivery_password'
,
'delivered_time'
,
'deliver_operator_id'
,
'deliver_operator_name'
,
'refund_time'
)
ORDER
BY
ORDINAL_POSITION
;
-- =====================================================
-- 回滚脚本(如需)
-- =====================================================
-- ALTER TABLE `compute_resource_order`
-- DROP COLUMN `delivery_ip`,
-- DROP COLUMN `delivery_username`,
-- DROP COLUMN `delivery_password`,
-- DROP COLUMN `delivered_time`,
-- DROP COLUMN `deliver_operator_id`,
-- DROP COLUMN `deliver_operator_name`,
-- DROP COLUMN `refund_time`;
-- ALTER TABLE `compute_resource_order`
-- MODIFY COLUMN `update_time` DATETIME NOT NULL
-- DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP
-- COMMENT '更新时间';
sql/migration/2026_08_19_fix_snapshot_rename_columns.sql
0 → 100644
View file @
676b953e
-- 算力资源订单快照表 - 字段重命名 + 补齐 delivered_time
-- 库:new_computility
-- 背景:本地 DO 字段名已重命名(ip→delivery_ip, init_username→delivery_username,
-- init_password→delivery_password, +新增 delivered_time),但线上没执行迁移
-- 脚本:幂等版本(INFORMATION_SCHEMA 探测)
-- 安全:使用 RENAME COLUMN(MySQL 8.0+),不丢数据;如已为新字段名则跳过
USE
`new_computility`
;
-- =====================================================
-- 存储过程:智能重命名列(老列存在则 RENAME,新列已存在则 SKIP)
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
rename_column_if_exists
;
DELIMITER
//
CREATE
PROCEDURE
rename_column_if_exists
(
IN
p_table
VARCHAR
(
64
),
IN
p_old_column
VARCHAR
(
64
),
IN
p_new_column
VARCHAR
(
64
)
)
BEGIN
DECLARE
v_old_exists
INT
DEFAULT
0
;
DECLARE
v_new_exists
INT
DEFAULT
0
;
SELECT
COUNT
(
*
)
INTO
v_old_exists
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
p_table
AND
COLUMN_NAME
=
p_old_column
;
SELECT
COUNT
(
*
)
INTO
v_new_exists
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
p_table
AND
COLUMN_NAME
=
p_new_column
;
IF
v_old_exists
=
1
AND
v_new_exists
=
0
THEN
SET
@
sql
=
CONCAT
(
'ALTER TABLE `'
,
p_table
,
'` '
,
'RENAME COLUMN `'
,
p_old_column
,
'` TO `'
,
p_new_column
,
'`'
);
PREPARE
stmt
FROM
@
sql
;
EXECUTE
stmt
;
DEALLOCATE
PREPARE
stmt
;
SELECT
CONCAT
(
'[RENAME] '
,
p_table
,
'.'
,
p_old_column
,
' → '
,
p_new_column
)
AS
action
;
ELSEIF
v_new_exists
=
1
THEN
SELECT
CONCAT
(
'[SKIP] '
,
p_table
,
'.'
,
p_new_column
,
' 已存在(可能已重命名或新增)'
)
AS
action
;
ELSE
SELECT
CONCAT
(
'[WARN] '
,
p_table
,
' 缺少老列 '
,
p_old_column
,
',也无法找到新列 '
,
p_new_column
)
AS
action
;
END
IF
;
END
//
DELIMITER
;
-- =====================================================
-- 存储过程:检查并 ADD COLUMN(缺则加,不缺则跳过)
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
add_column_if_missing
;
DELIMITER
//
CREATE
PROCEDURE
add_column_if_missing
(
IN
p_table
VARCHAR
(
64
),
IN
p_column
VARCHAR
(
64
),
IN
p_definition
TEXT
)
BEGIN
DECLARE
v_exists
INT
DEFAULT
0
;
SELECT
COUNT
(
*
)
INTO
v_exists
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
p_table
AND
COLUMN_NAME
=
p_column
;
IF
v_exists
=
0
THEN
SET
@
sql
=
CONCAT
(
'ALTER TABLE `'
,
p_table
,
'` ADD COLUMN `'
,
p_column
,
'` '
,
p_definition
);
PREPARE
stmt
FROM
@
sql
;
EXECUTE
stmt
;
DEALLOCATE
PREPARE
stmt
;
SELECT
CONCAT
(
'[ADD] '
,
p_table
,
'.'
,
p_column
)
AS
action
;
ELSE
SELECT
CONCAT
(
'[SKIP] '
,
p_table
,
'.'
,
p_column
,
' 已存在'
)
AS
action
;
END
IF
;
END
//
DELIMITER
;
-- =====================================================
-- 执行修复
-- =====================================================
-- 1. 重命名老字段 → 新字段名
CALL
rename_column_if_exists
(
'compute_resource_order_snapshot'
,
'ip'
,
'delivery_ip'
);
CALL
rename_column_if_exists
(
'compute_resource_order_snapshot'
,
'init_username'
,
'delivery_username'
);
CALL
rename_column_if_exists
(
'compute_resource_order_snapshot'
,
'init_password'
,
'delivery_password'
);
-- 2. 新增 delivered_time
CALL
add_column_if_missing
(
'compute_resource_order_snapshot'
,
'delivered_time'
,
"DATETIME DEFAULT NULL COMMENT '发货时间(快照)' AFTER `delivery_password`"
);
-- =====================================================
-- 清理
-- =====================================================
DROP
PROCEDURE
IF
EXISTS
rename_column_if_exists
;
DROP
PROCEDURE
IF
EXISTS
add_column_if_missing
;
-- =====================================================
-- 验证
-- =====================================================
SELECT
COLUMN_NAME
,
COLUMN_TYPE
,
IS_NULLABLE
,
COLUMN_COMMENT
FROM
INFORMATION_SCHEMA
.
COLUMNS
WHERE
TABLE_SCHEMA
=
DATABASE
()
AND
TABLE_NAME
=
'compute_resource_order_snapshot'
AND
COLUMN_NAME
IN
(
'delivery_ip'
,
'delivery_username'
,
'delivery_password'
,
'delivered_time'
,
'ip'
,
'init_username'
,
'init_password'
-- 检查老列是否还有残留
)
ORDER
BY
ORDINAL_POSITION
;
-- =====================================================
-- 回滚脚本(如需)
-- =====================================================
-- ALTER TABLE `compute_resource_order_snapshot`
-- RENAME COLUMN `delivery_ip` TO `ip`,
-- RENAME COLUMN `delivery_username` TO `init_username`,
-- RENAME COLUMN `delivery_password` TO `init_password`,
-- DROP COLUMN `delivered_time`;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment