【问题标题】:Character mask output data on select选择时的字符掩码输出数据
【发布时间】:2012-12-12 21:22:12
【问题描述】:

我使用的是 SQL Server 2008。

我想对查询的输出数据进行字符掩码。

这是我在进行选择时来自表格列的数据:

column1

384844033434

743423547878

111224678885

我想要这样的输出:

column1

384xxxxxx434

743xxxxxx878

111xxxxxx885

我该怎么做?

【问题讨论】:

标签: sql sql-server sql-server-2008 tsql data-masking


【解决方案1】:

您必须使用视图,并拒绝所有用户对基础表的 SELECT 访问。

你的视图看起来像

SELECT 
     SUBSTRING(x.SecurityNumber,1,3) + 
     'xxxxx' + 
     SUBSTRING(x.SecurityNumber,LEN(x.SecurityNumber) - 2, LEN(x.SecurityNumber))
     AS column1
FROM underlyingTable x

然后,您可以授予您的用户 SELECT 访问此视图的权限,并按照您描述的方式屏蔽输出。

如果您希望客户端软件能够在此表中插入或更新数据,您可以使用 INSTEAD OF INSERT 或 INSTEAD OF UPDATE 触发器来更新基表。

【讨论】:

  • 我正在使用sqlcmd for SQL Server 2008,发现偏移量不同。为了正确输出,我使用了SUBSTRING(x.SecurityNumber,1,3) + 'xxxxx' + SUBSTRING(x.SecurityNumber,LEN(x.SecurityNumber) - 2, LEN(x.SecurityNumber))
  • 谢谢@David。相应地进行了编辑。
【解决方案2】:

来自SQL Server 2016+,您可以使用Dynamic Data Masking功能。

动态数据屏蔽通过将敏感数据屏蔽给非特权用户来限制敏感数据的暴露。动态数据屏蔽通过使客户能够指定要透露多少敏感数据来帮助防止对敏感数据的未经授权的访问对应用层的影响最小。它是一种数据保护功能,可以在指定数据库字段的查询结果集中隐藏敏感数据,而数据库中的数据不会更改。动态数据屏蔽很容易与现有应用程序一起使用,因为屏蔽规则应用于查询结果。 许多应用程序可以在不修改现有查询的情况下屏蔽敏感数据。

CREATE TABLE #tab(ID INT IDENTITY(1,1), column1 VARCHAR(12));

INSERT INTO #tab(column1)
VALUES('384844033434'),('743423547878'),('111224678885');

SELECT * FROM #tab;

输出:

╔════╦══════════════╗
║ ID ║   column1    ║
╠════╬══════════════╣
║  1 ║ 384844033434 ║
║  2 ║ 743423547878 ║
║  3 ║ 111224678885 ║
╚════╩══════════════╝

ALTER TABLE #tab
ALTER COLUMN column1 VARCHAR(12) MASKED WITH (FUNCTION = 'partial(3,"xxxxxx",3)');

SELECT * FROM #tab;

输出:

╔════╦══════════════╗
║ ID ║   column1    ║
╠════╬══════════════╣
║  1 ║ 384xxxxxx434 ║
║  2 ║ 743xxxxxx878 ║
║  3 ║ 111xxxxxx885 ║
╚════╩══════════════╝

LiveDemo

【讨论】:

    【解决方案3】:

    如果你知道你的数据字段有多长,那么你可以使用另一个答案会产生的静态版本,但你总是可以创建一个函数来生成这个:

    CREATE FUNCTION MixUpCharacters
    (
        @OrigVal varchar(max)
    )
    RETURNS varchar(max)
    AS
    BEGIN
    
    DECLARE @NewVal varchar(max)
    DECLARE @OrigLen int
    DECLARE @LoopCt int
    DECLARE @Part varchar(max) = ''
    Declare @PartLength int
    
    SET @NewVal = ''
    SET @OrigLen = DATALENGTH(@OrigVal)
    SET @LoopCt = 1
    
    SET @Part = SUBSTRING(@OrigVal, 4, len(@OrigVal)-6)
    set @PartLength = LEN(@Part)
    
    WHILE @LoopCt <= @PartLength
        BEGIN
            -- Current length of possible characters
            SET @NewVal = @NewVal + 'X'
    
            -- Advance the loop
            SET @LoopCt = @LoopCt + 1
        END
    
        Return REPLACE(@OrigVal, @Part, @NewVal)
    END
    

    对于此函数,您将传入要屏蔽的值。所以你的查询是:

    declare @temp table
    (
        col1 varchar(50)
    )
    
    insert into @temp
    values ('384844033434'), ('743423547878'), ('111224678885')
    
    select dbo.MixUpCharacters(col1) col1
    from @temp
    

    SQL Fiddle with Demo

    结果是:

    |         COL1 |
    ----------------
    | 384XXXXXX434 |
    | 743XXXXXX878 |
    | 111XXXXXX885 |
    

    或者这里有一种使用递归 CTE 的方法:

    ;with data(col1) as
    (
        select '384844033434'
        union all
        select '7434235878'
        union all
        select '111224678885'
    ),
    s1 (col1,  repfull) as
    (
        select col1, 
            SUBSTRING(col1, 4, len(col1)-6) repfull
        from data
    ),
    s2 (col1, item, repfull, r) as
    (
        select col1,
            cast('x' as varchar(max)),
            right(repfull, LEN(repfull)-1),
            repfull
        from s1
        union all
        select col1,  
            'x'+ cast(item as varchar(max)),
            right(repfull, LEN(repfull)-1),
            r
        from s2
        where len(repfull) >0
    )
    select REPLACE(col1, r, item) newValue
    from
    (
        select col1, item, R,
            ROW_NUMBER() over(partition by col1 order by len(item) desc) rn
        from s2
    ) src
    where rn = 1
    

    SQL Fiddle with Demo

    【讨论】:

      【解决方案4】:

      无论是否加密,一个简单的选择查询都会返回表中的内容。

      所以,我认为您不能在数据库级别执行此操作。

      根据您的要求,您需要在应用程序中使用双向加密算法,这样您就可以在将数据加密保存到数据库之前对其进行加密,并从数据库中获取加密信息并在您的应用程序中解密。

      【讨论】:

        【解决方案5】:

        很简单的兄弟

        SELECT CONCAT (SUBSTR('Your string',1,3),LPAD(SUBSTR('Your string',-3),LENGTH('Your string')-1,'*')) RESULT FROM dual
        

        输出:

        你在搞砸

        如果是num 类型转换为char

        【讨论】:

        • 这是 Oracle SQL 吗?作者要求 T-SQL 解决方案。
        【解决方案6】:

        如果你想屏蔽你不知道字段长度的字段。你可以像这样升级 bluefeet 的代码:

        ALTER FUNCTION MixUpCharacters
        (
            @OrigVal varchar(MAX)
        )
        RETURNS varchar(MAX)
        AS
        BEGIN
        
        DECLARE @NewVal NVARCHAR(MAX)
        DECLARE @OrigLen INT
        DECLARE @LoopCt INT
        DECLARE @Part NVARCHAR(MAX) = ''
        DECLARE @PartLength INT     -- MastLength
        DECLARE @PartStartIndex INT -- MaskStartIndex
        
        SET @NewVal = ''
        SET @LoopCt = 1
        SET @OrigLen = LEN(@OrigVal)
        
        IF(@OrigLen = 1)
            BEGIN
                RETURN 'X'
            END
        IF(@OrigLen < 6)
            BEGIN
                SET @PartStartIndex = @OrigLen / 2
                SET @PartLength = @OrigLen - @PartStartIndex
                SET @Part = SUBSTRING(@OrigVal, @PartStartIndex,  @PartLength)
            END
        ELSE IF(@OrigLen < 8)
            BEGIN
                SET @PartStartIndex = 3
                SET @PartLength = @OrigLen - @PartStartIndex - 1
                SET @Part = SUBSTRING(@OrigVal, @PartStartIndex,  @PartLength)
            END
        ELSE
            BEGIN
                SET @PartStartIndex = 4
                SET @PartLength = @OrigLen - @PartStartIndex - 2
                SET @Part = SUBSTRING(@OrigVal, @PartStartIndex,  @PartLength)
            END
        
        WHILE @LoopCt <= @PartLength
            BEGIN
                -- Current length of possible characters
                SET @NewVal = @NewVal + 'X'
        
                -- Advance the loop
                SET @LoopCt = @LoopCt + 1
            END
        
            RETURN REPLACE(@OrigVal, @Part, @NewVal)
        END
        

        你可以这样测试:

        SELECT dbo.MixUpCharacters('1')
        UNION ALL
        SELECT dbo.MixUpCharacters('12')
        UNION ALL
        SELECT dbo.MixUpCharacters('123')
        UNION ALL
        SELECT dbo.MixUpCharacters('1234')
        UNION ALL
        SELECT dbo.MixUpCharacters('12345')
        UNION ALL
        SELECT dbo.MixUpCharacters('123456')
        UNION ALL
        SELECT dbo.MixUpCharacters('1234567')
        UNION ALL
        SELECT dbo.MixUpCharacters('12345678')
        UNION ALL
        SELECT dbo.MixUpCharacters('123456789')
        UNION ALL
        select dbo.MixUpCharacters('1234567890')
        UNION ALL
        select dbo.MixUpCharacters('12345678910')
        

        结果:

        X
        X2
        XX3
        1XX4
        1XXX5
        12XX56
        12XXX67
        123XX678
        123XXX789
        123XXXX890
        123XXXXX910
        

        【讨论】:

          【解决方案7】:

          这也适用于检索时屏蔽输出。

          SELECT CONCAT(SUBSTRING(column1, 1, 3),'xxxxxx',SUBSTRING(column1, 10, 3)) FROM tableName;
          

          如果值长度不固定,可以使用下面的。

          SELECT CONCAT(SUBSTRING(column1, 1, 3),'xxxxxx',SUBSTRING(column1, LEN(column1)-2, 3)) FROM tableName;
          

          【讨论】:

            【解决方案8】:
            concat('XXXXXXXXX',right(aadharno,4)) as aadharno
            

            它将掩盖 aadhar 编号,从右数第四个。

            【讨论】:

              【解决方案9】:
              concat('XXXXXXXXX',right(aadharno,4)) as aadharno
              

              它将掩盖 aadhar 号码。
              输出将类似于:XXXXXXXXX7995

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-03-12
                • 2012-11-14
                • 1970-01-01
                • 2013-10-18
                • 2015-12-13
                • 1970-01-01
                相关资源
                最近更新 更多