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:
BIN
assets/image.png
Normal file
BIN
assets/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
@@ -69,18 +69,53 @@ export async function POST(request: NextRequest) {
|
|||||||
// 获取连接
|
// 获取连接
|
||||||
const connection = await pool.getConnection();
|
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(
|
await connection.query(
|
||||||
`INSERT INTO t_daily_report_config
|
`INSERT INTO t_daily_report_config
|
||||||
(config_name, split_type, split_value, split_name, selected_fields, sum_fields)
|
(id, config_name, split_type, split_value, split_name, selected_fields, sum_fields, create_time, update_time, is_active)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)`,
|
||||||
[
|
[
|
||||||
|
id,
|
||||||
config_name,
|
config_name,
|
||||||
split_type,
|
split_type,
|
||||||
split_value,
|
split_value,
|
||||||
split_name || null,
|
split_name || null,
|
||||||
JSON.stringify(selected_fields),
|
JSON.stringify(selected_fields),
|
||||||
sum_fields ? JSON.stringify(sum_fields) : null
|
sum_fields ? JSON.stringify(sum_fields) : null,
|
||||||
|
now,
|
||||||
|
now
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,39 @@ export async function GET(request: NextRequest) {
|
|||||||
const splitType = searchParams.get('splitType');
|
const splitType = searchParams.get('splitType');
|
||||||
const reportDate = searchParams.get('reportDate');
|
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';
|
let whereClause = 'WHERE 1=1';
|
||||||
const queryParams: any[] = [];
|
const queryParams: any[] = [];
|
||||||
|
|||||||
@@ -1,38 +1,40 @@
|
|||||||
import pool from './db';
|
import pool from './db';
|
||||||
|
|
||||||
// 创建配置表和历史表的SQL语句
|
// 创建配置表和历史表的SQL语句(Doris兼容)
|
||||||
const createTablesSQL = `
|
const createTablesSQL = `
|
||||||
-- 日报配置表(用户字段选择配置)
|
CREATE TABLE t_daily_report_config (
|
||||||
CREATE TABLE IF NOT EXISTS t_daily_report_config (
|
id BIGINT NOT NULL COMMENT '配置ID',
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '配置ID',
|
|
||||||
config_name VARCHAR(100) NOT NULL COMMENT '配置名称',
|
config_name VARCHAR(100) NOT NULL COMMENT '配置名称',
|
||||||
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式:company_id 或 user_id',
|
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式:company_id 或 user_id',
|
||||||
split_value VARCHAR(100) NOT NULL COMMENT '拆分值(企业ID或用户ID)',
|
split_value VARCHAR(100) NOT NULL COMMENT '拆分值(企业ID或用户ID)',
|
||||||
split_name VARCHAR(200) COMMENT '拆分显示名称(企业名称或用户姓名)',
|
split_name VARCHAR(200) NULL COMMENT '拆分显示名称(企业名称或用户姓名)',
|
||||||
selected_fields JSON NOT NULL COMMENT '用户选择的字段列表(JSON数组)',
|
selected_fields VARCHAR(3000) NOT NULL COMMENT '用户选择的字段列表(JSON字符串)',
|
||||||
sum_fields JSON COMMENT '需要求和的字段列表(JSON数组)',
|
sum_fields VARCHAR(3000) NULL COMMENT '需要求和的字段列表(JSON字符串)',
|
||||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
create_time DATETIME NULL COMMENT '创建时间',
|
||||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
update_time DATETIME NULL COMMENT '更新时间',
|
||||||
is_active TINYINT DEFAULT 1 COMMENT '是否启用:0禁用 1启用'
|
is_active TINYINT NULL COMMENT '是否启用:0禁用 1启用'
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日报字段配置表';
|
)
|
||||||
|
DISTRIBUTED BY HASH(id) BUCKETS 1
|
||||||
|
PROPERTIES("replication_num" = "1");
|
||||||
|
|
||||||
-- 日报生成历史记录表
|
CREATE TABLE t_daily_report_history (
|
||||||
CREATE TABLE IF NOT EXISTS t_daily_report_history (
|
id BIGINT NOT NULL COMMENT '记录ID',
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '记录ID',
|
|
||||||
report_date DATE NOT NULL COMMENT '报表日期',
|
report_date DATE NOT NULL COMMENT '报表日期',
|
||||||
start_time DATETIME NOT NULL COMMENT '报表开始时间',
|
start_time DATETIME NOT NULL COMMENT '报表开始时间',
|
||||||
end_time DATETIME NOT NULL COMMENT '报表结束时间',
|
end_time DATETIME NOT NULL COMMENT '报表结束时间',
|
||||||
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式:company_id 或 user_id',
|
split_type VARCHAR(20) NOT NULL COMMENT '拆分方式:company_id 或 user_id',
|
||||||
split_value VARCHAR(100) NOT NULL COMMENT '拆分值(企业ID或用户ID)',
|
split_value VARCHAR(100) NOT NULL COMMENT '拆分值(企业ID或用户ID)',
|
||||||
split_name VARCHAR(200) COMMENT '拆分显示名称',
|
split_name VARCHAR(200) NULL COMMENT '拆分显示名称',
|
||||||
config_id BIGINT COMMENT '使用的配置ID',
|
config_id BIGINT NULL COMMENT '使用的配置ID',
|
||||||
total_orders INT DEFAULT 0 COMMENT '订单总数',
|
total_orders INT NULL COMMENT '订单总数',
|
||||||
total_amount DECIMAL(15,2) DEFAULT 0 COMMENT '总金额',
|
total_amount DECIMALV3 NULL COMMENT '总金额',
|
||||||
sum_results JSON COMMENT '求和结果(JSON对象)',
|
sum_results VARCHAR(3000) NULL COMMENT '求和结果(JSON字符串)',
|
||||||
file_path VARCHAR(500) COMMENT '生成的文件路径',
|
file_path VARCHAR(500) NULL COMMENT '生成的文件路径',
|
||||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '生成时间',
|
create_time DATETIME NULL COMMENT '生成时间',
|
||||||
status TINYINT DEFAULT 1 COMMENT '状态:0失败 1成功'
|
status TINYINT NULL COMMENT '状态:0失败 1成功'
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日报生成历史表';
|
)
|
||||||
|
DISTRIBUTED BY HASH(id) BUCKETS 1
|
||||||
|
PROPERTIES("replication_num" = "1");
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// 初始化数据库表
|
// 初始化数据库表
|
||||||
@@ -49,10 +51,10 @@ export async function initDatabaseTables(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connection.release();
|
connection.release();
|
||||||
console.log('数据库表初始化成功');
|
console.log('数据库表初始化成功(Doris兼容语法)');
|
||||||
console.log('创建了以下表:');
|
console.log('创建了以下表:');
|
||||||
console.log('1. t_daily_report_config - 日报字段配置表(包含拆分值和显示名称)');
|
console.log('1. t_daily_report_config - 日报字段配置表');
|
||||||
console.log('2. t_daily_report_history - 日报生成历史表(包含求和结果)');
|
console.log('2. t_daily_report_history - 日报生成历史表');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('数据库表初始化失败:', error);
|
console.error('数据库表初始化失败:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -224,12 +224,47 @@ export async function generateBatchReports(configId: number): Promise<ReportResu
|
|||||||
// 保存到历史记录表
|
// 保存到历史记录表
|
||||||
const connection2 = await pool.getConnection();
|
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) {
|
if (result.success) {
|
||||||
await connection2.query(
|
await connection2.query(
|
||||||
`INSERT INTO t_daily_report_history
|
`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)
|
(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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
[
|
[
|
||||||
|
historyId,
|
||||||
result.reportDate,
|
result.reportDate,
|
||||||
result.startTime,
|
result.startTime,
|
||||||
result.endTime,
|
result.endTime,
|
||||||
@@ -241,15 +276,17 @@ export async function generateBatchReports(configId: number): Promise<ReportResu
|
|||||||
result.totalAmount,
|
result.totalAmount,
|
||||||
result.sumResults ? JSON.stringify(result.sumResults) : null,
|
result.sumResults ? JSON.stringify(result.sumResults) : null,
|
||||||
result.filePath || null,
|
result.filePath || null,
|
||||||
|
now,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await connection2.query(
|
await connection2.query(
|
||||||
`INSERT INTO t_daily_report_history
|
`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)
|
(id, report_date, start_time, end_time, split_type, split_value, split_name, config_id, total_orders, total_amount, create_time, status)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
[
|
[
|
||||||
|
historyId,
|
||||||
result.reportDate,
|
result.reportDate,
|
||||||
result.startTime,
|
result.startTime,
|
||||||
result.endTime,
|
result.endTime,
|
||||||
|
|||||||
Reference in New Issue
Block a user