|
|
|
|
|
-- AmazingData 金融数据服务平台 - 数据库初始化脚本
|
|
|
|
|
|
-- PostgreSQL 15+
|
|
|
|
|
|
-- 执行命令: psql -U postgres -d amazing_data -f init.sql
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 1. 创建扩展
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
|
|
|
CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- 用于模糊搜索
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 2. 用户表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
|
username VARCHAR(50) UNIQUE NOT NULL,
|
|
|
|
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
|
|
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
|
|
|
|
is_superuser BOOLEAN DEFAULT FALSE,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE users IS '系统用户表';
|
|
|
|
|
|
COMMENT ON COLUMN users.password_hash IS 'bcrypt加密的密码';
|
|
|
|
|
|
|
|
|
|
|
|
-- 默认管理员用户由应用启动时自动创建 (admin/admin123)
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 3. SDK配置表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS sdk_configs (
|
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
|
name VARCHAR(100) NOT NULL,
|
|
|
|
|
|
username VARCHAR(100) NOT NULL,
|
|
|
|
|
|
password VARCHAR(255) NOT NULL,
|
|
|
|
|
|
host VARCHAR(100) NOT NULL,
|
|
|
|
|
|
port INTEGER NOT NULL DEFAULT 8080,
|
|
|
|
|
|
local_path VARCHAR(255) DEFAULT './amazing_data_cache/',
|
|
|
|
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
|
|
|
|
is_default BOOLEAN DEFAULT FALSE,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE sdk_configs IS 'AmazingData SDK配置表';
|
|
|
|
|
|
COMMENT ON COLUMN sdk_configs.password IS 'SDK登录密码,建议加密存储';
|
|
|
|
|
|
|
|
|
|
|
|
-- 确保只有一个默认配置
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION ensure_single_default_sdk()
|
|
|
|
|
|
RETURNS TRIGGER AS $$
|
|
|
|
|
|
BEGIN
|
|
|
|
|
|
IF NEW.is_default THEN
|
|
|
|
|
|
UPDATE sdk_configs SET is_default = FALSE WHERE id != NEW.id;
|
|
|
|
|
|
END IF;
|
|
|
|
|
|
RETURN NEW;
|
|
|
|
|
|
END;
|
|
|
|
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
|
|
|
|
|
|
|
|
DROP TRIGGER IF EXISTS trg_ensure_single_default_sdk ON sdk_configs;
|
|
|
|
|
|
CREATE TRIGGER trg_ensure_single_default_sdk
|
|
|
|
|
|
BEFORE INSERT OR UPDATE ON sdk_configs
|
|
|
|
|
|
FOR EACH ROW
|
|
|
|
|
|
EXECUTE FUNCTION ensure_single_default_sdk();
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 4. 系统配置表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS system_configs (
|
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
|
config_name VARCHAR(100),
|
|
|
|
|
|
config_key VARCHAR(100) UNIQUE NOT NULL,
|
|
|
|
|
|
config_value TEXT NOT NULL,
|
|
|
|
|
|
current_db_type VARCHAR(50),
|
|
|
|
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE system_configs IS '系统配置键值表';
|
|
|
|
|
|
|
|
|
|
|
|
INSERT INTO system_configs (config_key, config_value, description) VALUES
|
|
|
|
|
|
('cache.default_period', 'daily', '默认K线周期'),
|
|
|
|
|
|
('cache.default_days', '365', '默认查询天数'),
|
|
|
|
|
|
('cache.auto_cleanup_days', '7', '实时数据自动清理天数'),
|
|
|
|
|
|
('cache.batch_size', '100', '批量缓存每次处理代码数'),
|
|
|
|
|
|
('cache.missing_threshold', '0.1', '数据缺失判断阈值(10%)'),
|
|
|
|
|
|
('realtime.subscribe_interval', '1000', '实时订阅推送间隔(ms)'),
|
|
|
|
|
|
('jwt.expire_hours', '24', 'JWT Token过期时间(小时)')
|
|
|
|
|
|
ON CONFLICT (config_key) DO NOTHING;
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 5. 股票代码信息表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stock_info (
|
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) UNIQUE NOT NULL,
|
|
|
|
|
|
symbol VARCHAR(100) NOT NULL,
|
|
|
|
|
|
security_status INTEGER,
|
|
|
|
|
|
pre_close DECIMAL(12, 4),
|
|
|
|
|
|
high_limited DECIMAL(12, 4),
|
|
|
|
|
|
low_limited DECIMAL(12, 4),
|
|
|
|
|
|
price_tick DECIMAL(10, 4),
|
|
|
|
|
|
exchange VARCHAR(10), -- SH, SZ, BJ
|
|
|
|
|
|
industry VARCHAR(50),
|
|
|
|
|
|
list_date DATE,
|
|
|
|
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE stock_info IS '股票基础信息表';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_info_code ON stock_info(code);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_info_exchange ON stock_info(exchange);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_info_symbol ON stock_info USING gin(symbol gin_trgm_ops);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 6. 期货代码信息表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS future_info (
|
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) UNIQUE NOT NULL,
|
|
|
|
|
|
symbol VARCHAR(100) NOT NULL,
|
|
|
|
|
|
underlying VARCHAR(20), -- 标的代码
|
|
|
|
|
|
contract_month VARCHAR(10),
|
|
|
|
|
|
pre_close DECIMAL(12, 4),
|
|
|
|
|
|
high_limited DECIMAL(12, 4),
|
|
|
|
|
|
low_limited DECIMAL(12, 4),
|
|
|
|
|
|
price_tick DECIMAL(10, 4),
|
|
|
|
|
|
exchange VARCHAR(10) DEFAULT 'CFE', -- CFE: 中金所
|
|
|
|
|
|
list_date DATE,
|
|
|
|
|
|
expire_date DATE,
|
|
|
|
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE future_info IS '期货基础信息表';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_future_info_code ON future_info(code);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_future_info_underlying ON future_info(underlying);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 7. 股票日线数据表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stock_kline_daily (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
trade_date DATE NOT NULL,
|
|
|
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
volume BIGINT NOT NULL,
|
|
|
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
|
|
|
adj_factor DECIMAL(12, 6), -- 复权因子
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, trade_date)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE stock_kline_daily IS '股票日线K线数据';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_daily_code_date ON stock_kline_daily(code, trade_date);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_daily_trade_date ON stock_kline_daily(trade_date);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_daily_code ON stock_kline_daily(code);
|
|
|
|
|
|
|
|
|
|
|
|
-- 分区表(按年分区,可选)
|
|
|
|
|
|
-- 如果需要分区,可以创建子表
|
|
|
|
|
|
-- CREATE TABLE stock_kline_daily_2024 PARTITION OF stock_kline_daily
|
|
|
|
|
|
-- FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 8. 股票分钟数据表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stock_kline_min (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
period_type VARCHAR(10) NOT NULL CHECK (period_type IN ('min1', 'min5', 'min15', 'min30', 'min60')),
|
|
|
|
|
|
trade_datetime TIMESTAMP NOT NULL,
|
|
|
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
volume BIGINT NOT NULL,
|
|
|
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, period_type, trade_datetime)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE stock_kline_min IS '股票分钟K线数据';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_min_code_period_datetime ON stock_kline_min(code, period_type, trade_datetime);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_stock_min_trade_datetime ON stock_kline_min(trade_datetime);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 9. 期货日线数据表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS future_kline_daily (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
trade_date DATE NOT NULL,
|
|
|
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
volume BIGINT NOT NULL,
|
|
|
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
|
|
|
settle DECIMAL(12, 4),
|
|
|
|
|
|
open_interest BIGINT,
|
|
|
|
|
|
pre_settle DECIMAL(12, 4),
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, trade_date)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE future_kline_daily IS '期货日线K线数据';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_future_daily_code_date ON future_kline_daily(code, trade_date);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_future_daily_trade_date ON future_kline_daily(trade_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 10. 期货分钟数据表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS future_kline_min (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
period_type VARCHAR(10) NOT NULL CHECK (period_type IN ('min1', 'min5', 'min15', 'min30', 'min60')),
|
|
|
|
|
|
trade_datetime TIMESTAMP NOT NULL,
|
|
|
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
|
|
|
volume BIGINT NOT NULL,
|
|
|
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
|
|
|
settle DECIMAL(12, 4),
|
|
|
|
|
|
open_interest BIGINT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, period_type, trade_datetime)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE future_kline_min IS '期货分钟K线数据';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_future_min_code_period_datetime ON future_kline_min(code, period_type, trade_datetime);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 11. 指数日线数据表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS index_kline_daily (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
trade_date DATE NOT NULL,
|
|
|
|
|
|
open DECIMAL(12, 4),
|
|
|
|
|
|
high DECIMAL(12, 4),
|
|
|
|
|
|
low DECIMAL(12, 4),
|
|
|
|
|
|
close DECIMAL(12, 4),
|
|
|
|
|
|
volume BIGINT,
|
|
|
|
|
|
amount DECIMAL(18, 4),
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, trade_date)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE index_kline_daily IS '指数日线数据';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_index_daily_code_date ON index_kline_daily(code, trade_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 12. 实时快照数据表 (TTL 7天)
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS realtime_snapshot (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
security_type VARCHAR(20) NOT NULL, -- stock, future, index, etf, kzz, option
|
|
|
|
|
|
trade_time TIMESTAMP NOT NULL,
|
|
|
|
|
|
pre_close DECIMAL(12, 4),
|
|
|
|
|
|
last DECIMAL(12, 4),
|
|
|
|
|
|
open DECIMAL(12, 4),
|
|
|
|
|
|
high DECIMAL(12, 4),
|
|
|
|
|
|
low DECIMAL(12, 4),
|
|
|
|
|
|
close DECIMAL(12, 4),
|
|
|
|
|
|
volume BIGINT,
|
|
|
|
|
|
amount DECIMAL(18, 4),
|
|
|
|
|
|
-- 盘口数据
|
|
|
|
|
|
ask_price1 DECIMAL(12, 4),
|
|
|
|
|
|
ask_price2 DECIMAL(12, 4),
|
|
|
|
|
|
ask_price3 DECIMAL(12, 4),
|
|
|
|
|
|
ask_price4 DECIMAL(12, 4),
|
|
|
|
|
|
ask_price5 DECIMAL(12, 4),
|
|
|
|
|
|
ask_volume1 INTEGER,
|
|
|
|
|
|
ask_volume2 INTEGER,
|
|
|
|
|
|
ask_volume3 INTEGER,
|
|
|
|
|
|
ask_volume4 INTEGER,
|
|
|
|
|
|
ask_volume5 INTEGER,
|
|
|
|
|
|
bid_price1 DECIMAL(12, 4),
|
|
|
|
|
|
bid_price2 DECIMAL(12, 4),
|
|
|
|
|
|
bid_price3 DECIMAL(12, 4),
|
|
|
|
|
|
bid_price4 DECIMAL(12, 4),
|
|
|
|
|
|
bid_price5 DECIMAL(12, 4),
|
|
|
|
|
|
bid_volume1 INTEGER,
|
|
|
|
|
|
bid_volume2 INTEGER,
|
|
|
|
|
|
bid_volume3 INTEGER,
|
|
|
|
|
|
bid_volume4 INTEGER,
|
|
|
|
|
|
bid_volume5 INTEGER,
|
|
|
|
|
|
-- 期货特有字段
|
|
|
|
|
|
settle DECIMAL(12, 4),
|
|
|
|
|
|
open_interest BIGINT,
|
|
|
|
|
|
pre_settle DECIMAL(12, 4),
|
|
|
|
|
|
average_price DECIMAL(12, 4),
|
|
|
|
|
|
-- 状态
|
|
|
|
|
|
trading_phase_code VARCHAR(10),
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
expires_at TIMESTAMP WITH TIME ZONE NOT NULL -- 过期时间
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE realtime_snapshot IS '实时快照数据,自动清理7天前数据';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_snapshot_code_time ON realtime_snapshot(code, trade_time);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_snapshot_expires ON realtime_snapshot(expires_at);
|
|
|
|
|
|
|
|
|
|
|
|
-- 创建自动清理过期数据的触发器
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION auto_cleanup_expired_snapshots()
|
|
|
|
|
|
RETURNS void AS $$
|
|
|
|
|
|
BEGIN
|
|
|
|
|
|
DELETE FROM realtime_snapshot
|
|
|
|
|
|
WHERE expires_at < NOW();
|
|
|
|
|
|
END;
|
|
|
|
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 13. 历史快照数据表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS history_snapshot (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
security_type VARCHAR(20) NOT NULL,
|
|
|
|
|
|
trade_date DATE NOT NULL,
|
|
|
|
|
|
trade_time TIME NOT NULL,
|
|
|
|
|
|
pre_close DECIMAL(12, 4),
|
|
|
|
|
|
last DECIMAL(12, 4),
|
|
|
|
|
|
open DECIMAL(12, 4),
|
|
|
|
|
|
high DECIMAL(12, 4),
|
|
|
|
|
|
low DECIMAL(12, 4),
|
|
|
|
|
|
close DECIMAL(12, 4),
|
|
|
|
|
|
volume BIGINT,
|
|
|
|
|
|
amount DECIMAL(18, 4),
|
|
|
|
|
|
ask_price1 DECIMAL(12, 4),
|
|
|
|
|
|
ask_volume1 INTEGER,
|
|
|
|
|
|
bid_price1 DECIMAL(12, 4),
|
|
|
|
|
|
bid_volume1 INTEGER,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, trade_date, trade_time)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE history_snapshot IS '历史快照数据';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hist_snapshot_code_date ON history_snapshot(code, trade_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 14. 财务数据表 - 资产负债表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS finance_balance_sheet (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
report_date DATE NOT NULL,
|
|
|
|
|
|
report_type INTEGER, -- 1:年报, 2:中报, 3:季报
|
|
|
|
|
|
statement_type INTEGER, -- 报表类型
|
|
|
|
|
|
-- 资产
|
|
|
|
|
|
total_assets DECIMAL(18, 4),
|
|
|
|
|
|
total_cur_assets DECIMAL(18, 4),
|
|
|
|
|
|
total_noncur_assets DECIMAL(18, 4),
|
|
|
|
|
|
currency_cap DECIMAL(18, 4),
|
|
|
|
|
|
notes_receivable DECIMAL(18, 4),
|
|
|
|
|
|
acct_receivable DECIMAL(18, 4),
|
|
|
|
|
|
inventory DECIMAL(18, 4),
|
|
|
|
|
|
fix_assets DECIMAL(18, 4),
|
|
|
|
|
|
-- 负债
|
|
|
|
|
|
total_liab DECIMAL(18, 4),
|
|
|
|
|
|
total_cur_liab DECIMAL(18, 4),
|
|
|
|
|
|
total_noncur_liab DECIMAL(18, 4),
|
|
|
|
|
|
notes_payable DECIMAL(18, 4),
|
|
|
|
|
|
acct_payable DECIMAL(18, 4),
|
|
|
|
|
|
st_borrowing DECIMAL(18, 4),
|
|
|
|
|
|
lt_loan DECIMAL(18, 4),
|
|
|
|
|
|
-- 权益
|
|
|
|
|
|
tot_share_equity DECIMAL(18, 4),
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, report_date, statement_type)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE finance_balance_sheet IS '资产负债表';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_balance_code_date ON finance_balance_sheet(code, report_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 15. 财务数据表 - 现金流量表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS finance_cash_flow (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
report_date DATE NOT NULL,
|
|
|
|
|
|
report_type INTEGER,
|
|
|
|
|
|
statement_type INTEGER,
|
|
|
|
|
|
net_cash_flows_opera_act DECIMAL(18, 4),
|
|
|
|
|
|
net_cash_flows_inv_act DECIMAL(18, 4),
|
|
|
|
|
|
net_cash_flows_fin_act DECIMAL(18, 4),
|
|
|
|
|
|
net_incr_cash_and_cash_equ DECIMAL(18, 4),
|
|
|
|
|
|
cash_recp_sg_and_rs DECIMAL(18, 4),
|
|
|
|
|
|
cash_pay_goods_services DECIMAL(18, 4),
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, report_date, statement_type)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE finance_cash_flow IS '现金流量表';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_cashflow_code_date ON finance_cash_flow(code, report_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 16. 财务数据表 - 利润表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS finance_income (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
report_date DATE NOT NULL,
|
|
|
|
|
|
report_type INTEGER,
|
|
|
|
|
|
statement_type INTEGER,
|
|
|
|
|
|
tot_opera_rev DECIMAL(18, 4),
|
|
|
|
|
|
opera_rev DECIMAL(18, 4),
|
|
|
|
|
|
tot_opera_cost DECIMAL(18, 4),
|
|
|
|
|
|
opera_profit DECIMAL(18, 4),
|
|
|
|
|
|
total_profit DECIMAL(18, 4),
|
|
|
|
|
|
net_pro_incl_min_int_inc DECIMAL(18, 4),
|
|
|
|
|
|
basic_eps DECIMAL(12, 6),
|
|
|
|
|
|
diluted_eps DECIMAL(12, 6),
|
|
|
|
|
|
rd_exp DECIMAL(18, 4),
|
|
|
|
|
|
selling_exp DECIMAL(18, 4),
|
|
|
|
|
|
admin_exp DECIMAL(18, 4),
|
|
|
|
|
|
fin_exp DECIMAL(18, 4),
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(code, report_date, statement_type)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE finance_income IS '利润表';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_income_code_date ON finance_income(code, report_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 17. 交易日历表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS trading_calendar (
|
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
|
market VARCHAR(10) NOT NULL, -- SH, SZ, BJ, CFE
|
|
|
|
|
|
trade_date DATE NOT NULL,
|
|
|
|
|
|
is_trading_day BOOLEAN DEFAULT TRUE,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
UNIQUE(market, trade_date)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE trading_calendar IS '交易日历';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_calendar_market_date ON trading_calendar(market, trade_date);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_calendar_date ON trading_calendar(trade_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 18. 缓存任务表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS cache_tasks (
|
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
|
task_name VARCHAR(200) NOT NULL,
|
|
|
|
|
|
task_type VARCHAR(50) NOT NULL CHECK (task_type IN ('detect_missing', 'cache_data', 'sync_data')),
|
|
|
|
|
|
security_type VARCHAR(20) NOT NULL, -- stock, future, index
|
|
|
|
|
|
period_type VARCHAR(10), -- daily, min1, min5, etc.
|
|
|
|
|
|
start_date DATE NOT NULL,
|
|
|
|
|
|
end_date DATE NOT NULL,
|
|
|
|
|
|
code_list TEXT, -- 逗号分隔的代码列表,NULL表示全部
|
|
|
|
|
|
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'running', 'completed', 'failed', 'cancelled')),
|
|
|
|
|
|
progress DECIMAL(5, 2) DEFAULT 0, -- 0-100
|
|
|
|
|
|
total_count INTEGER DEFAULT 0,
|
|
|
|
|
|
success_count INTEGER DEFAULT 0,
|
|
|
|
|
|
error_count INTEGER DEFAULT 0,
|
|
|
|
|
|
error_message TEXT,
|
|
|
|
|
|
created_by INTEGER REFERENCES users(id),
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
started_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
|
|
completed_at TIMESTAMP WITH TIME ZONE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE cache_tasks IS '数据缓存任务';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_cache_tasks_status ON cache_tasks(status);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_cache_tasks_created ON cache_tasks(created_at);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 19. 缓存任务详情表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS cache_task_details (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
task_id INTEGER NOT NULL REFERENCES cache_tasks(id) ON DELETE CASCADE,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
trade_date DATE NOT NULL,
|
|
|
|
|
|
expected_count INTEGER DEFAULT 0,
|
|
|
|
|
|
actual_count INTEGER DEFAULT 0,
|
|
|
|
|
|
is_missing BOOLEAN DEFAULT FALSE,
|
|
|
|
|
|
status VARCHAR(20) DEFAULT 'pending', -- pending, success, failed, skipped
|
|
|
|
|
|
error_message TEXT,
|
|
|
|
|
|
processed_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE cache_task_details IS '缓存任务详细记录';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_cache_details_task ON cache_task_details(task_id);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_cache_details_code ON cache_task_details(code);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 20. API测试日志表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS api_test_logs (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
test_name VARCHAR(200) NOT NULL,
|
|
|
|
|
|
api_category VARCHAR(50) NOT NULL, -- base_data, stock, future, realtime, finance, etc.
|
|
|
|
|
|
api_endpoint VARCHAR(200) NOT NULL,
|
|
|
|
|
|
request_method VARCHAR(10) NOT NULL,
|
|
|
|
|
|
request_params JSONB,
|
|
|
|
|
|
response_data JSONB,
|
|
|
|
|
|
status_code INTEGER,
|
|
|
|
|
|
execution_time_ms INTEGER,
|
|
|
|
|
|
is_success BOOLEAN DEFAULT FALSE,
|
|
|
|
|
|
error_message TEXT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE api_test_logs IS 'API接口测试日志';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_test_logs_category ON api_test_logs(api_category);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_test_logs_endpoint ON api_test_logs(api_endpoint);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_test_logs_created ON api_test_logs(created_at);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 21. 数据同步日志表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS data_sync_logs (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
|
|
security_type VARCHAR(20) NOT NULL,
|
|
|
|
|
|
period_type VARCHAR(10),
|
|
|
|
|
|
start_date DATE,
|
|
|
|
|
|
end_date DATE,
|
|
|
|
|
|
record_count INTEGER DEFAULT 0,
|
|
|
|
|
|
source VARCHAR(50) DEFAULT 'sdk', -- sdk, manual, import
|
|
|
|
|
|
status VARCHAR(20) DEFAULT 'success',
|
|
|
|
|
|
error_message TEXT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON TABLE data_sync_logs IS '数据同步日志';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_sync_logs_code ON data_sync_logs(code);
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_sync_logs_created ON data_sync_logs(created_at);
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 22. 创建视图 - 数据缓存状态概览
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE OR REPLACE VIEW v_cache_status AS
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
code,
|
|
|
|
|
|
'stock' as security_type,
|
|
|
|
|
|
'daily' as period_type,
|
|
|
|
|
|
COUNT(*) as record_count,
|
|
|
|
|
|
MIN(trade_date) as min_date,
|
|
|
|
|
|
MAX(trade_date) as max_date
|
|
|
|
|
|
FROM stock_kline_daily
|
|
|
|
|
|
GROUP BY code
|
|
|
|
|
|
UNION ALL
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
code,
|
|
|
|
|
|
'future' as security_type,
|
|
|
|
|
|
'daily' as period_type,
|
|
|
|
|
|
COUNT(*) as record_count,
|
|
|
|
|
|
MIN(trade_date) as min_date,
|
|
|
|
|
|
MAX(trade_date) as max_date
|
|
|
|
|
|
FROM future_kline_daily
|
|
|
|
|
|
GROUP BY code;
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON VIEW v_cache_status IS '数据缓存状态概览视图';
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 23. 创建函数 - 获取交易日列表
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION get_trading_days(
|
|
|
|
|
|
p_market VARCHAR(10),
|
|
|
|
|
|
p_start_date DATE,
|
|
|
|
|
|
p_end_date DATE
|
|
|
|
|
|
)
|
|
|
|
|
|
RETURNS TABLE (trade_date DATE) AS $$
|
|
|
|
|
|
BEGIN
|
|
|
|
|
|
RETURN QUERY
|
|
|
|
|
|
SELECT tc.trade_date
|
|
|
|
|
|
FROM trading_calendar tc
|
|
|
|
|
|
WHERE tc.market = p_market
|
|
|
|
|
|
AND tc.trade_date BETWEEN p_start_date AND p_end_date
|
|
|
|
|
|
AND tc.is_trading_day = TRUE
|
|
|
|
|
|
ORDER BY tc.trade_date;
|
|
|
|
|
|
END;
|
|
|
|
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON FUNCTION get_trading_days IS '获取指定区间的交易日列表';
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 24. 创建函数 - 计算数据缺失率
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION calculate_missing_ratio(
|
|
|
|
|
|
p_code VARCHAR(20),
|
|
|
|
|
|
p_security_type VARCHAR(20),
|
|
|
|
|
|
p_period_type VARCHAR(10),
|
|
|
|
|
|
p_start_date DATE,
|
|
|
|
|
|
p_end_date DATE
|
|
|
|
|
|
)
|
|
|
|
|
|
RETURNS TABLE (
|
|
|
|
|
|
expected_count INTEGER,
|
|
|
|
|
|
actual_count INTEGER,
|
|
|
|
|
|
missing_count INTEGER,
|
|
|
|
|
|
missing_ratio DECIMAL(5, 4)
|
|
|
|
|
|
) AS $$
|
|
|
|
|
|
DECLARE
|
|
|
|
|
|
v_expected INTEGER;
|
|
|
|
|
|
v_actual INTEGER;
|
|
|
|
|
|
v_market VARCHAR(10);
|
|
|
|
|
|
BEGIN
|
|
|
|
|
|
-- 确定市场
|
|
|
|
|
|
v_market := CASE
|
|
|
|
|
|
WHEN p_security_type = 'future' THEN 'CFE'
|
|
|
|
|
|
WHEN RIGHT(p_code, 3) = '.SH' THEN 'SH'
|
|
|
|
|
|
WHEN RIGHT(p_code, 3) = '.SZ' THEN 'SZ'
|
|
|
|
|
|
WHEN RIGHT(p_code, 3) = '.BJ' THEN 'BJ'
|
|
|
|
|
|
ELSE 'SH'
|
|
|
|
|
|
END;
|
|
|
|
|
|
|
|
|
|
|
|
-- 计算期望数据条数
|
|
|
|
|
|
SELECT COUNT(*) INTO v_expected
|
|
|
|
|
|
FROM get_trading_days(v_market, p_start_date, p_end_date);
|
|
|
|
|
|
|
|
|
|
|
|
-- 计算实际数据条数
|
|
|
|
|
|
IF p_security_type = 'stock' AND p_period_type = 'daily' THEN
|
|
|
|
|
|
SELECT COUNT(*) INTO v_actual
|
|
|
|
|
|
FROM stock_kline_daily
|
|
|
|
|
|
WHERE code = p_code AND trade_date BETWEEN p_start_date AND p_end_date;
|
|
|
|
|
|
ELSIF p_security_type = 'future' AND p_period_type = 'daily' THEN
|
|
|
|
|
|
SELECT COUNT(*) INTO v_actual
|
|
|
|
|
|
FROM future_kline_daily
|
|
|
|
|
|
WHERE code = p_code AND trade_date BETWEEN p_start_date AND p_end_date;
|
|
|
|
|
|
ELSE
|
|
|
|
|
|
v_actual := 0;
|
|
|
|
|
|
END IF;
|
|
|
|
|
|
|
|
|
|
|
|
RETURN QUERY
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
v_expected,
|
|
|
|
|
|
v_actual,
|
|
|
|
|
|
GREATEST(0, v_expected - v_actual),
|
|
|
|
|
|
CASE
|
|
|
|
|
|
WHEN v_expected > 0 THEN (v_expected - v_actual)::DECIMAL / v_expected
|
|
|
|
|
|
ELSE 0
|
|
|
|
|
|
END;
|
|
|
|
|
|
END;
|
|
|
|
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
|
|
|
|
|
|
|
|
COMMENT ON FUNCTION calculate_missing_ratio IS '计算指定代码在指定区间的数据缺失率';
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 25. 创建触发器 - 自动更新updated_at
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
|
|
|
|
RETURNS TRIGGER AS $$
|
|
|
|
|
|
BEGIN
|
|
|
|
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
|
|
|
|
RETURN NEW;
|
|
|
|
|
|
END;
|
|
|
|
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
|
|
|
|
|
|
|
|
-- 为用户表创建触发器
|
|
|
|
|
|
DROP TRIGGER IF EXISTS trg_users_updated_at ON users;
|
|
|
|
|
|
CREATE TRIGGER trg_users_updated_at
|
|
|
|
|
|
BEFORE UPDATE ON users
|
|
|
|
|
|
FOR EACH ROW
|
|
|
|
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
|
|
|
|
|
|
|
|
-- 为SDK配置表创建触发器
|
|
|
|
|
|
DROP TRIGGER IF EXISTS trg_sdk_configs_updated_at ON sdk_configs;
|
|
|
|
|
|
CREATE TRIGGER trg_sdk_configs_updated_at
|
|
|
|
|
|
BEFORE UPDATE ON sdk_configs
|
|
|
|
|
|
FOR EACH ROW
|
|
|
|
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
|
|
|
|
|
|
|
|
-- 为系统配置表创建触发器
|
|
|
|
|
|
DROP TRIGGER IF EXISTS trg_system_configs_updated_at ON system_configs;
|
|
|
|
|
|
CREATE TRIGGER trg_system_configs_updated_at
|
|
|
|
|
|
BEFORE UPDATE ON system_configs
|
|
|
|
|
|
FOR EACH ROW
|
|
|
|
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 26. 创建分区表(可选,用于大数据量场景)
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 如果需要按月分区,可以使用以下命令创建分区表结构
|
|
|
|
|
|
-- 注意:这需要PostgreSQL 10+
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
-- 股票分钟数据按月分区示例
|
|
|
|
|
|
CREATE TABLE stock_kline_min_partitioned (
|
|
|
|
|
|
LIKE stock_kline_min INCLUDING ALL
|
|
|
|
|
|
) PARTITION BY RANGE (trade_datetime);
|
|
|
|
|
|
|
|
|
|
|
|
-- 创建各月分区
|
|
|
|
|
|
CREATE TABLE stock_kline_min_202401 PARTITION OF stock_kline_min_partitioned
|
|
|
|
|
|
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
|
|
|
|
|
|
CREATE TABLE stock_kline_min_202402 PARTITION OF stock_kline_min_partitioned
|
|
|
|
|
|
FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');
|
|
|
|
|
|
-- ... 更多分区
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
-- 初始化完成
|
|
|
|
|
|
-- ============================================
|
|
|
|
|
|
SELECT 'Database initialization completed successfully!' as status;
|