认识函数 ---语法详解与实战案例(SQL Server 2019)
一、SQL Server 2019 函数简介
函数是预定义的、可重用的代码块,用于执行特定操作并返回结果。
分类:
- 标量函数 :返回单个值(如
LEN(),GETDATE())- 聚合函数 :对一组值执行计算(如
SUM(),AVG())- 窗口函数 :在结果集的"窗口"上执行计算(如
ROW_NUMBER())- 系统函数:返回服务器/数据库/对象元数据信息
二、字符串函数(String Functions)
用于处理和操作字符数据。
2.1 ASCII() 函数
返回字符表达式最左端字符的 ASCII 码值
sql
SELECT ASCII('A') AS ASCIICode; -- 返回 65
SELECT ASCII('a') AS ASCIICode; -- 返回 97
SELECT ASCII('中') AS ASCIICode; -- 返回 20013(Unicode)
2.2 CHAR() 函数
将 ASCII 码值转换为字符(0~255)
sql
SELECT CHAR(65) AS CharA; -- 'A'
SELECT CHAR(97) AS Chara; -- 'a'
SELECT CHAR(48) AS Char0; -- '0'
-- 超过255会返回NULL
SELECT CHAR(256) AS Result; -- NULL
2.3 LEFT() 函数
从字符串左侧开始,返回指定长度的字符
sql
SELECT LEFT('Hello World', 5) AS LeftPart; -- 'Hello'
SELECT LEFT('SQL Server', 3) AS LeftPart; -- 'SQL'
-- 处理中文
SELECT LEFT('数据库管理系统', 3) AS LeftPart; -- '数据库'
2.4 RIGHT() 函数
从字符串右侧开始,返回指定长度的字符
sql
SELECT RIGHT('Hello World', 5) AS RightPart; -- 'World'
SELECT RIGHT('SQL Server 2019', 4) AS RightPart; -- '2019'
SELECT RIGHT('数据库管理系统', 2) AS RightPart; -- '系统'
2.5 LTRIM() 函数
去除字符串左侧的空格
sql
SELECT LTRIM(' Hello') AS Trimmed; -- 'Hello'
SELECT LTRIM(' SQL Server ') AS Trimmed; -- 'SQL Server '(右侧空格保留)
2.6 RTRIM() 函数
去除字符串右侧的空格
sql
SELECT RTRIM('Hello ') AS Trimmed; -- 'Hello'
SELECT RTRIM(' SQL Server ') AS Trimmed; -- ' SQL Server'(左侧空格保留)
2.7 STR() 函数
将数值转换为字符型(可指定长度和小数位数)
sql
SELECT STR(123.456, 10, 2) AS StrResult; -- ' 123.46'(总长10,右对齐)
SELECT STR(123.456, 6, 1) AS StrResult; -- ' 123.5'
SELECT STR(999.999, 5, 2) AS StrResult; -- '*****'(溢出时返回星号)
2.8 REVERSE() 函数
返回字符串的逆序
sql
SELECT REVERSE('Hello') AS Reversed; -- 'olleH'
SELECT REVERSE('12345') AS Reversed; -- '54321'
SELECT REVERSE('上海自来水来自海上') AS Reversed; -- '上海来自水自来海上'(回文验证)
2.9 LEN() 函数
返回字符串的字符数(不包括尾随空格)
sql
SELECT LEN('Hello') AS Length; -- 5
SELECT LEN('Hello ') AS Length; -- 5(尾部空格不计)
SELECT LEN('数据库') AS Length; -- 3
SELECT LEN('') AS Length; -- 0
2.10 CHARINDEX() 函数(匹配子串开始位置)
返回子串在字符串中第一次出现的位置(从1开始,未找到返回0)
sql
SELECT CHARINDEX('o', 'Hello World') AS Position; -- 5
SELECT CHARINDEX('SQL', 'Microsoft SQL Server') AS Position; -- 11
SELECT CHARINDEX('x', 'Hello') AS Position; -- 0(未找到)
-- 可指定起始位置
SELECT CHARINDEX('o', 'Hello World', 6) AS Position; -- 8(从第6位开始找)
2.11 SUBSTRING() 函数
从字符串中提取子串(起始位置从1开始)
sql
SELECT SUBSTRING('Hello World', 7, 5) AS SubStr; -- 'World'
SELECT SUBSTRING('SQL Server 2019', 1, 3) AS SubStr; -- 'SQL'
SELECT SUBSTRING('数据库管理系统', 3, 2) AS SubStr; -- '管理'
2.12 LOWER() 函数
将字符串转换为小写
sql
SELECT LOWER('HELLO WORLD') AS LowerCase; -- 'hello world'
SELECT LOWER('SQL Server') AS LowerCase; -- 'sql server'
2.13 UPPER() 函数
将字符串转换为大写
sql
SELECT UPPER('hello world') AS UpperCase; -- 'HELLO WORLD'
SELECT UPPER('sql server') AS UpperCase; -- 'SQL SERVER'
2.14 REPLACE() 函数
替换字符串中的子串
sql
SELECT REPLACE('Hello World', 'World', 'SQL Server') AS Replaced; -- 'Hello SQL Server'
SELECT REPLACE('123-456-789', '-', '') AS Replaced; -- '123456789'(删除所有-)
SELECT REPLACE('abcabcabc', 'abc', 'xyz') AS Replaced; -- 'xyzxyzxyz'
三、数学函数(Mathematical Functions)
用于执行数学运算。
3.1 ABS(x) 函数
返回绝对值
sql
SELECT ABS(-10) AS Absolute; -- 10
SELECT ABS(10) AS Absolute; -- 10
SELECT ABS(-3.14) AS Absolute; -- 3.14
3.2 PI() 函数
返回圆周率 π
sql
SELECT PI() AS PiValue; -- 3.14159265358979
SELECT ROUND(PI(), 2) AS PiRounded; -- 3.14
3.3 SQRT(x) 函数
返回平方根
sql
SELECT SQRT(16) AS SquareRoot; -- 4
SELECT SQRT(2) AS SquareRoot; -- 1.4142135623731
SELECT SQRT(ABS(-25)) AS SquareRoot; -- 5(负数先取绝对值)
3.4 RAND() 和 RAND(x) 函数
返回0到1之间的随机浮点数
RAND(x):x为种子,相同种子返回相同随机数
sql
SELECT RAND() AS RandomNumber; -- 如 0.123456789
SELECT RAND(100) AS RandomWithSeed; -- 每次执行都相同(如0.715436657)
SELECT RAND(100) AS RandomWithSeedAgain; -- 同上,相同种子相同结果
-- 生成1到100的随机整数
SELECT FLOOR(RAND() * 100) + 1 AS RandomInt1To100;
3.5 ROUND(x, y) 函数
四舍五入到指定小数位
sql
SELECT ROUND(123.456, 2) AS Rounded; -- 123.460
SELECT ROUND(123.456, 1) AS Rounded; -- 123.500
SELECT ROUND(123.456, 0) AS Rounded; -- 123.000
SELECT ROUND(123.456, -1) AS Rounded; -- 120.000(对十位四舍五入)
SELECT ROUND(123.456, -2) AS Rounded; -- 100.000(对百位四舍五入)
3.6 SIGN(x) 函数
返回符号:正数=1,负数=-1,零=0
sql
SELECT SIGN(10) AS Sign; -- 1
SELECT SIGN(-5) AS Sign; -- -1
SELECT SIGN(0) AS Sign; -- 0
SELECT SIGN(-3.14) AS Sign; -- -1
3.7 CEILING(x) 和 FLOOR(x) 函数
CEILING:向上取整(天花板)
FLOOR:向下取整(地板)
sql
SELECT CEILING(3.14) AS Ceiling; -- 4
SELECT CEILING(-3.14) AS Ceiling; -- -3(注意负数)
SELECT FLOOR(3.14) AS Floor; -- 3
SELECT FLOOR(-3.14) AS Floor; -- -4(注意负数)
3.8 POWER(x, y), SQUARE(x), EXP(x) 函数
POWER:x的y次方
SQUARE:x的平方(=POWER(x,2))
EXP:e的x次方
sql
SELECT POWER(2, 3) AS PowerResult; -- 8
SELECT POWER(10, 2) AS PowerResult; -- 100
SELECT SQUARE(5) AS SquareResult; -- 25
SELECT EXP(1) AS ExpResult; -- 2.71828182845905(e^1)
SELECT EXP(2) AS ExpResult; -- 7.38905609893065(e^2)
3.9 LOG(x) 和 LOG10(x) 函数
LOG:自然对数(以e为底)
LOG10:常用对数(以10为底)
sql
SELECT LOG(EXP(1)) AS LogResult; -- 1(ln(e) = 1)
SELECT LOG(10) AS LogResult; -- 2.30258509299405
SELECT LOG10(100) AS Log10Result; -- 2
SELECT LOG10(1000) AS Log10Result; -- 3
3.10 RADIANS(x) 和 DEGREES(x) 函数
角度与弧度转换
sql
SELECT RADIANS(180) AS Radians; -- 3.14159265358979(π)
SELECT DEGREES(PI()) AS Degrees; -- 180
SELECT RADIANS(90) AS Radians; -- 1.5707963267949
SELECT DEGREES(1.5707963267949) AS Degrees; -- 90
3.11 SIN(x), ASIN(x), COS(x), ACOS(x) 函数
三角函数(参数为弧度)
sql
SELECT SIN(RADIANS(30)) AS Sin30; -- 0.5
SELECT ASIN(0.5) AS Asin05; -- 0.523598775598299(弧度)
SELECT DEGREES(ASIN(0.5)) AS Asin05Degrees; -- 30
SELECT COS(RADIANS(60)) AS Cos60; -- 0.5
SELECT ACOS(0.5) AS Acos05; -- 1.0471975511966(弧度)
SELECT DEGREES(ACOS(0.5)) AS Acos05Degrees; -- 60
3.12 TAN(x), ATAN(x), COT(x) 函数
正切、反正切、余切
sql
SELECT TAN(RADIANS(45)) AS Tan45; -- 1
SELECT ATAN(1) AS Atan1; -- 0.785398163397448(π/4弧度)
SELECT DEGREES(ATAN(1)) AS Atan1Degrees; -- 45
SELECT COT(RADIANS(45)) AS Cot45; -- 1(余切=1/正切)
四、数据类型转换函数
主要使用
CAST()和CONVERT()
4.1 CAST() 函数
sql
SELECT CAST('123' AS INT) AS IntValue; -- 123
SELECT CAST(123.45 AS VARCHAR(10)) AS StrValue; -- '123.45'
SELECT CAST(GETDATE() AS DATE) AS DateOnly; -- 2025-09-13
SELECT CAST('2025-09-13' AS DATETIME) AS DateTimeValue; -- 2025-09-13 00:00:00.000
4.2 CONVERT() 函数(更灵活,支持格式化)
sql
SELECT CONVERT(VARCHAR(10), GETDATE(), 120) AS Format1; -- '2025-09-13'
SELECT CONVERT(VARCHAR(19), GETDATE(), 120) AS Format2; -- '2025-09-13 20:56:00'
SELECT CONVERT(VARCHAR(8), GETDATE(), 108) AS TimeOnly; -- '20:56:00'
SELECT CONVERT(DECIMAL(10,2), '123.456') AS DecimalValue; -- 123.46
五、文本函数和图像函数(TEXT/IMAGE 类型已过时,建议用 VARCHAR(MAX)/VARBINARY(MAX))
SQL Server 2005+ 已推荐使用
VARCHAR(MAX),NVARCHAR(MAX),VARBINARY(MAX)但为兼容性仍支持以下函数:
5.1 TEXTPTR() 函数
返回指向
text,ntext,image列的指针(二进制值)
sql
-- 创建含TEXT列的表(仅演示,实际不推荐)
CREATE TABLE OldTable (
ID INT PRIMARY KEY,
Content TEXT
);
GO
INSERT INTO OldTable VALUES (1, 'This is a long text content...');
GO
-- 获取文本指针
SELECT TEXTPTR(Content) AS TextPointer FROM OldTable WHERE ID = 1;
-- 返回如:0x0000000000000700000000000000...
GO
DROP TABLE OldTable;
5.2 TEXTVALID() 函数
检查文本指针是否有效
sql
-- 假设有表和数据
-- SELECT TEXTVALID('OldTable.Content', TEXTPTR(Content)) AS IsValid FROM OldTable;
-- 返回1表示有效,0表示无效
💡 现代替代方案 :直接操作
VARCHAR(MAX),无需指针。
六、日期和时间函数(Date and Time Functions)
6.1 GETDATE() 函数
返回当前系统日期和时间(datetime类型)
sql
SELECT GETDATE() AS CurrentDateTime; -- 2025-09-13 20:56:00.123
6.2 GETUTCDATE() 函数
返回当前UTC(协调世界时)日期和时间
sql
SELECT GETUTCDATE() AS UTCDateTime; -- 如:2025-09-13 12:56:00.123(UTC时间)
6.3 DAY(d), MONTH(d), YEAR(d) 函数
提取日期中的天、月、年
sql
DECLARE @Date DATE = '2025-09-13';
SELECT
DAY(@Date) AS DayPart, -- 13
MONTH(@Date) AS MonthPart, -- 9
YEAR(@Date) AS YearPart; -- 2025
6.4 DATENAME(dp, d) 函数
返回日期指定部分的字符串值
sql
SELECT DATENAME(YEAR, GETDATE()) AS YearName; -- '2025'
SELECT DATENAME(MONTH, GETDATE()) AS MonthName; -- 'September'
SELECT DATENAME(DAY, GETDATE()) AS DayName; -- '13'
SELECT DATENAME(WEEKDAY, GETDATE()) AS WeekdayName; -- 'Saturday'
SELECT DATENAME(QUARTER, GETDATE()) AS QuarterName; -- '3'
6.5 DATEPART(dp, d) 函数
返回日期指定部分的整数值
sql
SELECT DATEPART(YEAR, GETDATE()) AS YearPart; -- 2025
SELECT DATEPART(MONTH, GETDATE()) AS MonthPart; -- 9
SELECT DATEPART(DAY, GETDATE()) AS DayPart; -- 13
SELECT DATEPART(WEEKDAY, GETDATE()) AS WeekdayPart; -- 7(周日=1,周六=7)
SELECT DATEPART(WEEK, GETDATE()) AS WeekOfYear; -- 当年第几周
6.6 DATEADD(dp, num, d) 函数
在日期上增加指定时间间隔
sql
SELECT DATEADD(DAY, 7, GETDATE()) AS NextWeek; -- 7天后
SELECT DATEADD(MONTH, -1, GETDATE()) AS LastMonth; -- 1个月前
SELECT DATEADD(YEAR, 1, GETDATE()) AS NextYear; -- 1年后
SELECT DATEADD(HOUR, 2, GETDATE()) AS TwoHoursLater; -- 2小时后
七、系统函数(System Functions)
返回数据库、服务器、对象等元数据信息。
7.1 COL_LENGTH() ------ 返回表中指定字段的长度值
sql
-- 假设存在Students表
SELECT COL_LENGTH('Students', 'Name') AS NameLength; -- 如:100(NVARCHAR(50)占100字节)
SELECT COL_LENGTH('Students', 'StudentNo') AS StudentNoLength; -- 10(CHAR(10))
7.2 COL_NAME() ------ 返回表中指定字段的名称
sql
-- 需要表ID和列ID
DECLARE @TableID INT = OBJECT_ID('Students');
SELECT
COL_NAME(@TableID, 1) AS Column1, -- 第1列名
COL_NAME(@TableID, 2) AS Column2; -- 第2列名
7.3 DATALENGTH() ------ 返回数据表达式的实际字节长度
sql
SELECT DATALENGTH('Hello') AS Len1; -- 5(VARCHAR)
SELECT DATALENGTH(N'Hello') AS Len2; -- 10(NVARCHAR,每个字符2字节)
SELECT DATALENGTH('数据库') AS Len3; -- 6(VARCHAR,假设中文占3字节)
SELECT DATALENGTH(N'数据库') AS Len4; -- 6(NVARCHAR,3字符×2字节=6)
7.4 DB_ID() 和 DB_NAME() ------ 数据库编号和名称
sql
SELECT DB_ID() AS CurrentDBID; -- 当前数据库ID
SELECT DB_ID('master') AS MasterDBID; -- master数据库ID
SELECT DB_NAME() AS CurrentDBName; -- 当前数据库名
SELECT DB_NAME(1) AS DBName; -- ID=1的数据库名(通常是master)
7.5 GETANSINULL() ------ 返回当前数据库默认的NULL值处理
sql
SELECT GETANSINULL() AS AnsiNullDefault; -- 1表示启用ANSI NULL默认值
7.6 @@SERVICENAME ------ 返回服务器实例名
sql
SELECT @@SERVICENAME AS ServerInstanceName; -- 如:MSSQLSERVER 或 SQLEXPRESS
7.7 @@SERVERNAME ------ 返回服务器计算机名称
sql
SELECT @@SERVERNAME AS ServerComputerName; -- 如:DESKTOP-XXXXX
7.8 OBJECT_ID() ------ 返回数据库对象的编号
sql
SELECT OBJECT_ID('Students') AS StudentsTableID;
SELECT OBJECT_ID('vw_StudentClass') AS ViewID;
7.9 SUSER_SID() ------ 返回用户的SID(安全标识号)
sql
SELECT SUSER_SID() AS CurrentUserSID; -- 当前登录用户的SID
SELECT SUSER_SID('sa') AS SASID; -- sa用户的SID
7.10 SUSER_NAME() ------ 返回用户的登录名
sql
SELECT SUSER_NAME() AS CurrentLoginName; -- 当前登录名
SELECT SUSER_NAME(0x01) AS LoginName; -- 根据SID获取登录名
7.11 OBJECT_NAME() ------ 返回数据库对象的名称
sql
SELECT OBJECT_NAME(OBJECT_ID('Students')) AS TableName; -- 'Students'
7.12 USER_ID() 和 USER_NAME() ------ 数据库用户的ID和名称
sql
SELECT USER_ID() AS CurrentUserID; -- 当前数据库用户ID
SELECT USER_ID('dbo') AS DBOUserID; -- dbo用户ID
SELECT USER_NAME() AS CurrentUserName; -- 当前数据库用户名
SELECT USER_NAME(1) AS UserName; -- ID=1的用户名(通常是dbo)
八、窗口函数(Window Functions)
在结果集的"窗口"(分区)上执行计算,不减少行数。
8.1 ROW_NUMBER() ------ 行号
sql
SELECT
Name,
ClassID,
ROW_NUMBER() OVER (ORDER BY Name) AS RowNum
FROM Students;
8.2 RANK() 和 DENSE_RANK() ------ 排名
sql
-- 假设有成绩表
CREATE TABLE Scores (
StudentName NVARCHAR(50),
Score INT
);
INSERT INTO Scores VALUES
('张三', 95), ('李四', 90), ('王五', 95), ('赵六', 85);
SELECT
StudentName,
Score,
RANK() OVER (ORDER BY Score DESC) AS Rank, -- 1,2,2,4(跳过重复名次)
DENSE_RANK() OVER (ORDER BY Score DESC) AS DenseRank -- 1,2,2,3(不跳过)
FROM Scores;
8.3 NTILE() ------ 分组排名
sql
SELECT
StudentName,
Score,
NTILE(3) OVER (ORDER BY Score DESC) AS Tier -- 分成3组
FROM Scores;
8.4 LEAD() 和 LAG() ------ 前后行值
sql
SELECT
StudentName,
Score,
LAG(Score, 1, 0) OVER (ORDER BY Score DESC) AS PrevScore, -- 前一行分数
LEAD(Score, 1, 0) OVER (ORDER BY Score DESC) AS NextScore -- 后一行分数
FROM Scores;
8.5 SUM() OVER() ------ 累计求和
sql
SELECT
StudentName,
Score,
SUM(Score) OVER (ORDER BY Score DESC ROWS UNBOUNDED PRECEDING) AS RunningTotal
FROM Scores;
九、综合性实战案例
🎯 案例19:学生数据清洗与标准化脚本
sql
USE SchoolManagement;
GO
-- 创建示例数据(含脏数据)
IF OBJECT_ID('RawStudents', 'U') IS NOT NULL DROP TABLE RawStudents;
CREATE TABLE RawStudents (
RawID INT IDENTITY(1,1),
RawName NVARCHAR(100),
RawGender NVARCHAR(10),
RawBirthDate NVARCHAR(20),
RawClass NVARCHAR(50),
RawEmail NVARCHAR(100)
);
GO
INSERT INTO RawStudents VALUES
(' 张三 ', '男', '2007-03-15', '高三(1)班', ' zhangsan@school.com '),
('Lisi', 'Female', '2008/07/22', '高二(2)班', 'lisi@school.com'),
('王五 ', 'M', '07-15-2006', '高一(3)班', 'wangwu@'),
(' 赵六 ', '未知', '2007-12-32', '高三(1)班', 'zhaoliu@school.com'), -- 无效日期
('QianQi', 'F', '2008-02-29', '高二(2)班', 'qianqi@school.com'); -- 闰年有效
GO
-- ========== 数据清洗脚本 ==========
PRINT '📊 原始数据:';
SELECT * FROM RawStudents;
GO
-- 清洗后的学生表
IF OBJECT_ID('CleanStudents', 'U') IS NOT NULL DROP TABLE CleanStudents;
CREATE TABLE CleanStudents (
StudentID INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(50) NOT NULL,
Gender CHAR(1) CHECK (Gender IN ('M','F')),
BirthDate DATE,
ClassName NVARCHAR(50),
Email NVARCHAR(100),
CleanStatus NVARCHAR(50) -- 清洗状态
);
GO
-- 插入清洗后数据
INSERT INTO CleanStudents (Name, Gender, BirthDate, ClassName, Email, CleanStatus)
SELECT
-- 清洗姓名:去空格,取前50字符
LEFT(LTRIM(RTRIM(RawName)), 50) AS Name,
-- 清洗性别:映射中文和英文
CASE
WHEN LOWER(LTRIM(RTRIM(RawGender))) IN ('男', 'm', 'male') THEN 'M'
WHEN LOWER(LTRIM(RTRIM(RawGender))) IN ('女', 'f', 'female') THEN 'F'
ELSE 'U' -- 未知
END AS Gender,
-- 清洗日期:尝试多种格式转换
CASE
WHEN ISDATE(RawBirthDate) = 1 THEN CONVERT(DATE, RawBirthDate)
WHEN ISDATE(REPLACE(RawBirthDate, '/', '-')) = 1 THEN CONVERT(DATE, REPLACE(RawBirthDate, '/', '-'))
ELSE NULL -- 无效日期设为NULL
END AS BirthDate,
-- 班级:去空格
LTRIM(RTRIM(RawClass)) AS ClassName,
-- 邮箱:去空格,验证格式
CASE
WHEN LTRIM(RTRIM(RawEmail)) LIKE '%@%.%' THEN LTRIM(RTRIM(RawEmail))
ELSE NULL
END AS Email,
-- 清洗状态
CASE
WHEN LTRIM(RTRIM(RawName)) = '' OR LTRIM(RTRIM(RawName)) IS NULL THEN '姓名为空'
WHEN CASE
WHEN LOWER(LTRIM(RTRIM(RawGender))) IN ('男', 'm', 'male', '女', 'f', 'female') THEN 1
ELSE 0
END = 0 THEN '性别无效'
WHEN ISDATE(RawBirthDate) = 0 AND ISDATE(REPLACE(RawBirthDate, '/', '-')) = 0 THEN '日期无效'
WHEN LTRIM(RTRIM(RawEmail)) NOT LIKE '%@%.%' THEN '邮箱格式无效'
ELSE '清洗成功'
END AS CleanStatus
FROM RawStudents;
GO
PRINT '✅ 数据清洗完成!';
PRINT '📋 清洗后数据:';
SELECT * FROM CleanStudents;
GO
-- 统计清洗结果
SELECT
CleanStatus,
COUNT(*) AS RecordCount
FROM CleanStudents
GROUP BY CleanStatus;
GO
🎯 案例20:学生年龄分布报表(综合日期、数学、字符串函数)
sql
USE SchoolManagement;
GO
-- 生成年龄分布报表
SELECT
-- 年龄分组
CASE
WHEN Age < 16 THEN '15岁以下'
WHEN Age BETWEEN 16 AND 18 THEN '16-18岁'
WHEN Age BETWEEN 19 AND 22 THEN '19-22岁'
ELSE '23岁以上'
END AS AgeGroup,
COUNT(*) AS StudentCount,
MIN(Age) AS MinAge,
MAX(Age) AS MaxAge,
AVG(Age * 1.0) AS AvgAge, -- *1.0转为小数
-- 用REPLICATE生成简单图表
REPLICATE('■', COUNT(*) * 2) AS Chart,
-- 百分比
CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS DECIMAL(5,2)) AS Percentage
FROM (
SELECT
DATEDIFF(YEAR, BirthDate, GETDATE()) -
CASE
WHEN MONTH(BirthDate) > MONTH(GETDATE()) OR
(MONTH(BirthDate) = MONTH(GETDATE()) AND DAY(BirthDate) > DAY(GETDATE()))
THEN 1
ELSE 0
END AS Age -- 精确年龄计算
FROM Students
WHERE Status = 'A' AND BirthDate IS NOT NULL
) AS AgeData
GROUP BY
CASE
WHEN Age < 16 THEN '15岁以下'
WHEN Age BETWEEN 16 AND 18 THEN '16-18岁'
WHEN Age BETWEEN 19 AND 22 THEN '19-22岁'
ELSE '23岁以上'
END
ORDER BY MIN(Age);
GO
🎯 案例21:系统信息监控报表
sql
-- 生成系统信息报告
SELECT
'服务器信息' AS Category,
@@SERVERNAME AS ItemName,
'服务器名称' AS Description
UNION ALL
SELECT '服务器信息', @@SERVICENAME, '服务实例名'
UNION ALL
SELECT '数据库信息', DB_NAME(), '当前数据库'
UNION ALL
SELECT '数据库信息', CAST(DB_ID() AS VARCHAR), '当前数据库ID'
UNION ALL
SELECT '用户信息', SUSER_NAME(), '当前登录名'
UNION ALL
SELECT '用户信息', USER_NAME(), '当前数据库用户名'
UNION ALL
SELECT '系统日期', CONVERT(VARCHAR, GETDATE(), 120), '当前系统时间'
UNION ALL
SELECT '系统日期', CONVERT(VARCHAR, GETUTCDATE(), 120), 'UTC时间'
UNION ALL
SELECT '版本信息', @@VERSION, 'SQL Server版本'
UNION ALL
SELECT '进程ID', CAST(@@SPID AS VARCHAR), '当前会话ID'
ORDER BY Category, ItemName;
GO
✅ 本章核心函数速查表
| 类别 | 函数 | 用途 |
|---|---|---|
| 字符串 | LEFT, RIGHT, LEN, SUBSTRING, REPLACE, UPPER, LOWER |
字符串截取、长度、替换、大小写转换 |
| 数学 | ROUND, RAND, CEILING, FLOOR, POWER, SQRT |
数值计算、随机数、取整、幂运算 |
| 日期 | GETDATE, DATEADD, DATEDIFF, YEAR, MONTH, DAY |
日期获取、计算、提取部分 |
| 系统 | DB_NAME, USER_NAME, OBJECT_ID, @@SERVERNAME |
获取数据库、用户、对象、服务器信息 |
| 转换 | CAST, CONVERT |
数据类型转换 |
| 窗口 | ROW_NUMBER, RANK, SUM() OVER() |
分区计算、排名、累计 |
📌 学习建议:
- 多练习组合使用函数(如
LEFT(LTRIM(RTRIM(...)))) - 注意函数的参数类型和返回类型
- 使用
ISNULL()或COALESCE()处理NULL值 - 日期函数注意时区和格式问题
- 窗口函数是高级分析利器,务必掌握
- 系统函数在运维和监控脚本中非常有用
📘 本章是SQL Server函数的百科全书,掌握后可轻松应对各种数据处理需求!