首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >验证GST标识号(GSTIN)

验证GST标识号(GSTIN)
EN

Database Administration用户
提问于 2018-04-11 11:48:50
回答 3查看 7.4K关注 0票数 1

以下图片描述了商品税标识号的格式:

  • 前两位数表示根据2011年印度人口普查制定的独特的州法典。例如,“新德里州法典”为“07”,“卡纳塔克邦法典”为“29”。
  • 接下来的10个字符表示纳税人的PAN (永久帐号)。
  • 第13位表示同一纳税人的注册号码(或实体号)。
  • 在默认情况下,第14位数字是“Z”,对于所有的人来说--目前并不打算使用任何东西。
  • 第15位是校验和数字,可以是数字,也可以是字母字符。

也许我可以通过PATINDEX或Regex来执行验证?

EN

回答 3

Database Administration用户

回答已采纳

发布于 2018-04-11 12:17:00

您不需要使用PATINDEX或RegEx。

代码语言:javascript
复制
CREATE TABLE #floob
(
  GSTINColumn char(15),
  CONSTRAINT CheckGSTINColumn CHECK 
  (
    GSTINColumn  LIKE '[0-9][0-9][0-9A-Z]'
      + '[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]'
      + '[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]'
      + '[0-9A-Z][0-9]Z[0-9A-Z]'
  )
);

-- succeeds
INSERT #floob(GSTINColumn) VALUES('22AAAAA0000A1Z5');
GO
-- succeeds
INSERT #floob(GSTINColumn) VALUES('675T3E5600AZ7Z9');
GO
-- fails
INSERT #floob(GSTINColumn) VALUES('22AAAAA0000A1X5');
GO

DROP TABLE #floob;
票数 4
EN

Database Administration用户

发布于 2018-04-11 15:44:25

为了补充Aaron的完全有效的答案,您可能决定对GSTIN数字进行更深入的验证,方法是验证校验数字的正确性,这是数字中的最后一个数字。

下面的代码创建了许多函数,CHECK CONSTRAINT将使用这些函数来验证新行,以及对GSTIN编号的任何修改。

前两个函数提供包含在GSTIN编号中的ASCII字符到基-36的任意映射;即0映射到09映射到9A映射到10Z映射到35

代码语言:javascript
复制
IF OBJECT_ID(N'dbo.map_char', N'FN') IS NOT NULL
DROP FUNCTION dbo.map_char;
GO
CREATE FUNCTION dbo.map_char(@c char(1))
RETURNS int
AS
BEGIN
    DECLARE @val int;
    SET @c = UPPER(@c);
    IF ASCII(@c) >= 48 AND ASCII(@c) <= 57
        SET @val = ASCII(@c) - 48;
    IF ASCII(@c) >= 65 AND ASCII(@c) <= 90
        SET @val = (ASCII(@c) - 65) + 10;
    RETURN @val;
END
GO
IF OBJECT_ID(N'dbo.unmap_char', N'FN') IS NOT NULL
DROP FUNCTION dbo.unmap_char;
GO
CREATE FUNCTION dbo.unmap_char(@v int)
RETURNS char(1)
AS
BEGIN
    DECLARE @c char(1);
    IF @v >= 0 AND @v <=9 
        SET @c = CHAR(@v + 48);
    IF @v >= 10 AND @v <= 90
        SET @c = CHAR((@v + 65) - 10);
    RETURN @c;
END
GO

我一直无法确定印度政府是否使用同样的编码方式,但它似乎适用于所提供的价值观。

此代码使用上述dbo.map_char函数验证给定GSTIN编号中的检查数字。

代码语言:javascript
复制
CREATE FUNCTION dbo.fn_validate_gstin
(
    @inp char(15)
)
RETURNS tinyint
AS
BEGIN
    DECLARE @return tinyint;
    DECLARE @i int = LEN(@inp);
    DECLARE @factor int = 1;
    DECLARE @char char(1);
    DECLARE @codepoint int;
    DECLARE @addend int;
    DECLARE @sum int = 0;
    IF @i <> 15 /* GSTIN MUST be 15 characters to be valid */
    BEGIN
        SET @return = 0;
    END
    ELSE
    BEGIN
        WHILE @i > 0
        BEGIN
            SET @codepoint = dbo.map_char(SUBSTRING(@inp, @i, 1));
            SET @addend = @factor * @codepoint;
            SET @addend = (@addend / 36) + (@addend % 36);
            SET @sum += @addend;
            IF @factor = 2 SET @factor = 1 ELSE SET @factor = 2;
            SET @i -= 1;
        END
    END
    DECLARE @remainder int = @sum % 36;
    IF @remainder = 0 SET @return = 1 ELSE SET @return = 0;
    RETURN @return;
END
GO

注意,在这段代码中绝对没有错误检查;我把它作为一个练习留给读者。如果GSTIN包含一个有效的检查数字作为最后一个数字,则该函数返回1。如果检查数字无效,则返回0。

在这里,我创建一个实现dbo.fn_validate_gstin函数的表:

代码语言:javascript
复制
CREATE TABLE dbo.t
(
    i char(15) NOT NULL
        CONSTRAINT CK_t_valid_gstin
        CHECK (dbo.fn_validate_gstin(i) = 1)
);

在这里我们插入了几个“测试”GSTIN号码:

代码语言:javascript
复制
INSERT INTO dbo.t (i) VALUES ('123456789012345');
INSERT INTO dbo.t (i) VALUES ('27AAFFM5744C1ZE');
INSERT INTO dbo.t (i) VALUES ('27AAACE7932L1ZC');

第一个插入失败。第二和第三插入成功。试图插入无效的GSTIN编号会导致以下错误:

Msg 547,级别16,状态0,第80行 INSERT语句与CHECK约束"CK_t_valid_gstin".冲突在数据库“.”、表"dbo.t“、列'i‘中发生冲突。

注意,标量函数作为约束防止使用并行性进行查询的一部分存在。这对您的系统可能有问题,也可能没有问题。如果需要并行性,可以考虑使用表上的INSTEAD OF触发器在insert或update时检查GSTIN号。例如:

代码语言:javascript
复制
IF OBJECT_ID(N'dbo.t_with_trigger', N'U') IS NOT NULL
DROP TABLE dbo.t_with_trigger;
GO
CREATE TABLE dbo.t_with_trigger
(
    i char(15) NOT NULL
);

GO
CREATE TRIGGER t_validate
ON dbo.t_with_trigger
INSTEAD OF INSERT, UPDATE
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRANSACTION
    DECLARE @bOk bit = 1;
    IF EXISTS (
        SELECT TOP(1) 1
        FROM inserted i
        WHERE dbo.fn_validate_gstin(i.i) = 0
        UNION ALL
        SELECT TOP(1) 1
        FROM deleted d
        WHERE dbo.fn_validate_gstin(d.i) = 0
        )
    BEGIN
        SET @bOk = 0; 
    END
    IF @bOk = 1 
    BEGIN
        DELETE
        FROM dbo.t_with_trigger
        FROM dbo.t_with_trigger t
            INNER JOIN deleted d ON t.i = d.i;
        INSERT INTO dbo.t_with_trigger(i)
        SELECT i.i
        FROM inserted i;
        COMMIT TRANSACTION;
    END
    ELSE
    BEGIN
        ROLLBACK TRANSACTION;
        DECLARE @msg varchar(1000);
        SET @msg = 'Attempted to insert/update using an invalid GSTIN number.';
        RAISERROR (@msg, 14, 1);
    END
END
GO

插入无效的GSTIN号码:

代码语言:javascript
复制
INSERT INTO dbo.t_with_trigger (i) 
VALUES ('123456789012345')
    , ('27AAFFM5744C1ZE')
    , ('27AAACE7932L1ZC');

导致此错误:

Msg 50000、级别14、状态1、过程t_validate、第37行批处理起始线129 试图使用无效的GSTIN number. Msg 3609、级别16、状态1、130 插入/更新事务,事务在触发器中结束。批处理已被中止。

我的实现基于卢恩算法

票数 5
EN

Database Administration用户

发布于 2022-04-15 07:32:45

为了检查GST号,您需要让它们保存DB。一旦在DB中可用,您就可以使用下面的代码在gst中通过select语句来设置pan、gst和pan。请记住,pan_in_gst是gst的子字符串,即SUBSTRING(table.field_name(gst),3,10)。

代码语言:javascript
复制
DECLARE @pan VARCHAR(10)
DECLARE @gst VARCHAR(15)
DECLARE @pan_in_gst VARCHAR(10)
DECLARE @v VARCHAR(5)


SET @pan = 'CABPG8363J'
SET @gst = '22CABPG8363J1Z1'
SET @pan_in_gst = 'CABPG8363A'

SET @v = CASE WHEN @pan = @pan_in_gst
THEN  'Yes'
ELSE 'No'
END

SELECT @pan AS 'Pan' , @gst AS 'GST', @pan_in_gst AS 'Pan IN GST', @v AS 'validation'
票数 -1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/203612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档