fix: 修复 Doris 数据库建表语法兼容性问题

核心问题:数据库为 Apache Doris 而非标准 MySQL,建表语法完全不同

关键修改:
1. 去除所有 MySQL 特有语法(ENGINE、DEFAULT、IF NOT EXISTS)
2. 使用 Doris 必需语法:DISTRIBUTED BY HASH + PROPERTIES
3. 所有 NULL/NOT NULL 和 DEFAULT 值重新适配
4. 修复四个文件的建表语句:
   - config/route.ts(配置表)
   - report/history/route.ts(历史表)
   - report-generator.ts(生成器)
   - init-tables.ts(初始化脚本)

测试结果:
 配置创建 API 测试通过(HTTP 200)
 所有静态检查通过
 Doris 建表语法完全兼容

Coze-Commit-Type: user
Coze-User-ID: 3722323274763196
Coze-Conversation-ID: 9894087
This commit is contained in:
user9994793890
2026-07-07 17:13:14 +08:00
parent 05b031bb40
commit 26f0ed12f1
5 changed files with 140 additions and 33 deletions

BIN
assets/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@@ -69,18 +69,53 @@ export async function POST(request: NextRequest) {
// 获取连接
const connection = await pool.getConnection();
// 尝试创建表(如果已存在会失败,但不影响后续操作)
try {
await connection.query(`
CREATE TABLE t_daily_report_config (
id BIGINT NOT NULL COMMENT '配置ID',
config_name VARCHAR(100) NOT NULL COMMENT '配置名称',
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式',
split_value VARCHAR(100) NOT NULL COMMENT '拆分值',
split_name VARCHAR(200) NULL COMMENT '拆分显示名称',
selected_fields VARCHAR(3000) NOT NULL COMMENT '选择的字段列表',
sum_fields VARCHAR(3000) NULL COMMENT '求和字段列表',
create_time DATETIME NULL COMMENT '创建时间',
update_time DATETIME NULL COMMENT '更新时间',
is_active TINYINT NULL COMMENT '是否启用'
)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES("replication_num" = "1")
`);
console.log('配置表创建成功');
} catch (tableError: any) {
// 如果表已存在,忽略错误
if (tableError.message && tableError.message.includes('already exists')) {
console.log('配置表已存在');
} else {
console.error('创建表失败:', tableError);
}
}
// 生成ID使用时间戳
const id = Date.now();
const now = new Date();
// 插入配置
await connection.query(
`INSERT INTO t_daily_report_config
(config_name, split_type, split_value, split_name, selected_fields, sum_fields)
VALUES (?, ?, ?, ?, ?, ?)`,
(id, config_name, split_type, split_value, split_name, selected_fields, sum_fields, create_time, update_time, is_active)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)`,
[
id,
config_name,
split_type,
split_value,
split_name || null,
JSON.stringify(selected_fields),
sum_fields ? JSON.stringify(sum_fields) : null
sum_fields ? JSON.stringify(sum_fields) : null,
now,
now
]
);

View File

@@ -10,6 +10,39 @@ export async function GET(request: NextRequest) {
const splitType = searchParams.get('splitType');
const reportDate = searchParams.get('reportDate');
// 获取连接并确保表存在
const connection = await pool.getConnection();
try {
await connection.query(`
CREATE TABLE t_daily_report_history (
id BIGINT NOT NULL COMMENT '记录ID',
report_date DATE NOT NULL COMMENT '报表日期',
start_time DATETIME NOT NULL COMMENT '报表开始时间',
end_time DATETIME NOT NULL COMMENT '报表结束时间',
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式',
split_value VARCHAR(100) NOT NULL COMMENT '拆分值',
split_name VARCHAR(200) NULL COMMENT '拆分显示名称',
config_id BIGINT NULL COMMENT '使用的配置ID',
total_orders INT NULL COMMENT '订单总数',
total_amount DECIMALV3 NULL COMMENT '总金额',
sum_results VARCHAR(3000) NULL COMMENT '求和结果',
file_path VARCHAR(500) NULL COMMENT '生成的文件路径',
create_time DATETIME NULL COMMENT '生成时间',
status TINYINT NULL COMMENT '状态'
)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES("replication_num" = "1")
`);
console.log('历史表创建成功');
} catch (tableError: any) {
if (tableError.message && tableError.message.includes('already exists')) {
console.log('历史表已存在');
} else {
console.error('创建历史表失败:', tableError);
}
}
connection.release();
// 构建查询条件
let whereClause = 'WHERE 1=1';
const queryParams: any[] = [];

View File

@@ -1,38 +1,40 @@
import pool from './db';
// 创建配置表和历史表的SQL语句
// 创建配置表和历史表的SQL语句Doris兼容
const createTablesSQL = `
-- 日报配置表(用户字段选择配置)
CREATE TABLE IF NOT EXISTS t_daily_report_config (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '配置ID',
CREATE TABLE t_daily_report_config (
id BIGINT NOT NULL COMMENT '配置ID',
config_name VARCHAR(100) NOT NULL COMMENT '配置名称',
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式company_id 或 user_id',
split_value VARCHAR(100) NOT NULL COMMENT '拆分值企业ID或用户ID',
split_name VARCHAR(200) COMMENT '拆分显示名称(企业名称或用户姓名)',
selected_fields JSON NOT NULL COMMENT '用户选择的字段列表JSON数组',
sum_fields JSON COMMENT '需要求和的字段列表JSON数组',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
is_active TINYINT DEFAULT 1 COMMENT '是否启用0禁用 1启用'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日报字段配置表';
split_name VARCHAR(200) NULL COMMENT '拆分显示名称(企业名称或用户姓名)',
selected_fields VARCHAR(3000) NOT NULL COMMENT '用户选择的字段列表JSON字符串',
sum_fields VARCHAR(3000) NULL COMMENT '需要求和的字段列表JSON字符串',
create_time DATETIME NULL COMMENT '创建时间',
update_time DATETIME NULL COMMENT '更新时间',
is_active TINYINT NULL COMMENT '是否启用0禁用 1启用'
)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES("replication_num" = "1");
-- 日报生成历史记录表
CREATE TABLE IF NOT EXISTS t_daily_report_history (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '记录ID',
CREATE TABLE t_daily_report_history (
id BIGINT NOT NULL COMMENT '记录ID',
report_date DATE NOT NULL COMMENT '报表日期',
start_time DATETIME NOT NULL COMMENT '报表开始时间',
end_time DATETIME NOT NULL COMMENT '报表结束时间',
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式company_id 或 user_id',
split_value VARCHAR(100) NOT NULL COMMENT '拆分值企业ID或用户ID',
split_name VARCHAR(200) COMMENT '拆分显示名称',
config_id BIGINT COMMENT '使用的配置ID',
total_orders INT DEFAULT 0 COMMENT '订单总数',
total_amount DECIMAL(15,2) DEFAULT 0 COMMENT '总金额',
sum_results JSON COMMENT '求和结果JSON对象',
file_path VARCHAR(500) COMMENT '生成的文件路径',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '生成时间',
status TINYINT DEFAULT 1 COMMENT '状态0失败 1成功'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日报生成历史表';
split_name VARCHAR(200) NULL COMMENT '拆分显示名称',
config_id BIGINT NULL COMMENT '使用的配置ID',
total_orders INT NULL COMMENT '订单总数',
total_amount DECIMALV3 NULL COMMENT '总金额',
sum_results VARCHAR(3000) NULL COMMENT '求和结果JSON字符串',
file_path VARCHAR(500) NULL COMMENT '生成的文件路径',
create_time DATETIME NULL COMMENT '生成时间',
status TINYINT NULL COMMENT '状态0失败 1成功'
)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES("replication_num" = "1");
`;
// 初始化数据库表
@@ -49,10 +51,10 @@ export async function initDatabaseTables(): Promise<void> {
}
connection.release();
console.log('数据库表初始化成功');
console.log('数据库表初始化成功Doris兼容语法');
console.log('创建了以下表:');
console.log('1. t_daily_report_config - 日报字段配置表(包含拆分值和显示名称)');
console.log('2. t_daily_report_history - 日报生成历史表(包含求和结果)');
console.log('1. t_daily_report_config - 日报字段配置表');
console.log('2. t_daily_report_history - 日报生成历史表');
} catch (error) {
console.error('数据库表初始化失败:', error);
throw error;

View File

@@ -224,12 +224,47 @@ export async function generateBatchReports(configId: number): Promise<ReportResu
// 保存到历史记录表
const connection2 = await pool.getConnection();
// 确保历史表存在
try {
await connection2.query(`
CREATE TABLE t_daily_report_history (
id BIGINT NOT NULL COMMENT '记录ID',
report_date DATE NOT NULL COMMENT '报表日期',
start_time DATETIME NOT NULL COMMENT '报表开始时间',
end_time DATETIME NOT NULL COMMENT '报表结束时间',
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式',
split_value VARCHAR(100) NOT NULL COMMENT '拆分值',
split_name VARCHAR(200) NULL COMMENT '拆分显示名称',
config_id BIGINT NULL COMMENT '使用的配置ID',
total_orders INT NULL COMMENT '订单总数',
total_amount DECIMALV3 NULL COMMENT '总金额',
sum_results VARCHAR(3000) NULL COMMENT '求和结果',
file_path VARCHAR(500) NULL COMMENT '生成的文件路径',
create_time DATETIME NULL COMMENT '生成时间',
status TINYINT NULL COMMENT '状态'
)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES("replication_num" = "1")
`);
console.log('历史表创建成功');
} catch (tableError: any) {
if (tableError.message && tableError.message.includes('already exists')) {
console.log('历史表已存在');
} else {
console.error('创建历史表失败:', tableError);
}
}
const historyId = Date.now();
const now = new Date();
if (result.success) {
await connection2.query(
`INSERT INTO t_daily_report_history
(report_date, start_time, end_time, split_type, split_value, split_name, config_id, total_orders, total_amount, sum_results, file_path, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
(id, report_date, start_time, end_time, split_type, split_value, split_name, config_id, total_orders, total_amount, sum_results, file_path, create_time, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
historyId,
result.reportDate,
result.startTime,
result.endTime,
@@ -241,15 +276,17 @@ export async function generateBatchReports(configId: number): Promise<ReportResu
result.totalAmount,
result.sumResults ? JSON.stringify(result.sumResults) : null,
result.filePath || null,
now,
1
]
);
} else {
await connection2.query(
`INSERT INTO t_daily_report_history
(report_date, start_time, end_time, split_type, split_value, split_name, config_id, total_orders, total_amount, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
(id, report_date, start_time, end_time, split_type, split_value, split_name, config_id, total_orders, total_amount, create_time, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
historyId,
result.reportDate,
result.startTime,
result.endTime,