+123
@@ -0,0 +1,123 @@
|
||||
-- PostgreSQL / Supabase schema for the exam result query module.
|
||||
-- Each exam is independent. Scores are stored under one exam only and do
|
||||
-- not affect any other exam.
|
||||
|
||||
create extension if not exists pgcrypto;
|
||||
|
||||
create table if not exists public.exam_exams (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
exam_code text not null unique,
|
||||
exam_name text not null,
|
||||
exam_date date,
|
||||
is_published boolean not null default true,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create table if not exists public.exam_results (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
exam_id uuid not null references public.exam_exams(id) on delete cascade,
|
||||
student_name text not null,
|
||||
admission_no text not null,
|
||||
class_name text,
|
||||
remark text,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
constraint exam_results_one_candidate_per_exam unique (exam_id, admission_no, student_name)
|
||||
);
|
||||
|
||||
create table if not exists public.exam_score_items (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
result_id uuid not null references public.exam_results(id) on delete cascade,
|
||||
item_name text not null,
|
||||
score numeric(10, 2) not null,
|
||||
full_score numeric(10, 2),
|
||||
sort_order integer not null default 0,
|
||||
created_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create index if not exists exam_results_lookup_idx
|
||||
on public.exam_results (exam_id, student_name, admission_no);
|
||||
|
||||
create unique index if not exists exam_score_items_unique_item_idx
|
||||
on public.exam_score_items (result_id, item_name);
|
||||
|
||||
create index if not exists exam_score_items_result_idx
|
||||
on public.exam_score_items (result_id, sort_order);
|
||||
|
||||
grant select on public.exam_exams to anon, authenticated;
|
||||
grant select on public.exam_results to anon, authenticated;
|
||||
grant select on public.exam_score_items to anon, authenticated;
|
||||
|
||||
alter table public.exam_exams enable row level security;
|
||||
alter table public.exam_results enable row level security;
|
||||
alter table public.exam_score_items enable row level security;
|
||||
|
||||
drop policy if exists "Public can read published exams" on public.exam_exams;
|
||||
create policy "Public can read published exams"
|
||||
on public.exam_exams
|
||||
for select
|
||||
to anon, authenticated
|
||||
using (is_published = true);
|
||||
|
||||
drop policy if exists "Public can read published exam results" on public.exam_results;
|
||||
create policy "Public can read published exam results"
|
||||
on public.exam_results
|
||||
for select
|
||||
to anon, authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1
|
||||
from public.exam_exams
|
||||
where public.exam_exams.id = exam_results.exam_id
|
||||
and public.exam_exams.is_published = true
|
||||
)
|
||||
);
|
||||
|
||||
drop policy if exists "Public can read published score items" on public.exam_score_items;
|
||||
create policy "Public can read published score items"
|
||||
on public.exam_score_items
|
||||
for select
|
||||
to anon, authenticated
|
||||
using (
|
||||
exists (
|
||||
select 1
|
||||
from public.exam_results
|
||||
join public.exam_exams on public.exam_exams.id = public.exam_results.exam_id
|
||||
where public.exam_results.id = exam_score_items.result_id
|
||||
and public.exam_exams.is_published = true
|
||||
)
|
||||
);
|
||||
|
||||
insert into public.exam_exams (exam_code, exam_name, exam_date)
|
||||
values
|
||||
('2026-spring-midterm', '2026 年春季期中考试', '2026-04-18'),
|
||||
('2026-spring-monthly-01', '2026 年春季第一次月考', '2026-03-12')
|
||||
on conflict (exam_code) do nothing;
|
||||
|
||||
with target_exam as (
|
||||
select id from public.exam_exams where exam_code = '2026-spring-midterm'
|
||||
),
|
||||
inserted_result as (
|
||||
insert into public.exam_results (exam_id, student_name, admission_no, class_name, remark)
|
||||
select id, '张三', 'EX20260001', '高一 1 班', '本场考试独立计分,实验规范扣分仅影响本场期中考试。'
|
||||
from target_exam
|
||||
on conflict (exam_id, admission_no, student_name) do update
|
||||
set class_name = excluded.class_name,
|
||||
remark = excluded.remark,
|
||||
updated_at = now()
|
||||
returning id
|
||||
)
|
||||
insert into public.exam_score_items (result_id, item_name, score, full_score, sort_order)
|
||||
select id, item_name, score, full_score, sort_order
|
||||
from inserted_result,
|
||||
(values
|
||||
('语文', 108, 150, 10),
|
||||
('数学', 126, 150, 20),
|
||||
('英语', 119, 150, 30),
|
||||
('实验规范扣分', -2, null, 40)
|
||||
) as item_rows(item_name, score, full_score, sort_order)
|
||||
on conflict (result_id, item_name) do update
|
||||
set score = excluded.score,
|
||||
full_score = excluded.full_score,
|
||||
sort_order = excluded.sort_order;
|
||||
Reference in New Issue
Block a user