1. 数据库的建立、更改、删除

创建数据库

-- 基本创建
CREATE DATABASE SchoolDB;
GO

-- 带详细配置的创建
CREATE DATABASE SchoolDB
ON PRIMARY (
    NAME = 'SchoolDB_Data',
    FILENAME = 'C:\Data\SchoolDB.mdf',
    SIZE = 10MB,
    MAXSIZE = 50MB,
    FILEGROWTH = 5MB
)
LOG ON (
    NAME = 'SchoolDB_Log',
    FILENAME = 'C:\Data\SchoolDB.ldf',
    SIZE = 5MB,
    MAXSIZE = 25MB,
    FILEGROWTH = 2MB
);
GO

修改数据库

-- 修改数据库名称
ALTER DATABASE SchoolDB MODIFY NAME = UniversityDB;
GO

-- 添加数据文件
ALTER DATABASE UniversityDB
ADD FILE (
    NAME = 'UniversityDB_Data2',
    FILENAME = 'C:\Data\UniversityDB2.ndf',
    SIZE = 5MB,
    MAXSIZE = 20MB,
    FILEGROWTH = 2MB
);
GO

-- 修改文件大小
ALTER DATABASE UniversityDB
MODIFY FILE (
    NAME = 'UniversityDB_Data',
    SIZE = 15MB
);
GO

删除数据库

-- 删除数据库
DROP DATABASE UniversityDB;
GO

-- 安全删除(先检查是否存在)
IF EXISTS (SELECT name FROM sys.databases WHERE name = 'UniversityDB')
    DROP DATABASE UniversityDB;
GO

2. 表的建立、更改、删除

创建表

USE SchoolDB;
GO

CREATE TABLE Students (
    StudentID INT IDENTITY(1,1) PRIMARY KEY,
    FirstName NVARCHAR(50) NOT NULL,
    LastName NVARCHAR(50) NOT NULL,
    DateOfBirth DATE,
    Email NVARCHAR(100) UNIQUE,
    EnrollmentDate DATETIME DEFAULT GETDATE(),
    GPA DECIMAL(3,2) CHECK (GPA >= 0.0 AND GPA <= 4.0),
    DepartmentID INT,
    FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID)
);
GO

-- 带有计算列的表
CREATE TABLE OrderDetails (
    OrderDetailID INT IDENTITY(1,1) PRIMARY KEY,
    OrderID INT NOT NULL,
    ProductID INT NOT NULL,
    UnitPrice MONEY NOT NULL,
    Quantity INT NOT NULL,
    Discount DECIMAL(4,2) DEFAULT 0.00,
    TotalPrice AS (UnitPrice * Quantity * (1 - Discount)) PERSISTED
);
GO

修改表

-- 添加列
ALTER TABLE Students ADD PhoneNumber NVARCHAR(20);
GO

-- 修改列
ALTER TABLE Students ALTER COLUMN Email NVARCHAR(150);
GO

-- 删除列
ALTER TABLE Students DROP COLUMN PhoneNumber;
GO

-- 添加约束
ALTER TABLE Students ADD CONSTRAINT CHK_GPA CHECK (GPA >= 0.0 AND GPA <= 5.0);
GO

-- 添加外键约束
ALTER TABLE Students WITH CHECK ADD CONSTRAINT FK_Students_Departments 
    FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID);
GO

-- 启用/禁用约束
ALTER TABLE Students NOCHECK CONSTRAINT FK_Students_Departments; -- 禁用
ALTER TABLE Students CHECK CONSTRAINT FK_Students_Departments; -- 启用
GO

删除表

-- 删除表
DROP TABLE Students;
GO

-- 安全删除(先检查是否存在)
IF OBJECT_ID('Students', 'U') IS NOT NULL
    DROP TABLE Students;
GO

3. 数据的插入、查询、删除、更新

插入数据

-- 基本插入
INSERT INTO Students (FirstName, LastName, DateOfBirth, Email, GPA, DepartmentID)
VALUES ('张', '明', '2000-05-15', 'zhangming@example.com', 3.75, 1);
GO

-- 批量插入
INSERT INTO Students (FirstName, LastName, DateOfBirth, Email, GPA, DepartmentID)
VALUES 
    ('李', '华', '1999-08-22', 'lihua@example.com', 3.90, 2),
    ('王', '芳', '2001-03-10', 'wangfang@example.com', 3.50, 1),
    ('赵', '强', '2000-11-30', 'zhaoqiang@example.com', 3.80, 3);
GO

-- 从其他表插入
INSERT INTO StudentsArchive (StudentID, FirstName, LastName, GraduationDate)
SELECT StudentID, FirstName, LastName, GETDATE()
FROM Students
WHERE GPA > 3.8;
GO

查询数据

-- 基本查询
SELECT StudentID, FirstName, LastName, GPA
FROM Students
WHERE DepartmentID = 1 AND GPA > 3.5
ORDER BY GPA DESC;
GO

-- 聚合函数
SELECT 
    DepartmentID,
    COUNT(*) AS StudentCount,
    AVG(GPA) AS AverageGPA,
    MIN(GPA) AS MinGPA,
    MAX(GPA) AS MaxGPA
FROM Students
GROUP BY DepartmentID
HAVING COUNT(*) > 5;
GO

-- 连接查询
SELECT 
    s.StudentID, s.FirstName, s.LastName, 
    d.DepartmentName,
    c.CourseName, sc.Grade
FROM Students s
INNER JOIN Departments d ON s.DepartmentID = d.DepartmentID
INNER JOIN StudentCourses sc ON s.StudentID = sc.StudentID
INNER JOIN Courses c ON sc.CourseID = c.CourseID
WHERE d.DepartmentName = '计算机科学';
GO

-- 子查询
SELECT StudentID, FirstName, LastName, GPA
FROM Students
WHERE GPA > (SELECT AVG(GPA) FROM Students);
GO

-- 分页查询 (SQL Server 2012+)
SELECT StudentID, FirstName, LastName, GPA
FROM Students
ORDER BY StudentID
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
GO

更新数据

-- 基本更新
UPDATE Students
SET GPA = 3.95, Email = 'zhangming_new@example.com'
WHERE StudentID = 1;
GO

-- 基于连接的更新
UPDATE s
SET s.GPA = s.GPA + 0.1
FROM Students s
INNER JOIN Departments d ON s.DepartmentID = d.DepartmentID
WHERE d.DepartmentName = '计算机科学' AND s.GPA < 4.0;
GO

-- 使用子查询更新
UPDATE Students
SET GPA = (SELECT AVG(GPA) FROM Students)
WHERE StudentID IN (SELECT StudentID FROM ProbationStudents);
GO

删除数据

-- 基本删除
DELETE FROM Students
WHERE StudentID = 5;
GO

-- 带条件的删除
DELETE FROM Students
WHERE EnrollmentDate < '2018-01-01' AND GPA < 2.0;
GO

-- 基于连接的删除
DELETE s
FROM Students s
INNER JOIN Departments d ON s.DepartmentID = d.DepartmentID
WHERE d.DepartmentName = '已关闭部门';
GO

-- 截断表(删除所有数据,重置标识列)
TRUNCATE TABLE StudentLogs;
GO

4. 视图的建立、更改和删除

创建视图

-- 简单视图
CREATE VIEW ComputerScienceStudents AS
SELECT StudentID, FirstName, LastName, GPA
FROM Students
WHERE DepartmentID = (SELECT DepartmentID FROM Departments WHERE DepartmentName = '计算机科学');
GO

-- 带聚合的视图
CREATE VIEW DepartmentStatistics AS
SELECT 
    d.DepartmentName,
    COUNT(s.StudentID) AS StudentCount,
    AVG(s.GPA) AS AverageGPA,
    MAX(s.GPA) AS HighestGPA
FROM Departments d
LEFT JOIN Students s ON d.DepartmentID = s.DepartmentID
GROUP BY d.DepartmentName;
GO

-- 加密视图(防止查看定义)
CREATE VIEW EncryptedStudentView
WITH ENCRYPTION
AS
SELECT StudentID, FirstName, LastName, Email
FROM Students;
GO

修改视图

-- 修改视图定义
ALTER VIEW ComputerScienceStudents AS
SELECT 
    s.StudentID, 
    s.FirstName + ' ' + s.LastName AS FullName, 
    s.GPA,
    d.DepartmentName
FROM Students s
INNER JOIN Departments d ON s.DepartmentID = d.DepartmentID
WHERE d.DepartmentName = '计算机科学' AND s.GPA >= 3.0;
GO

删除视图

-- 删除视图
DROP VIEW ComputerScienceStudents;
GO

-- 安全删除
IF OBJECT_ID('DepartmentStatistics', 'V') IS NOT NULL
    DROP VIEW DepartmentStatistics;
GO

使用视图

-- 查询视图
SELECT * FROM DepartmentStatistics;
GO

-- 通过视图更新数据(有条件限制)
UPDATE ComputerScienceStudents
SET GPA = 4.0
WHERE StudentID = 1;
GO

5. 索引的建立、更改和删除

创建索引

-- 创建非聚集索引
CREATE INDEX IX_Students_LastName
ON Students (LastName);
GO

-- 创建复合索引
CREATE INDEX IX_Students_Name
ON Students (LastName, FirstName);
GO

-- 创建唯一索引
CREATE UNIQUE INDEX IX_Students_Email
ON Students (Email);
GO

-- 创建聚集索引(每表只能一个)
CREATE CLUSTERED INDEX IX_Students_EnrollmentDate
ON Students (EnrollmentDate DESC);
GO

-- 创建筛选索引
CREATE INDEX IX_Students_Active
ON Students (LastName, FirstName)
WHERE IsInactive = 0;
GO

-- 创建包含列的索引
CREATE INDEX IX_Students_GPA_Include
ON Students (GPA)
INCLUDE (FirstName, LastName, Email);
GO

修改索引

-- 重新生成索引(碎片整理)
ALTER INDEX IX_Students_LastName ON Students REBUILD;
GO

-- 重新组织索引
ALTER INDEX IX_Students_LastName ON Students REORGANIZE;
GO

-- 禁用索引
ALTER INDEX IX_Students_LastName ON Students DISABLE;
GO

-- 启用索引
ALTER INDEX IX_Students_LastName ON Students REBUILD;
GO

删除索引

-- 删除索引
DROP INDEX IX_Students_LastName ON Students;
GO

-- 安全删除
IF EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_Students_Email' AND object_id = OBJECT_ID('Students'))
    DROP INDEX IX_Students_Email ON Students;
GO

6. T-SQL (Transact-SQL)

变量和批处理

DECLARE @StudentCount INT;
DECLARE @AvgGPA DECIMAL(3,2);

SELECT @StudentCount = COUNT(*), @AvgGPA = AVG(GPA)
FROM Students
WHERE DepartmentID = 1;

PRINT '计算机科学系学生数量: ' + CAST(@StudentCount AS VARCHAR);
PRINT '平均GPA: ' + CAST(@AvgGPA AS VARCHAR);
GO

控制流

-- IF...ELSE
DECLARE @HighGPAStudents INT;
SELECT @HighGPAStudents = COUNT(*) FROM Students WHERE GPA > 3.8;

IF @HighGPAStudents > 10
    PRINT '优秀学生较多';
ELSE
    PRINT '需要提高学生表现';
GO

-- WHILE循环
DECLARE @Counter INT = 1;
DECLARE @TotalStudents INT;
SELECT @TotalStudents = COUNT(*) FROM Students;

WHILE @Counter <= @TotalStudents
BEGIN
    PRINT '处理学生ID: ' + CAST(@Counter AS VARCHAR);
    SET @Counter = @Counter + 1;
END
GO

-- CASE表达式
SELECT 
    StudentID,
    FirstName,
    LastName,
    GPA,
    PerformanceLevel = CASE
        WHEN GPA >= 3.8 THEN '优秀'
        WHEN GPA >= 3.5 THEN '良好'
        WHEN GPA >= 3.0 THEN '中等'
        WHEN GPA >= 2.0 THEN '及格'
        ELSE '不及格'
    END
FROM Students;
GO

事务处理

BEGIN TRY
    BEGIN TRANSACTION;
    
    -- 删除学生
    DELETE FROM Students WHERE StudentID = 100;
    
    -- 删除关联的课程注册
    DELETE FROM StudentCourses WHERE StudentID = 100;
    
    COMMIT TRANSACTION;
    PRINT '事务成功提交';
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
    PRINT '事务回滚: ' + ERROR_MESSAGE();
END CATCH
GO

-- 设置事务隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO

7. 触发器、存储过程

存储过程

-- 创建简单存储过程
CREATE PROCEDURE GetStudentsByDepartment
    @DepartmentName NVARCHAR(50)
AS
BEGIN
    SELECT s.StudentID, s.FirstName, s.LastName, s.GPA
    FROM Students s
    INNER JOIN Departments d ON s.DepartmentID = d.DepartmentID
    WHERE d.DepartmentName = @DepartmentName
    ORDER BY s.LastName, s.FirstName;
END
GO

-- 带输出参数的存储过程
CREATE PROCEDURE GetDepartmentStatistics
    @DepartmentName NVARCHAR(50),
    @StudentCount INT OUTPUT,
    @AverageGPA DECIMAL(3,2) OUTPUT
AS
BEGIN
    SELECT 
        @StudentCount = COUNT(*),
        @AverageGPA = AVG(GPA)
    FROM Students s
    INNER JOIN Departments d ON s.DepartmentID = d.DepartmentID
    WHERE d.DepartmentName = @DepartmentName;
END
GO

-- 执行存储过程
EXEC GetStudentsByDepartment @DepartmentName = '计算机科学';
GO

DECLARE @Count INT, @AvgGPA DECIMAL(3,2);
EXEC GetDepartmentStatistics '计算机科学', @Count OUTPUT, @AvgGPA OUTPUT;
PRINT '学生数量: ' + CAST(@Count AS VARCHAR) + ', 平均GPA: ' + CAST(@AvgGPA AS VARCHAR);
GO

触发器

-- 创建AFTER触发器(记录学生表更改历史)
CREATE TRIGGER trg_Students_Audit
ON Students
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    SET NOCOUNT ON;
    
    -- 插入操作
    IF EXISTS(SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted)
    BEGIN
        INSERT INTO StudentsAudit (StudentID, Action, ActionDate, ChangedBy)
        SELECT StudentID, 'INSERT', GETDATE(), SUSER_SNAME()
        FROM inserted;
    END
    
    -- 删除操作
    IF EXISTS(SELECT * FROM deleted) AND NOT EXISTS(SELECT * FROM inserted)
    BEGIN
        INSERT INTO StudentsAudit (StudentID, Action, ActionDate, ChangedBy)
        SELECT StudentID, 'DELETE', GETDATE(), SUSER_SNAME()
        FROM deleted;
    END
    
    -- 更新操作
    IF EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)
    BEGIN
        INSERT INTO StudentsAudit (StudentID, Action, ActionDate, ChangedBy)
        SELECT i.StudentID, 'UPDATE', GETDATE(), SUSER_SNAME()
        FROM inserted i
        INNER JOIN deleted d ON i.StudentID = d.StudentID;
    END
END
GO

-- 创建INSTEAD OF触发器(自定义插入逻辑)
CREATE TRIGGER trg_Students_InsteadOfInsert
ON Students
INSTEAD OF INSERT
AS
BEGIN
    SET NOCOUNT ON;
    
    INSERT INTO Students (FirstName, LastName, DateOfBirth, Email, GPA, DepartmentID, EnrollmentDate)
    SELECT 
        FirstName, 
        LastName, 
        DateOfBirth, 
        Email, 
        CASE WHEN GPA > 4.0 THEN 4.0 ELSE GPA END, -- 确保GPA不超过4.0
        DepartmentID,
        ISNULL(EnrollmentDate, GETDATE()) -- 如果未提供,使用当前日期
    FROM inserted;
END
GO

8. 数据库安全相关

用户和角色管理

-- 创建登录账户
CREATE LOGIN SchoolAdmin WITH PASSWORD = 'Str0ngP@ssw0rd!123';
GO

-- 在数据库中创建用户
USE SchoolDB;
GO
CREATE USER SchoolAdminUser FOR LOGIN SchoolAdmin;
GO

-- 创建数据库角色
CREATE ROLE StudentManager;
GO

-- 授予权限给角色
GRANT SELECT, INSERT, UPDATE ON Students TO StudentManager;
GRANT SELECT ON Departments TO StudentManager;
GO

-- 将用户添加到角色
ALTER ROLE StudentManager ADD MEMBER SchoolAdminUser;
GO

-- 撤销权限
REVOKE UPDATE ON Students FROM StudentManager;
GO

-- 拒绝特定权限
DENY DELETE ON Students TO StudentManager;
GO

行级安全性

-- 创建行级安全函数
CREATE FUNCTION fn_SecurityPredicate(@DepartmentID INT)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS AccessResult
WHERE @DepartmentID = ISNULL(SESSION_CONTEXT(N'DepartmentFilter'), @DepartmentID);
GO

-- 创建安全策略
CREATE SECURITY POLICY DepartmentFilterPolicy
ADD FILTER PREDICATE fn_SecurityPredicate(DepartmentID) ON Students
WITH (STATE = ON);
GO

-- 设置会话上下文
EXEC sp_set_session_context @key = N'DepartmentFilter', @value = 1;
GO

数据加密

-- 创建数据库主密钥
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MasterKeyP@ssw0rd!';
GO

-- 创建证书
CREATE CERTIFICATE StudentDataCertificate
WITH SUBJECT = 'Student SSN Encryption';
GO

-- 创建对称密钥
CREATE SYMMETRIC KEY StudentSSN_Key
WITH ALGORITHM = AES_256
ENCRYPTION BY CERTIFICATE StudentDataCertificate;
GO

-- 使用对称密钥加密数据
OPEN SYMMETRIC KEY StudentSSN_Key
DECRYPTION BY CERTIFICATE StudentDataCertificate;

UPDATE Students
SET SSN = EncryptByKey(Key_GUID('StudentSSN_Key'), SSN_PlainText);

CLOSE SYMMETRIC KEY StudentSSN_Key;
GO

-- 解密数据
OPEN SYMMETRIC KEY StudentSSN_Key
DECRYPTION BY CERTIFICATE StudentDataCertificate;

SELECT 
    StudentID,
    FirstName,
    LastName,
    CONVERT(NVARCHAR(11), DecryptByKey(SSN)) AS DecryptedSSN
FROM Students;

CLOSE SYMMETRIC KEY StudentSSN_Key;
GO

审计

-- 创建服务器审计
USE master;
GO
CREATE SERVER AUDIT Compliance_Audit
TO FILE (FILEPATH = 'C:\Audits\')
WITH (ON_FAILURE = SHUTDOWN);
GO

-- 启用服务器审计
ALTER SERVER AUDIT Compliance_Audit WITH (STATE = ON);
GO

-- 创建数据库审计规范
USE SchoolDB;
GO
CREATE DATABASE AUDIT SPECIFICATION StudentData_Audit
FOR SERVER AUDIT Compliance_Audit
ADD (SELECT, INSERT, UPDATE, DELETE ON Students BY PUBLIC)
WITH (STATE = ON);
GO