Função SQL para Validar NIF

Olá,
esta semana necessitei de criar um script para validação do NIF, número de identificação fiscal, mais conhecido por número de contribuinte.

O código foi implementado em numa linguagem diferente mas achei interessante recriar o mesmo em TSQL.

Explicações mais profundas sobre esta matéria podem consultar por ex. aqui:
https://pt.m.wikipedia.org/wiki/N%C3%BAmero_de_identifica%C3%A7%C3%A3o_fiscal

Vou apenas resumir o algoritmo a implementar:

O NIF é constituído por nove dígitos, sendo os oito primeiros sequenciais e o último um dígito de controlo. Adicionalmente, o primeiro dígito do NIF não pode ser zero nem quatro.

Para ser calculado o digito de controlo:

Multiplicar 1º digito por 9, o 2.º dígito por 8, o 3.º dígito por 7, o 4.º dígito por 6, o 5.º dígito por 5, o 6.º dígito por 4, o 7.º dígito por 3 e o 8.º dígito por 2.

Seguidamente somar os resultados.

Calcular o resto da divisão do número por 11: se o resto for 0 (zero) ou 1 (um) o dígito de controlo será 0 (zero); se for outro qualquer algarismo X o dígito de controlo será o resultado da subtracção 11 – X.

Por fim, basta ver a igualdade do dígito de controlo com o último dígito do NIF. No caso de ser igual o NIF está correcto; no caso de ser diferente o NIF não é válido.

O código TSQL foi colocado como uma função. Esta é chamada com um NIF e o retorno será o próprio NIF se estiver válido ou vazio caso não o seja.
Denominei a função como [dbo].[up_check_nif] e codifica-se da seguinte forma:

/*
Função valida NIF,
2021 JG
*/

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

if OBJECT_ID('[dbo].[up_check_nif]') IS NOT NULL       drop function dbo.up_check_nif
GO

CREATE function [dbo].up_check_nif (@nif_input varchar(9))
RETURNS varchar(9)
AS
BEGIN

declare @j int = 9
declare @i int = 1
declare @total int = 0
declare @digit_control int 
declare @result varchar(9)
-- nif_pri_digito   = '1,2,3,5,6,7,8,9'

IF  LEN(@nif_input) = 9 AND @nif_input NOT LIKE '%[^0-9]%' AND LEFT(@nif_input,1) not in (0,4)      
BEGIN   

    -- SUM( primeiros 8 digitos * [9,8,7,6,5,4,3,2])
    WHILE @i < LEN(@nif_input)  
    BEGIN
         SET @total = @total + SUBSTRING(@nif_input,@i,1) * @j               
         SET @j = @j-1 
         SET @i = @i+1
    END             

    IF (@total % 11) = 0 OR (@total % 11) = 1 
         SET @digit_control = 0          
    ELSE            
         SET @digit_control = 11 - (@total % 11) 

    IF @digit_control = RIGHT(@nif_input,1)                                 
         SET @result = @nif_input   /* nif válido */        
    ELSE                    
         SET @result = ''          /* nif inválido */  
END
ELSE

        SET @result = ''           /* nif inválido */  

RETURN @result  

END

A função poderá ser chamada da seguinte forma:

select dbo.up_check_nif(‘123456789’) AS NIF_Validado

Espero que vos seja útil,

JG

2 opiniões sobre “Função SQL para Validar NIF”

  1. Obrigado, Jorge, pela partilha, muito útil esta função.
    Com base nesta função, alterei-a de modo a não usar loops e passar a usar sets.
    Desta maneira o algoritmo fica mais rápido e, eventualmente mais importante, pode-se facilmente alterar o algoritmo para ser usado diretamente nos campos do SELECT ou na cláusula WHERE, nos casos em que não for permitido criar ou usar funções.
    Obrigado!
    Cumprimentos,
    João Cristóvão

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO

    if OBJECT_ID(‘[dbo].[up_check_nif]’) IS NOT NULL drop function dbo.up_check_nif
    GO

    CREATE function [dbo].up_check_nif (@nif_input varchar(9))
    RETURNS varchar(9)
    AS
    BEGIN
    DECLARE @result varchar(9)

    SELECT @result = CASE
    WHEN len(@nif_input) 9 THEN ”
    WHEN @nif_input LIKE ‘%[^0-9]%’ THEN ”
    WHEN left(@nif_input, 1) IN (0,4) THEN ”
    WHEN SUM(N) % 11 IN (0,1) THEN
    CASE
    WHEN right(@nif_input, 1) = ‘0’ THEN @nif_input
    ELSE ”
    END
    ELSE
    CASE
    WHEN right(@nif_input, 1) = 11 – SUM(N) % 11 THEN @nif_input
    ELSE ”
    END
    END
    FROM (
    VALUES
    (9 * SUBSTRING(@nif_input, 1, 1))
    ,(8 * SUBSTRING(@nif_input, 2, 1))
    ,(7 * SUBSTRING(@nif_input, 3, 1))
    ,(6 * SUBSTRING(@nif_input, 4, 1))
    ,(5 * SUBSTRING(@nif_input, 5, 1))
    ,(4 * SUBSTRING(@nif_input, 6, 1))
    ,(3 * SUBSTRING(@nif_input, 7, 1))
    ,(2 * SUBSTRING(@nif_input, 8, 1))
    ) v(n)

    RETURN @result

    END

Deixe um comentário