SQL Server 2008 Обновите несколько столбцов с помощью цикла или другого метода - PullRequest
0 голосов
/ 02 ноября 2018

Скажем, у меня есть две таблицы: A и B.

Обе таблицы содержат одинаковую структуру: ID, имя, зарплата, домашнее хозяйство

Мне нужно обновить отсутствующие записи A с помощью B.

Таблица A:

ID   NAME   SALARY   HOUSEHOLD
--------------------------------
 1   John     100        2
 2   Jane    NULL        3
 3   Mary     200       NULL
 4   Ann     NULL       NULL

Таблица B:

ID   NAME   SALARY   HOUSEHOLD
--------------------------------
 1   John     400        2
 2   Jane     200        3
 3   Mary     200        1
 4   Ann      125        1

После всех обновлений он должен выглядеть так

Таблица A:

ID   NAME   SALARY   HOUSEHOLD
--------------------------------
 1   John     100        2
 2   Jane     200        3
 3   Mary     200        1
 4   Ann      125        1

Я пробовал этот SQL:

UPDATE A
SET SALARY = B.SALARY
FROM A
LEFT JOIN B ON A.ID = B.ID AND A.NAME = B.NAME
WHERE ISNULL(A.SALARY, '') = ''
  AND ISNULL(B.SALARY, '') <> ''

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

UPDATE A
SET HOUSEHOLD = B.HOUSEHOLD
FROM A
LEFT JOIN B ON A.ID = B.ID AND A.NAME = B.NAME
WHERE ISNULL(A.HOUSEHOLD, '') = ''
  AND ISNULL(B.HOUSEHOLD, '') <> ''

Я представляю, как использовать цикл, который будет переходить к следующей переменной в каком-то контейнере и использовать переменную вместо имени столбца. В моей реальной таблице у меня есть около 30 столбцов, которые нужно было обновить.

Это не должно быть петлей. Пока это делает работу. Буду рад узнать другие способы, если это облегчит работу!

Возможно, что-то вроде этого (это на 100% неправильно. Даже близко к правильному синтаксису):

for i <= 2
i = 1
@Column = ('ID', 'NAME')

UPDATE A
SET @Column = B.@Column
FROM A
LEFT JOIN B ON A.ID = B.ID AND A.NAME = B.NAME
WHERE ISNULL(A.@Column, '') = ''
  AND ISNULL(B.@Column, '') <> ''
NEXT

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Попробуйте, это простой, но эффективный цикл

BEGIN
    DECLARE @TableA TABLE -- temp table to hold data
    (
        ID INT IDENTITY(1,1)
        , TableA_ID INT
        ,  [Name] NVARCHAR(256)
        , Salary NVARCHAR(256)
        , HOUSEHOLD INT
    )
    --fill in the temp table with data
    INSERT INTO @TableA SELECT  B.* FROM A
LEFT JOIN B ON A.ID = B.ID AND A.NAME = B.NAME
WHERE ISNULL(A.SALARY, '') = ''
AND ISNULL(B.SALARY, '') <> ''
    --declare some variables to hold data
    DECLARE @Count INT, @Counter INT, @TableA_ID INT, @Name NVARCHAR(256),@Salary NVARCHAR(260),@HOUSEHOLD int
    SELECT @Count = COUNT(*) FROM @TableA m
    SET @Counter = 1


    WHILE @Counter <= @Count
    BEGIN
        SELECT @TableA_ID = TableA_ID, @Name = ModuleTableName,@Salary = Salary,@HOUSEHOLD = HOUSEHOLD
        FROM @TableA m WHERE ID = @Counter


        -- now everything is in variables
        --something like
         --Update TableA set Name = @Name, Salary = @Salary where ID =@TableA_ID

        SET @Counter = @Counter + 1
    END 
END
0 голосов
/ 02 ноября 2018

Домохозяйство и зарплата - это числа, могут ли они быть пустыми строками? Если это так, вы можете изменить их типы данных на числовые.

В любом случае вы можете сделать это за один выстрел без петель:

UPDATE A SET 
  HOUSEHOLD = COALESCE(A.HOUSEHOLD, B.HOUSEHOLD),
  SALARY    = COALESCE(A.SALARY,    B.SALARY)
  -- repeat for other columns
FROM dbo.TableA AS A
LEFT JOIN dbo.TableB AS B
ON A.ID = B.ID AND A.NAME = B.NAME;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...