T-SQL для обновления строк с одинаковым значением в столбце - PullRequest
8 голосов
/ 24 октября 2011

У меня есть таблица, скажем, с именем FavoriteFruits, которая имеет NAME, FRUIT и GUID для столбцов.Стол уже заполнен именами и фруктами.Итак, скажем:

NAME      FRUIT       GUID
John      Apple       NULL
John      Orange      NULL
John      Grapes      NULL
Peter     Canteloupe  NULL
Peter     Grapefruit  NULL

Хорошо, теперь я хочу обновить столбец GUID новым GUID (используя NEWID()), но я хочу иметь тот же GUID для каждого отдельногоназвание.Поэтому я хочу, чтобы все John Smiths имели одинаковый GUID, и я хочу, чтобы оба Peters имели одинаковый GUID, но этот GUID отличается от того, который использовался для Джонса.Так что теперь это будет выглядеть примерно так:

NAME      FRUIT       GUID
John      Apple       f6172268-78b7-4c2b-8cd7-7a5ca20f6a01
John      Orange      f6172268-78b7-4c2b-8cd7-7a5ca20f6a01
John      Grapes      f6172268-78b7-4c2b-8cd7-7a5ca20f6a01
Peter     Canteloupe  e3b1851c-1927-491a-803e-6b3bce9bf223
Peter     Grapefruit  e3b1851c-1927-491a-803e-6b3bce9bf223

Могу ли я сделать это в операторе обновления без использования курсора?Если да, можете ли вы привести пример?

Спасибо, ребята ...

Ответы [ 3 ]

6 голосов
/ 24 октября 2011

Обновление CTE не будет работать, потому что будет оцениваться для каждой строки . Табличная переменная будет работать:

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

DECLARE @n TABLE (Name varchar(10), Guid uniqueidentifier);

INSERT @n
SELECT Name, newid() AS Guid
FROM FavoriteFruits
GROUP BY Name;

UPDATE f
    SET f.Guid = n.Guid
FROM @n n
    JOIN FavoriteFruits f ON f.Name = n.Name

Таким образом, заполняется переменная с GUID для каждого имени, затем присоединяется к исходной таблице и обновляется соответствующим образом.

0 голосов
/ 24 октября 2011

Существует также решение с одним оператором, которое, однако, имеет некоторые ограничения. Идея состоит в том, чтобы использовать OPENQUERY(), вот так:

UPDATE FavoriteFruits
SET GUID = n.GUID
FROM (
  SELECT NAME, GUID
  FROM OPENQUERY(
    <i>linkedserver</i>,
    'SELECT NAME, NEWID() AS GUID FROM <i>database</i>.<i>schema</i>.FavoriteFruits GROUP BY NAME'
  )
) n
WHERE FavoriteFruits.NAME = n.NAME

Это решение подразумевает, что вам нужно создать самонаправленный связанный сервер. Другая особенность заключается в том, что вы не можете использовать этот метод для переменных таблиц или локальных временных таблиц (глобальные подходили бы так же, как «обычные» таблицы).

0 голосов
/ 24 октября 2011

Для пояснения комментариев по табличному выражению в предложении USING оператора MERGE.

Следующее не будет работать, потому что будет оцениваться по строке :

MERGE INTO FavoriteFruits
   USING (
          SELECT NAME, NEWID() AS GUID
            FROM FavoriteFruits
           GROUP 
              BY NAME
         ) AS source
      ON source.NAME = FavoriteFruits.NAME
WHEN MATCHED THEN
   UPDATE
      SET GUID = source.GUID;

Но с использованием табличной переменной будет работать следующее:

DECLARE @n TABLE 
(
 NAME VARCHAR(10) NOT NULL UNIQUE, 
 GUID UNIQUEIDENTIFIER NOT NULL UNIQUE
);

INSERT INTO @n (NAME, GUID)
   SELECT NAME, NEWID() 
     FROM FavoriteFruits
    GROUP 
       BY NAME;

MERGE INTO FavoriteFruits
   USING @n AS source
      ON source.NAME = FavoriteFruits.NAME
WHEN MATCHED THEN
   UPDATE
      SET GUID = source.GUID;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...