mall数据库文件

This commit is contained in:
comlibmb
2026-01-30 16:17:13 +08:00
parent cfec4a16c0
commit 8f181b2b6a
42 changed files with 12758 additions and 2 deletions

View File

@@ -0,0 +1,303 @@
-- ============================================
-- 数据分析实时大屏 - 基础业务表结构(创建版 / Create-only
-- ============================================
-- 用途创建业务核心表orders, users, user_sessions, products, merchants 等)
-- 特点:
-- 1. 不做 DROP/DELETE/TRUNCATE不清空数据
-- 2. 通过 IF NOT EXISTS + 系统表判断,实现可重复执行
-- 3. 与 analytics_* 表ANALYTICS_DB_SCHEMA.sql配套使用
-- ============================================
-- ============================================
-- 1. 表结构创建
-- ============================================
-- 1.1 商家表
CREATE TABLE IF NOT EXISTS merchants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
shop_name VARCHAR(255) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE public.merchants IS '商家表';
COMMENT ON COLUMN public.merchants.id IS '商家ID';
COMMENT ON COLUMN public.merchants.shop_name IS '店铺名称';
COMMENT ON COLUMN public.merchants.created_at IS '创建时间';
-- 1.2 商品表
CREATE TABLE IF NOT EXISTS products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
merchant_id UUID REFERENCES merchants(id) ON DELETE SET NULL,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
sales INTEGER DEFAULT 0,
status INTEGER DEFAULT 1,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE public.products IS '商品表';
COMMENT ON COLUMN public.products.id IS '商品ID';
COMMENT ON COLUMN public.products.merchant_id IS '所属商家ID';
COMMENT ON COLUMN public.products.name IS '商品名称';
COMMENT ON COLUMN public.products.price IS '价格';
COMMENT ON COLUMN public.products.sales IS '销量';
COMMENT ON COLUMN public.products.status IS '状态1:上架, 0:下架)';
COMMENT ON COLUMN public.products.created_at IS '创建时间';
-- 1.3 用户(统计兼容)表
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY,
phone VARCHAR(20) UNIQUE,
email VARCHAR(255),
nickname VARCHAR(100),
last_login_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE public.users IS '用户(统计兼容表,不作为权威用户表)';
COMMENT ON COLUMN public.users.id IS '用户ID建议与 auth.users.id/ak_users.id 对齐)';
COMMENT ON COLUMN public.users.phone IS '手机号(可选)';
COMMENT ON COLUMN public.users.email IS '邮箱(可选)';
COMMENT ON COLUMN public.users.nickname IS '昵称';
COMMENT ON COLUMN public.users.last_login_at IS '最后登录时间';
COMMENT ON COLUMN public.users.created_at IS '创建时间';
COMMENT ON COLUMN public.users.updated_at IS '更新时间';
-- 1.4 订单表
CREATE TABLE IF NOT EXISTS orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
merchant_id UUID REFERENCES merchants(id) ON DELETE SET NULL,
total_amount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
status INTEGER NOT NULL DEFAULT 0,
payment_method VARCHAR(50),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE public.orders IS '订单表';
COMMENT ON COLUMN public.orders.id IS '订单ID';
COMMENT ON COLUMN public.orders.user_id IS '用户ID';
COMMENT ON COLUMN public.orders.merchant_id IS '商家ID';
COMMENT ON COLUMN public.orders.total_amount IS '订单总金额';
COMMENT ON COLUMN public.orders.status IS '订单状态0:待支付, 1:已支付, 2:已完成, 3:已取消)';
COMMENT ON COLUMN public.orders.payment_method IS '支付方式';
COMMENT ON COLUMN public.orders.created_at IS '创建时间';
COMMENT ON COLUMN public.orders.updated_at IS '更新时间';
-- 1.5 订单商品关联表
CREATE TABLE IF NOT EXISTS order_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
order_id UUID NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
product_id UUID NOT NULL REFERENCES products(id) ON DELETE RESTRICT,
quantity INTEGER NOT NULL DEFAULT 1,
price DECIMAL(10, 2) NOT NULL,
total_amount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE public.order_items IS '订单商品关联表';
COMMENT ON COLUMN public.order_items.id IS '主键';
COMMENT ON COLUMN public.order_items.order_id IS '订单ID';
COMMENT ON COLUMN public.order_items.product_id IS '商品ID';
COMMENT ON COLUMN public.order_items.quantity IS '数量';
COMMENT ON COLUMN public.order_items.price IS '单价';
COMMENT ON COLUMN public.order_items.total_amount IS '总价';
COMMENT ON COLUMN public.order_items.created_at IS '创建时间';
-- 1.6 用户会话表
CREATE TABLE IF NOT EXISTS user_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
session_token VARCHAR(255) UNIQUE,
last_active_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
is_active BOOLEAN DEFAULT true,
ip_address VARCHAR(45),
user_agent TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE public.user_sessions IS '用户会话表(用于在线用户统计)';
COMMENT ON COLUMN public.user_sessions.id IS '会话ID';
COMMENT ON COLUMN public.user_sessions.user_id IS '用户ID';
COMMENT ON COLUMN public.user_sessions.session_token IS '会话Token';
COMMENT ON COLUMN public.user_sessions.last_active_at IS '最后活跃时间';
COMMENT ON COLUMN public.user_sessions.is_active IS '是否活跃';
COMMENT ON COLUMN public.user_sessions.ip_address IS 'IP地址';
COMMENT ON COLUMN public.user_sessions.user_agent IS '用户代理';
COMMENT ON COLUMN public.user_sessions.created_at IS '创建时间';
COMMENT ON COLUMN public.user_sessions.updated_at IS '更新时间';
-- 1.7 访问日志表
CREATE TABLE IF NOT EXISTS page_views (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
path VARCHAR(255),
source VARCHAR(50) DEFAULT 'direct',
referrer VARCHAR(255),
ip_address VARCHAR(45),
user_agent TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE public.page_views IS '访问日志表(用于转化率分析)';
COMMENT ON COLUMN public.page_views.id IS '主键';
COMMENT ON COLUMN public.page_views.user_id IS '用户ID可空表示匿名访问';
COMMENT ON COLUMN public.page_views.path IS '访问路径';
COMMENT ON COLUMN public.page_views.source IS '流量来源direct/search/social/ad';
COMMENT ON COLUMN public.page_views.referrer IS '来源页面';
COMMENT ON COLUMN public.page_views.ip_address IS 'IP地址';
COMMENT ON COLUMN public.page_views.user_agent IS '用户代理';
COMMENT ON COLUMN public.page_views.created_at IS '创建时间';
-- ============================================
-- 2. 索引创建
-- ============================================
-- orders
CREATE INDEX IF NOT EXISTS idx_orders_created_at ON orders(created_at);
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id);
CREATE INDEX IF NOT EXISTS idx_orders_created_at_status ON orders(created_at, status);
-- user_sessions
CREATE INDEX IF NOT EXISTS idx_user_sessions_last_active_at ON user_sessions(last_active_at);
CREATE INDEX IF NOT EXISTS idx_user_sessions_is_active ON user_sessions(is_active);
CREATE INDEX IF NOT EXISTS idx_user_sessions_user_id ON user_sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_user_sessions_created_at ON user_sessions(created_at);
-- users
CREATE INDEX IF NOT EXISTS idx_users_last_login_at ON users(last_login_at);
-- order_items
CREATE INDEX IF NOT EXISTS idx_order_items_order_id ON order_items(order_id);
CREATE INDEX IF NOT EXISTS idx_order_items_product_id ON order_items(product_id);
-- page_views
CREATE INDEX IF NOT EXISTS idx_page_views_user_id ON page_views(user_id);
CREATE INDEX IF NOT EXISTS idx_page_views_created_at ON page_views(created_at);
CREATE INDEX IF NOT EXISTS idx_page_views_source ON page_views(source);
-- ============================================
-- 3. 触发器函数和触发器
-- ============================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 为需要 updated_at 的表添加触发器
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_orders_updated_at') THEN
EXECUTE 'CREATE TRIGGER update_orders_updated_at BEFORE UPDATE ON public.orders FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column()';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_user_sessions_updated_at') THEN
EXECUTE 'CREATE TRIGGER update_user_sessions_updated_at BEFORE UPDATE ON public.user_sessions FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column()';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_users_updated_at') THEN
EXECUTE 'CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column()';
END IF;
END $$;
-- ============================================
-- 4. 行级安全策略RLS
-- ============================================
-- 启用 RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE products ENABLE ROW LEVEL SECURITY;
ALTER TABLE merchants ENABLE ROW LEVEL SECURITY;
ALTER TABLE order_items ENABLE ROW LEVEL SECURITY;
ALTER TABLE page_views ENABLE ROW LEVEL SECURITY;
-- orders: 用户只能查看和管理自己的订单
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='orders' AND policyname='Users can view own orders') THEN
EXECUTE 'CREATE POLICY "Users can view own orders" ON public.orders FOR SELECT USING (auth.uid() = user_id)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='orders' AND policyname='Users can insert own orders') THEN
EXECUTE 'CREATE POLICY "Users can insert own orders" ON public.orders FOR INSERT WITH CHECK (auth.uid() = user_id)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='orders' AND policyname='Users can update own orders') THEN
EXECUTE 'CREATE POLICY "Users can update own orders" ON public.orders FOR UPDATE USING (auth.uid() = user_id)';
END IF;
END $$;
-- order_items: 用户只能查看自己订单的商品
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='order_items' AND policyname='Users can view own order items') THEN
EXECUTE 'CREATE POLICY "Users can view own order items" ON public.order_items FOR SELECT USING (EXISTS (SELECT 1 FROM public.orders WHERE public.orders.id = public.order_items.order_id AND public.orders.user_id = auth.uid()))';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='order_items' AND policyname='Users can insert own order items') THEN
EXECUTE 'CREATE POLICY "Users can insert own order items" ON public.order_items FOR INSERT WITH CHECK (EXISTS (SELECT 1 FROM public.orders WHERE public.orders.id = public.order_items.order_id AND public.orders.user_id = auth.uid()))';
END IF;
END $$;
-- user_sessions: 用户只能查看和管理自己的会话
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='user_sessions' AND policyname='Users can view own sessions') THEN
EXECUTE 'CREATE POLICY "Users can view own sessions" ON public.user_sessions FOR SELECT USING (auth.uid() = user_id)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='user_sessions' AND policyname='Users can insert own sessions') THEN
EXECUTE 'CREATE POLICY "Users can insert own sessions" ON public.user_sessions FOR INSERT WITH CHECK (auth.uid() = user_id)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='user_sessions' AND policyname='Users can update own sessions') THEN
EXECUTE 'CREATE POLICY "Users can update own sessions" ON public.user_sessions FOR UPDATE USING (auth.uid() = user_id)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='user_sessions' AND policyname='Users can delete own sessions') THEN
EXECUTE 'CREATE POLICY "Users can delete own sessions" ON public.user_sessions FOR DELETE USING (auth.uid() = user_id)';
END IF;
END $$;
-- users: 用户只能查看和管理自己的记录
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='users' AND policyname='Users can view own profile') THEN
EXECUTE 'CREATE POLICY "Users can view own profile" ON public.users FOR SELECT USING (auth.uid() = id)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='users' AND policyname='Users can insert own profile') THEN
EXECUTE 'CREATE POLICY "Users can insert own profile" ON public.users FOR INSERT WITH CHECK (auth.uid() = id)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='users' AND policyname='Users can update own profile') THEN
EXECUTE 'CREATE POLICY "Users can update own profile" ON public.users FOR UPDATE USING (auth.uid() = id)';
END IF;
END $$;
-- products: 任何人可读,认证用户可管理(简化策略)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='products' AND policyname='Anyone can view products') THEN
EXECUTE 'CREATE POLICY "Anyone can view products" ON public.products FOR SELECT USING (true)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='products' AND policyname='Authenticated can manage products') THEN
EXECUTE 'CREATE POLICY "Authenticated can manage products" ON public.products FOR ALL USING (auth.role() = ''authenticated'')';
END IF;
END $$;
-- merchants: 任何人可读,认证用户可管理(简化策略)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='merchants' AND policyname='Anyone can view merchants') THEN
EXECUTE 'CREATE POLICY "Anyone can view merchants" ON public.merchants FOR SELECT USING (true)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='merchants' AND policyname='Authenticated can manage merchants') THEN
EXECUTE 'CREATE POLICY "Authenticated can manage merchants" ON public.merchants FOR ALL USING (auth.role() = ''authenticated'')';
END IF;
END $$;
-- page_views: 任何人可插入,用户只能读自己的记录
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='page_views' AND policyname='Anyone can insert page views') THEN
EXECUTE 'CREATE POLICY "Anyone can insert page views" ON public.page_views FOR INSERT WITH CHECK (true)';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='page_views' AND policyname='Users can view own page views') THEN
EXECUTE 'CREATE POLICY "Users can view own page views" ON public.page_views FOR SELECT USING (auth.uid() = user_id)';
END IF;
END $$;