TSQL не генерирует новое значение в строке - PullRequest
2 голосов
/ 29 апреля 2011

Я пытаюсь анонимизировать все данные в моей базе данных, поэтому я переименовываю всех людей в ней.Ранее я задавал подобный вопрос, и мне сказали использовать NewID для принудительного создания нового значения для обновленной строки, но в этой ситуации это, похоже, не работает.

Что я делаю неправильно?

-- Create Table Customer
CREATE TABLE #FirstName
(
    ID int,
    FirstName nvarchar(255) NULL,
    Gender nvarchar(255) NULL
)  

CREATE TABLE #LastName (
    ID int,
    LastName nvarchar(255)
)

-- BULK INSERT to import data from Text or CSV File
BULK INSERT #FirstName
FROM 'C:\Users\jhollon\Desktop\tmp\names\firstnames.lined.txt'
WITH
(
 FIRSTROW = 1,
 FIELDTERMINATOR = ',',
 ROWTERMINATOR = '\n'
)

BULK INSERT #LastName
FROM 'C:\Users\jhollon\Desktop\tmp\names\lastnames.lined.txt'
WITH
(
 FIRSTROW = 1,
 FIELDTERMINATOR = ',',
 ROWTERMINATOR = '\n'
)

/*SELECT FirstName FROM #FirstName WHERE ID = (
    SELECT RandomNumber FROM (
        SELECT ABS(CHECKSUM(NewID())) % 1500 AS RandomNumber FROM tblTenant WHERE Sex = '1'
        ) AS A
    );*/

UPDATE tblTenant SET TenantName = ( 
    SELECT LastName + ', ' + FirstName FROM 
        (SELECT UPPER(FirstName) as FirstName FROM #FirstName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 500 + 1501)) AS A,
        (SELECT LastName FROM #LastName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 200 + 1)) as B
) WHERE Sex = '2';

UPDATE tblTenant SET TenantName = ( 
    SELECT LastName + ', ' + FirstName FROM 
        (SELECT UPPER(FirstName) as FirstName FROM #FirstName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 500 + 1)) AS A,
        (SELECT LastName FROM #LastName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 200 + 1)) as B
) WHERE Sex = '1';

DROP TABLE #FirstName;
DROP TABLE #LastName;

Ответы [ 3 ]

2 голосов
/ 29 апреля 2011

Правильно.Подзапрос оценивается один раз, как объявлено («кэшируемый скалярный подзапрос»)

Попробуйте это, используя NEWID в качестве производной таблицы

UPDATE T
SET
    TenantName =  L.LastName + ', ' + F.FirstName
FROM
   tblTenant T
   CROSS APPLY
   (SELECT TOP 1 UPPER(FirstName) as FirstName FROM #FirstName 
           WHERE CHECKSUM(NEWID()) <> T.ID
           ORDER BY NEWID()) F
   CROSS APPLY
   (SELECT TOP 1 LastName FROM #LastName
           WHERE CHECKSUM(NEWID()) <> T.ID
           ORDER BY NEWID()) L
0 голосов
/ 29 апреля 2011

Приведенный ниже код демонстрирует, что без внутренней и внешней корреляции старое имя не обязательно будет отличаться от нового при использовании ответа CROSS APPLY выше.
WHERE F.Id <> T.Id ORDER BY NEWID() было бы лучше в FirstName CROSS APPLY

USE tempdb
GO           
IF OBJECT_ID('tblTenant') IS NOT NULL 
  DROP TABLE tblTenant
GO
CREATE TABLE tblTenant
(
  Id        int,
  FirstName nvarchar(20),
  LastName  nvarchar(20),
  Gender    bit
)
INSERT INTO tblTenant
VALUES (1, 'Bob'   , 'Marley', 1),
       (2, 'Boz'   , 'Skaggs', 1)

SELECT DISTINCT FirstName
INTO #FirstNames
FROM tblTenant

SELECT DISTINCT LastName
INTO #LastNames
FROM tblTenant

    -- There is a probability > 0 that a tenant's new name = tenants old name
    SELECT
      OldFirst = T.FirstName,
      OldLast  = T.LastName,
      NewFirst = F.FirstName,
      NewLast  = L.LastName
    FROM  
      tblTenant T

      CROSS APPLY
      (
        SELECT TOP 1 UPPER(FirstName) AS FirstName 
        FROM #FirstNames 
        WHERE CHECKSUM(NEWID()) <> T.ID
        ORDER BY NEWID()
      ) F

      CROSS APPLY
      (
        SELECT TOP 1 LastName 
        FROM #LastNames
        WHERE CHECKSUM(NEWID()) <> T.ID
        ORDER BY NEWID()
      ) L
0 голосов
/ 29 апреля 2011

Я не уверен, что понимаю ваш вопрос, но если вы хотите, чтобы идентификатор имел уникальные значения, вы можете сделать его столбцом идентификаторов. Пример:

[ID] [int] IDENTITY(1,1) NOT NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...