SQL Database Fundamentals and Practical Examples

Datbaase Schema Setup

The following SQL script creates a student information database with four tables: major, stu (students), cou (courses), and sc (student-course enrollments).

-- Create and use database
DROP DATABASE IF EXISTS stuinfo;
CREATE DATABASE stuinfo;
USE stuinfo;

-- Majors table
CREATE TABLE major (
    mno INT PRIMARY KEY,
    mname VARCHAR(30)
);

-- Students table
CREATE TABLE stu (
    sno VARCHAR(13) PRIMARY KEY,
    sname VARCHAR(30) NOT NULL,
    age INT,
    sex BIT,
    mno INT,
    FOREIGN KEY (mno) REFERENCES major(mno)
);

-- Courses table
CREATE TABLE cou (
    cno VARCHAR(13) PRIMARY KEY,
    cname VARCHAR(30) NOT NULL,
    ctime INT,
    ccredit DECIMAL(5,2)
);

-- Enrollments table
CREATE TABLE sc (
    cno VARCHAR(13),
    sno VARCHAR(13),
    grade DECIMAL(5,2),
    PRIMARY KEY (cno, sno),
    FOREIGN KEY (sno) REFERENCES stu(sno)
);

-- Add foreign key for course
ALTER TABLE sc 
ADD CONSTRAINT fk_sc_cno 
FOREIGN KEY (cno) REFERENCES cou(cno);

Sample Data Insertion

Example data is inserted into each table to demonstrate queries.

-- Majors
INSERT INTO major VALUES 
(1, 'Computer Science'), 
(2, 'Software Engineering'), 
(3, 'Network Engineering'), 
(4, 'Intelligent Science');

-- Students
INSERT INTO stu VALUES 
('2020001', 'Xiao Yi', 18, 0, 1),
('2020002', 'Xiao Er', 18, 1, 1),
('2020005', 'Xiao Liu', 18, 0, 2),
('2020009', 'Xiao Shi', 19, 0, 3),
('20200013', 'Xiao Yu', 19, 0, NULL),
('20200014', 'Xiao Dian', 19, 0, 4);

-- Courses
INSERT INTO cou VALUES 
('20201', 'C Language', 32, 5.0),
('20202', 'C#', 32, 3.0),
('20203', 'Data Structures', 16, 5.0),
('20204', 'College English 1', 32, 3.5);

-- Enrollments
INSERT INTO sc (sno, cno, grade) VALUES 
('2020001', '20201', 90),
('2020002', '20201', 90),
('2020004', '20201', 58),
('2020004', '20202', 98),
('2020005', '20203', 90),
('2020006', '20201', NULL);

Basic DDL and DML Operations

-- Add/drop column
ALTER TABLE stu ADD qq VARCHAR(20);
ALTER TABLE stu DROP COLUMN qq;

-- Create/drop table
CREATE TABLE temp_table (id INT);
DROP TABLE temp_table;

Single-Table Queries

-- Basic selection
SELECT sno, sname FROM stu;
SELECT sname, 2024 - age AS birth_year FROM stu;

-- Filtering
SELECT * FROM stu WHERE age BETWEEN 18 AND 19;
SELECT * FROM stu WHERE mno IN (1, 2, 4);
SELECT * FROM stu WHERE sname LIKE 'Peng%';
SELECT * FROM sc WHERE grade IS NULL;

-- Distinct values
SELECT DISTINCT sno FROM sc;

Sorting, Aggregation, and Grouping

-- Sorting
SELECT * FROM sc ORDER BY grade DESC;

-- Aggregation
SELECT COUNT(*) FROM stu;
SELECT COUNT(grade) FROM sc;  -- Ignores NULLs

-- Grouped results
SELECT cno, COUNT(sno) AS enrollment_count 
FROM sc 
GROUP BY cno;

-- Filter groups
SELECT sno, AVG(grade) AS avg_score 
FROM sc 
GROUP BY sno 
HAVING AVG(grade) >= 90;

Multi-Table Queries

-- Implicit join (Cartesian product with condition)
SELECT stu.sname, cou.cname, sc.grade
FROM stu, sc, cou
WHERE stu.sno = sc.sno AND sc.cno = cou.cno;

-- Explicit LEFT JOIN
SELECT stu.sname, sc.cno, sc.grade
FROM stu
LEFT JOIN sc ON stu.sno = sc.sno;

-- Majors with zero students
SELECT m.mno, m.mname, COUNT(s.sno) AS student_count
FROM major m
LEFT JOIN stu s ON m.mno = s.mno
GROUP BY m.mno, m.mname;

Nested and Set Queries

-- Subquery with IN
SELECT sname FROM stu 
WHERE sno IN (SELECT sno FROM sc WHERE cno = '20201');

-- Correlated subquery
SELECT sname FROM stu 
WHERE EXISTS (
    SELECT 1 FROM sc 
    WHERE sc.sno = stu.sno AND cno = '20201'
);

-- Set operations
SELECT sno FROM sc WHERE cno = '20201'
UNION
SELECT sno FROM sc WHERE cno = '20203';

Views

Views provide virtual tables based on underlying base tables.

-- Student basic info
CREATE VIEW v_student_info AS
SELECT sno, sname, age FROM stu;

-- Student with major name
CREATE VIEW v_student_major AS
SELECT s.sno, s.sname, m.mname
FROM stu s
LEFT JOIN major m ON s.mno = m.mno;

-- Average grades per student
CREATE VIEW v_student_avg AS
SELECT sno, AVG(grade) AS avg_grade
FROM sc
GROUP BY sno;

Stored Procedures

-- Parameterized procedure
CREATE PROCEDURE GetStudentCourseInfo 
    @student_id VARCHAR(13), 
    @course_id VARCHAR(13)
AS
BEGIN
    SELECT sc.*, cou.ccredit
    FROM sc
    JOIN cou ON sc.cno = cou.cno
    WHERE sc.sno = @student_id AND sc.cno = @course_id;
END;

EXEC GetStudentCourseInfo '2020004', '20203';

Triggers

-- Prevent insertion if total students exceed 17
CREATE TRIGGER trg_limit_students
ON stu
AFTER INSERT
AS
BEGIN
    IF (SELECT COUNT(*) FROM stu) > 17
    BEGIN
        ROLLBACK TRANSACTION;
        PRINT 'Maximum student limit exceeded.';
    END
END;

-- Auto-adjust borderline grades (55–59 → 60)
CREATE TRIGGER trg_adjust_grades
ON sc
INSTEAD OF INSERT
AS
BEGIN
    DECLARE @sno VARCHAR(13), @cno VARCHAR(13), @grade DECIMAL(5,2);
    SELECT @sno = sno, @cno = cno, @grade = grade FROM inserted;
    
    IF @grade BETWEEN 55 AND 59
        SET @grade = 60;
        
    INSERT INTO sc (sno, cno, grade) VALUES (@sno, @cno, @grade);
END;

User-Defined Functinos

-- Scalar function: average grade for a course
CREATE FUNCTION GetCourseAvg(@course_id VARCHAR(13))
RETURNS DECIMAL(5,2)
AS
BEGIN
    DECLARE @avg DECIMAL(5,2);
    SELECT @avg = AVG(grade) FROM sc WHERE cno = @course_id;
    RETURN @avg;
END;

-- Table-valued function: students in a major
CREATE FUNCTION GetStudentsByMajor(@major_id INT)
RETURNS TABLE
AS
RETURN (
    SELECT sno, sname FROM stu WHERE mno = @major_id
);

Indexes

Indexes improve query performance but incur maintenance overhead.

-- Unique composite index on sc
CREATE UNIQUE INDEX idx_sc_enrollment 
ON sc (sno ASC, cno DESC);

-- Avoid indexing on low-cardinality columns (e.g., sex)

Cursors

Cursors enable row-by-row processing of result sets.

-- Assign grade ranks using cursor
ALTER TABLE sc ADD sc_rank CHAR(1);

DECLARE grade_cursor CURSOR FOR 
    SELECT sno, cno, grade FROM sc;

DECLARE @s VARCHAR(13), @c VARCHAR(13), @g DECIMAL(5,2);
OPEN grade_cursor;
FETCH NEXT FROM grade_cursor INTO @s, @c, @g;

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @rank CHAR(1) = 
        CASE 
            WHEN @g >= 80 THEN 'A'
            WHEN @g >= 70 THEN 'B'
            WHEN @g IS NOT NULL THEN 'C'
            ELSE NULL
        END;
        
    UPDATE sc SET sc_rank = @rank 
    WHERE sno = @s AND cno = @c;
    
    FETCH NEXT FROM grade_cursor INTO @s, @c, @g;
END;

CLOSE grade_cursor;
DEALLOCATE grade_cursor;

Tags: sql database Structured Query Language Database Design SQL Queries

Posted on Sun, 10 May 2026 20:33:27 +0000 by jzimmerlin