Цикл SQL при вставке или обновлении - PullRequest
2 голосов
/ 19 ноября 2010

У меня есть две таблицы.

Таблица A и Таблица B. Столбцы одинаковые.

create table TableA (
    id int
    , name varchar
    , last datetime
)

create table TableB (
    id int
    , name varchar
    , last datetime
)

Заполняю таблицу A данными о массе.и я хотел бы либо вставить, либо обновить данные в таблице A в таблицу B.

Я хотел бы взять данные из таблицы A и либо вставить в таблицу B, если имя и имя совпадают, либо обновить, еслиID и имя совпадают.

Я попробовал какой-нибудь инструмент ETL, но результат был очень медленным.У меня есть индексирование по идентификатору и имени, я хотел попробовать это с SQL.

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

SELECT      @id = ID, 
      @name = name, 
      @LSDATE = LastSeen_DateTime   
            FROM DBO.A
IF EXISTS (SELECT ID, name FROM DBO.A
WHERE  @ID = ID AND @name = Name)

begin - обновление конец, иначе begin --insertend

Полагаю, мне нужно поместить это в цикл, и я не совсем уверен, как мне это сделать.

Спасибо.

Ответы [ 3 ]

6 голосов
/ 20 ноября 2010

Если вы используете SQL Server 2008 (или Oracle или DB2), вы можете использовать оператор слияния.

MERGE B
USING A AS source 
ON (B.ID = source.ID and B.Name = source.Name)
WHEN MATCHED THEN 
    UPDATE SET Last = source.Last
WHEN NOT MATCHED BY TARGET THEN
    INSERT (ID, Name, Last) VALUES (source.ID, source.Name, source.Last)

   -- the following is optional, if you remove it, add a semicolon to the end of the above line. 
   OUTPUT $action, 
   inserted.ID AS SourceID, inserted.Name AS SourceName, 
   inserted.Last AS SourceLast, 
   deleted.ID AS TargetID, deleted.Name AS TargetName, 
   deleted.Last AS TargetLast ;   

Бит с «output $ action» покажет, какие строки обновляются и какие строки обновляются.

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

6 голосов
/ 19 ноября 2010

Вероятно, быстрее сделать это двумя операторами, одним обновлением и одной вставкой, а не циклом

Этот оператор обновляет все строки B, используя данные из A, где идентификатор совпадает, но имя отличается

Обновление

Update 
    tableB
SET
   name = a.Name
From
   tableB a
   INNER JOIN tableA a
   on b.ID = a.ID 
      and A.Name <> b.Name

Этот оператор вставляет все строки B в A, где идентификатор не существует в A

ВСТАВИТЬ

INSERT INTO
   tableB
(   ID,
    Name
)
SELECT
   a.ID
   a.Name
FROM 
   tableA b
WHERE
   not exists (Select A.ID From tableB a WHERE a.ID = b.ID)

Обновлено (перевернуло его из А в В, а не В в А)

2 голосов
/ 19 ноября 2010
DECLARE @id int
DECLARE @name nvarchar
DECLARE @last datetime
DECLARE TableA_Cursor CURSOR FOR
    select id
            , name
            , last
        from TableA;

OPEN TableA_Cursor;

FETCH NEXT from TableA_Cursor 
INTO @id, @name, @last;

WHILE @@FETCH_STATUS = 0
    BEGIN
        IF (EXISTS select 1 from TableB b where b.Id = @id)
            update TableB
                set Name = @name
                    , Last = @last
        ELSE
            insert into TableB (Id, Name, Last) 
                values (@id, @name, @last)

        FETCH NEXT from TableA_Cursor
        INTO @id, @name, @last
    END

CLOSE TableA_Cursor;

DEALLOCATE TableA_Cursor;

Может быть некоторая синтаксическая ошибка, особенно в отношении условия IF, но вы можете получить точку.

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