使用唯一随机值更新sql表中的所有行,而不使用c#中的主键或唯一键

Posted

技术标签:

【中文标题】使用唯一随机值更新sql表中的所有行,而不使用c#中的主键或唯一键【英文标题】:Update all rows in sql table with unique random value without using primary key or unique key in c# 【发布时间】:2022-01-02 19:06:27 【问题描述】:

在我的应用程序中,我获取数据库中的所有表。 用户将选择要屏蔽的表名和列名。

现在我想用随机生成的字符串更新 sql 表列,每行必须是唯一的,而不使用主键或唯一键。

例如,在我的 Employeedb 中,我有一个表 Employee。 在 Employee 表中的列中,我想屏蔽 name 和 city 列中的数据。 如果表包含 1000 行,我想更改名称和城市列,每个列有 1000 个唯一值。这意味着我想逐行更新。

姓名地址城市 Raghav flatno34 孟买 Ranveer flatno23 钦奈

这是原始数据

名称地址城市 Sbgha flatno34 mmjgujj Lkhhvh flatno23 呵呵

这是预料之中的

表有时有主键。可能没有主键。

我还有一个 qn,我在数据表中有这个预期的输出。由于我无法预定义表名和字段数,我将如何编写更新 qry。

【问题讨论】:

有些表没有主键,还是你不知道有?如果两者都不是,您将如何更新保留外键约束?如果将 CountryCode 列从“IN”更改为“XY”会怎样?您可以通过在 WHERE 子句中包含所有列来更新没有主键的记录,但这不能保证唯一。你为什么要自己编写代码?有一些工具可用于数据清理/匿名化。 我想更改名称和城市列,每个列有 1000 个唯一值你确定吗?您的目标不应该是混淆,以便您更改的值仍然以与原始值相同的方式在统计上分布吗?由于您只讨论字符串,您将如何处理其他数据类型,如日期和整数?您是否考虑过参与约束的列?小心你的假设。 【参考方案1】:

我想您会发现我的题为 How to pre-populate a random strings pool 的博文对这个要求很有帮助。 (受 Martin Smith 的 this SO answer 启发,在应得的地方给予表扬) 它描述了一个内联表值用户定义函数,该函数生成一个随机值表,您可以使用它来更新数据。

但是,它不保证这些值的唯一性。为此,您必须在从中选择时使用DISTINCT。 因此,您可能遇到的一个问题是结果的值少于您生成的值,但是对于您在问题中所写的每个表的 1,000 条记录,这可能不会成为问题,因为该函数每个最多可以生成 1,000,000 条记录你叫它的时间。

为了完整起见,我也会在此处发布代码,但您可能应该阅读我博客上的帖子。 此外,在另一篇名为 A more controllable random string generator function for SQL Server 的博客文章中还有另一个版本的此函数 - 它可以让您更好地控制随机字符串的内容 - 即仅包含数字或仅包含低位数字的字符串。

您需要做的第一件事是创建一个视图,该视图将为您生成一个新的 guid,因为这无法在用户定义的函数中完成:

CREATE VIEW GuidGenerator
AS
    SELECT Newid() As NewGuid

然后,函数代码:(注意:这是更简单的版本)

CREATE FUNCTION dbo.RandomStringGenerator
(
    @Length int,
    @Count int -- Note: up to 1,000,000 rows
)
RETURNS TABLE
AS
RETURN
 
-- An inline tally table with 1,000,000 rows
WITH E1(N) AS (SELECT N FROM (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) V(N)),   -- 10
     E2(N) AS (SELECT 1 FROM E1 a, E1 b), --100
     E3(N) AS (SELECT 1 FROM E2 a, E2 b), --10,000
     Tally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY @@SPID) FROM E3 a, E2 b) --1,000,000
 
 
SELECT TOP(@Count) (
    SELECT  TOP (@Length) CHAR(
            -- create a random number from a guid using the GuidGenerator view, mod 3.
            CASE  Abs(Checksum(NewGuid)) % 3
                WHEN 0 THEN 65 + Abs(Checksum(NewGuid)) % 26 -- Random upper case letter
                WHEN 1 THEN 97 + Abs(Checksum(NewGuid)) % 26 -- Random lower case letter
                ELSE 48 + Abs(Checksum(NewGuid)) % 10 -- Random digit
            END
            )
    FROM Tally As t0  
    CROSS JOIN GuidGenerator 
    WHERE  t0.n != -t1.n -- Needed for the subquery to get re-evaluated for each row
    FOR XML PATH('')
    ) As RandomString
FROM Tally As t1

然后,您可以像这样使用它来获得一个不同的随机字符串:

SELECT DISTINCT RandomString 
FROM dbo.RandomStringGenerator(50, 5000); 

【讨论】:

以上是关于使用唯一随机值更新sql表中的所有行,而不使用c#中的主键或唯一键的主要内容,如果未能解决你的问题,请参考以下文章

随机名称表中的 SQL 更新

如何使用 C# 程序中的新值快速更新表中的所有行

使用另一个表作为随机值的集合随机更新一组值而不使用循环的方法?

使用唯一的递增值更新表中的 int 列

更新表中所有行的有效方法

在 SQL 表中使用 C# 更新值