好的,我相信这就是您所追求的。
首先,这使用了一个表值函数,它比标量或多语句表值函数快得多。
其次,表变量或临时表没有用处,只是一些很好的奇怪字符串操作、一点数学和 CTE。绝对没有昂贵的WHILE
循环。
我已经针对链接中的示例对此进行了测试,它们都返回了预期值。
USE Sandbox;
GO
CREATE FUNCTION ValidateHealthNumber (@HealthNumber varchar(10))
RETURNS TABLE
AS
RETURN
WITH Doubles AS(
SELECT CONVERT(tinyint,SUBSTRING(V.HN,O.P,1)) AS HNDigit,
CONVERT(tinyint,SUBSTRING(V.HN,O.P,1)) * CASE WHEN O.P % 2 = 0 THEN 1 ELSE 2 END ToAdd
FROM (VALUES(@HealthNumber)) V(HN)
CROSS APPLY (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9)) O(P)),
Parts AS (
SELECT CONVERT(tinyint,SUBSTRING(CONVERT(varchar(2),ToAdd),1,1)) AS FirstDigit, --We know that the highest value can be 18 (2*9)
CONVERT(tinyint,SUBSTRING(CONVERT(varchar(2),ToAdd),2,1)) AS SecondDigit --so no need for more than 2 digits.
FROM Doubles)
SELECT CASE RIGHT(@HealthNumber, 1) WHEN 10 - RIGHT(SUM(FirstDigit + SecondDigit),1) THEN 1 ELSE 0 END AS IsValid
FROM Parts;
GO
CREATE TABLE #Sample(HealthNumber varchar(10));
INSERT INTO #Sample
VALUES ('9876543217'), --Sample
('5322369835'), --Valid
('7089771195'), --Valid
('8108876957'), --Valid
('4395667779'), --Valid
('6983806917'), --Valid
('2790412845'), --not Valid
('5762696912'); --not Valid
SELECT *
FROM #Sample S
CROSS APPLY ValidateHealthNumber(HealthNumber) VHN;
GO
DROP TABLE #Sample
DROP FUNCTION ValidateHealthNumber;
如果你不明白这些,请尽管问。