0

假设我在 SQL Server 表中有一个列,其中包含以下条目:

+----+-----+
| ids| col1|
+----+-----+
|4   | a   |
|4   | b   |
|4   | a   |
|4   | b   |
|5   | a   |
+----+-----+

ids鉴于col1 = a. _ 但是,我还想保持ids掩码的唯一性,因此结果如下所示:

+----+-----+
| ids| col1|
+----+-----+
|XX  | a   |
|4   | b   |
|XX  | a   |
|4   | b   |
|YY  | a   |
+----+-----+

我使用了一个案例......当使用 SHA2_256 算法来保持唯一性时,如本文所述: 如何在视图中屏蔽/加密数据但保持值的唯一性?

,但随后生成的掩码是看起来机器无法读取的“中文外观”字符。有没有更好的办法?

4

5 回答 5

1

数字会好吗?

首先,创建并填充示例表(在以后的问题中保存我们这一步)

DECLARE @T AS TABLE
(
    ids int, 
    col1 char(1)
)

INSERT INTO @T VALUES
(4, 'a'),
(4, 'b'),
(4, 'a'),
(4, 'b'),
(5, 'a')

查询:

SELECT  CASE WHEN col1 = 'a' THEN CHECKSUM(CAST(Ids as varchar(11))) ELSE ids END As ids, 
        col1
FROM @T

结果:

ids     col1
136     a
4       b
136     a
4       b
137     a
于 2018-10-23T09:08:48.827 回答
0

您也可以通过整数隐藏 ID(不知道在您的情况下是否足够安全)

CREATE TABLE #t (ids int, col1 char(1));
INSERT INTO #t VALUES
(4, 'a'),
(4, 'b'),
(4, 'a'),
(4, 'b'),
(5, 'a');

询问

SELECT ISNULL(t2.num, t1.ids) AS ids, t1.col1
FROM 
    #t t1 LEFT JOIN 
    (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY ids, col1) + (SELECT MAX(ids) FROM #t) AS num, 
        ids, col1 
    FROM #t 
    WHERE col1 = 'a' 
    GROUP BY ids, col1) t2 
        ON t1.ids = t2.ids AND t1.col1 = t2.col1;

结果

ids                  col1
-------------------- ----
6                    a
4                    b
6                    a
4                    b
7                    a
于 2018-10-23T10:36:34.533 回答
0

XX您建议的和的掩码输出值YY可能具有误导性,因为如果您id的表中有数百万个值,那么两个字母将无法唯一/随机覆盖所有数据。这里的一个选项可能是用于NEWID()为每个id组生成唯一的 UUID:

WITH cte AS (
    SELECT DISTINCT id, NEWID() AS mask
    FROM yourTable
)

SELECT t2.mask, t1.col
FROM yourTable t1
INNER JOIN cte t2
    ON t1.id = t2.id;

如果您不想显示整个 UUID,因为它太长,那么您可以改为显示它的子字符串,例如仅显示前 5 个字符:

SELECT LEFT(t2.mask, 5) AS mask, t1.col
FROM yourTable t1
INNER JOIN cte t2
    ON t1.id = t2.id;

但请记住,显示的 UUID 越短,id使用相同掩码呈现两个不同组的可能性就越大。

于 2018-10-23T09:18:18.037 回答
0

试试这个查询(用你的实际表名替换#test),在未来的情况下,除了'a'之外,你还需要包含其他字符。

下面的列表表将帮助您。

create table #list
(
col1 varchar(1)

)

insert into #list values ('a')

 select case when isnull(b.col1,'0')<>'0' then a.col1+cast ( Dense_rank() OVER(PARTITION BY a.col1 ORDER BY a.col1 ASC) as varchar(max)) else cast(a.ids as varchar(max)) end as ids, 
a.col1  from #test a
left join #list b
on a.col1 =b.col1

输出

在此处输入图像描述

于 2018-10-23T09:08:15.930 回答
0

所以这就是我最终做的。使用@Zohar Peled 提供的示例,但将ids列调整为 varchar,我们可以制作如下表格:

DECLARE @T AS TABLE
(
    ids varchar(150), 
    col1 char(1)
)

INSERT INTO @T VALUES
(4, 'a'),
(4, 'b'),
(4, 'a'),
(4, 'b'),
(5, 'a')

然后执行以下操作:

SELECT  CASE WHEN col1 = 'a' THEN CONVERT(VARCHAR(150),HashBytes('SHA2_256', ids),2) ELSE ids END As ids,
col1
FROM @T

我相信,这更类似于链接中的初始解决方案。

于 2018-10-23T10:14:00.913 回答