CREATE TABLE student_profiles ( id UUID PRIMARY KEY, owner_id UUID NOT NULL, name VARCHAR(20) NOT NULL CHECK (char_length(btrim(name)) BETWEEN 1 AND 20), grade VARCHAR(40) NOT NULL CHECK (char_length(btrim(grade)) > 0), subject VARCHAR(40) NOT NULL CHECK (char_length(btrim(subject)) > 0), academic_year SMALLINT NOT NULL CHECK (academic_year BETWEEN 2000 AND 2200), term VARCHAR(1) NOT NULL CHECK (term IN ('春', '暑', '秋', '寒')), guardian_title VARCHAR(24) NOT NULL CHECK (char_length(btrim(guardian_title)) BETWEEN 1 AND 24), start_time CHAR(5) NOT NULL, end_time CHAR(5) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX student_profiles_owner_updated_idx ON student_profiles (owner_id, updated_at DESC); CREATE INDEX student_profiles_owner_grade_subject_idx ON student_profiles (owner_id, grade, subject); CREATE TABLE student_profile_defaults ( owner_id UUID PRIMARY KEY, grade VARCHAR(40) NOT NULL CHECK (char_length(btrim(grade)) > 0), subject VARCHAR(40) NOT NULL CHECK (char_length(btrim(subject)) > 0), lesson_duration_minutes SMALLINT NOT NULL CHECK (lesson_duration_minutes BETWEEN 15 AND 360 AND lesson_duration_minutes % 15 = 0), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE feedback_records ( id UUID PRIMARY KEY, owner_id UUID NOT NULL, profile_id UUID REFERENCES student_profiles(id) ON DELETE SET NULL, feedback_date DATE NOT NULL, content TEXT NOT NULL CHECK (char_length(btrim(content)) > 0), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX feedback_records_owner_date_idx ON feedback_records (owner_id, feedback_date DESC, updated_at DESC); CREATE INDEX feedback_records_owner_profile_idx ON feedback_records (owner_id, profile_id);