【发布时间】:2009-03-23 10:41:52
【问题描述】:
我有一个 MS-SQL 服务器,它跟踪许多客户端。如果生日已知,则将其存储为名为@987654321@ 的日期时间属性。现在我想要另一个属性年龄,它跟踪客户的当前年龄。由于年龄随时可能发生变化,我认为脚本可能是最好的主意。
我做的第一件事是创建一个存储过程,它计算给定生日的年龄作为日期时间。这是我想出的:
USE [MyDB]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE CalculateAge
@dayOfBirth datetime,
@age INT OUTPUT
AS
DECLARE @today datetime, @thisYearBirthDay datetime
DECLARE @years int
SET @today = GETDATE()
SET @thisYearOfBirth = DATEADD(year, @dayOfBirth, @today), @dayOfBirth)
SET @years = DATEDIFF(year, @dayOfBirth, @today) - (CASE WHEN @thisYearBirthDay > @today THEN 1 ELSE 0 END)
SET @age = @years
之后我创建了另一个脚本,它遍历所有具有非空 dayOfBirth 属性的记录,并相应地更新填充的年龄。
USE [MyDB]
GO
DECLARE @age int;
DECLARE @birth datetime;
DECLARE @id intl
DECLARE cursorQuery CURSOR FOR SELECT clientId FROM Clients WHERE dayOfBirth IS NOT NULL;
OPEN cursorQuery
FETCH NEXT FROM cursorQuery INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
SET @birth = (SELECT dayOfBirth from Kunden where clientId=@id);
EXEC dbo.CalculateAge @birth, @age OUTPUT;
UPDATE Clients SET Age = @age WHERE clientId = @id;
FETCH NEXT FROM cursorQuery INTO @id
END
CLOSE cursorQuery
DEALLOCATE cursorQuery
我会每天触发一次上面的脚本来填充年龄属性。到目前为止,这就是我所拥有的,但我觉得还有很大的改进空间。
** 谢谢宋老师 **
我最终得到了这样的结果:
CREATE TABLE Client (
ID int identity(1,1) primary key,
DOB datetime null,
AGE as (case
when DOB is null then null
else DATEDIFF(YY,DOB,GETDATE()) - CASE WHEN (MONTH(GETDATE()) = MONTH(DOB) AND DAY(DOB) > DAY(GETDATE()) OR MONTH(GETDATE()) > MONTH(DOB)) THEN 1 ELSE 0 END
end
)
)
【问题讨论】: