Validera Personnummer
![article feature image](/posts/2022/validera-personnummer/feature.png)
Tabellvärd funktion som tar ett personnummer och svara med om det är giltigt, födelsedatum, kön.
Inline-funktion för att det ska gå snabbt att köra med t.ex. OUTER APPLY.
CREATE FUNCTION dbo.ValideraPersonnummer (@Personnummer varchar(13))
RETURNS table
AS
RETURN (
WITH P AS (
SELECT
PNR10.Personnummer10,
CASE
WHEN L.Luhn >= 10 THEN
L.Luhn - 9
ELSE
L.Luhn
END AS [Luhn]
FROM
(VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) V (Number)
OUTER APPLY (
SELECT
RIGHT(REPLACE(REPLACE(@Personnummer,
'-', ''),
' ', ''
), 10) AS [Personnummer10]
) PNR10
OUTER APPLY (
SELECT
TRY_CONVERT(INT, SUBSTRING(PNR10.Personnummer10, V.Number, 1)) AS [Digit]
) D
OUTER APPLY (
SELECT
IIF(V.Number % 2 = 1, D.Digit * 2, D.Digit) AS [Luhn]
) L
),
PNR AS (
SELECT
SUM(P.Luhn) Luhn,
P.Personnummer10,
CASE
WHEN LEN(P.Personnummer10) <> 10 THEN
CONVERT(bit, 0)
WHEN FD.Födelsedatum IS NULL THEN
CONVERT(bit, 0)
WHEN TRY_CONVERT(bigint, P.Personnummer10) IS NULL THEN
CONVERT(bit, 0)
WHEN SUM(P.Luhn) % 10 = 0 THEN
CONVERT(bit, 1)
ELSE
CONVERT(bit, 0)
END AS [Giltigt],
CASE
WHEN YEAR(FD.Födelsedatum) < 3000 THEN
FD.Födelsedatum
END AS [Födelsedatum]
FROM
P
OUTER APPLY (
SELECT
TRY_CONVERT(date, STUFF(STUFF(LEFT(@Personnummer, 8), 7, 0, '-'), 5, 0, '-')) AS [Födelsedatum]
) FD
GROUP BY
P.Personnummer10,
FD.Födelsedatum
)
SELECT
PNR.Giltigt,
CASE
WHEN Giltigt = 1 THEN
CASE
WHEN SUBSTRING(Personnummer10, 9, 1) % 2 = 0 THEN
'K'
ELSE
'M'
END
END AS [Kön],
IIF(PNR.Giltigt = 1, PNR.Födelsedatum, NULL) AS [Födelsedatum]
FROM
PNR
)
GO