Kim Torgersen


Validera Personnummer

article feature image


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