2014-02-07 6 views
-3

Я работаю в Microsoft SQL Server, и у меня проблема с моей базой данных, где я пытаюсь вставить новые данные в таблицу, но данные были случайно вставлены один раз в прошлом и поскольку такое повторное включение приведет к ключевым нарушениям. Я ищу способ вставить нужные мне данные и обновить то, что было случайно включено. Некоторые из особенностей коды были изменены для краткости, но мой код, как он стоит сейчас:SQL INSERT и UPDATE

BEGIN TRANSACTION 

INSERT INTO dbs_salesinternals.acc_saleshistory 
SELECT a, 
     b AS n 
FROM dbs_sales.orders AS O 
     INNER JOIN dbs_salesinternals.acc_report_months AS ARM 
       ON ARM.acc_report_month_id = dbo.Reportmonth(CASE 
          WHEN O.ordertypeid = 2 THEN shipduedate 
          ELSE shipdate 
                  END) 
     INNER JOIN dbo.contactfullnames 
       ON O.customerid = dbo.contactfullnames.contact_id 
     INNER JOIN dbs_sales.ordertypes 
       ON dbs_sales.ordertypes.ordertypeid = O.ordertypeid 
     LEFT JOIN(SELECT OD.orderid, 
         Sum(CASE 
           WHEN PB.format LIKE '%kit%' 
            AND units.curriculumcode = 'CUR' THEN 
           OD.price 
           ELSE 0 
          END) AS KitPart, 
         Sum(CASE 
           WHEN PB.format = 'PD' 
            AND units.curriculumcode = 'CUR' THEN 
           OD.price 
           ELSE 0 
          END) AS PDPart, 
         Sum(CASE 
           WHEN (PB.format <> 'PD' 
            AND PB.format NOT LIKE '%kit%' 
            AND units.curriculumcode = 'CUR') THEN 
           OD.price 
           ELSE 0 
          END) AS OtherPart, 
         Sum(CASE 
           WHEN PB.format LIKE '%kit%' 
            AND units.curriculumcode = 'WEB' THEN 
           OD.price 
           ELSE 0 
          END) AS EKitPart, 
         Sum(CASE 
           WHEN PB.format = 'PD' 
            AND units.curriculumcode = 'WEB' THEN 
           OD.price 
           ELSE 0 
          END) AS EPDPart, 
         Sum(CASE 
           WHEN (PB.format <> 'PD' 
            AND PB.format NOT LIKE '%kit%' 
            AND units.curriculumcode = 'WEB') THEN 
           OD.price 
           ELSE 0 
          END) AS EGuidePart 
       FROM dbs_salesinternals.eieproductsbase AS PB 
         INNER JOIN dbs_salesinternals.productpricing AS PP 
           ON PB.productid = PP.product_id 
         INNER JOIN dbs_sales.[order details] AS OD 
           ON PP.productpricing_id = OD.productpricing_id 
         INNER JOIN units 
           ON PB.unit_id = units.unit_id 
       GROUP BY OD.orderid) OP 
       ON OP.orderid = O.orderid 
     LEFT JOIN [dbo].[grant_codes] 
       ON [dbo].[grant_codes].grantcodemap_id = O.accountcode 
WHERE O.ordertotal <> 0 
     AND O.ordertypeid IN (1, 2, 3, 4) 
     AND ARM.acc_report_month_id = 166 
     AND ([dbo].[grant_codes].granttype IS NULL 
       OR [dbo].[grant_codes].granttype <> 2) 

COMMIT TRANSACTION 

Как я могу изменить это сделать то, что мне нужно?

+1

Похоже, вам нужно исследовать MERGE: http://msdn.microsoft.com/en-us/library/bb510625.aspx –

+0

Возможно, вы захотите изменить свой вопрос и удалить форматирование из вопроса, сделав все смелым не поможет. –

+0

Yep merge может быть очень полезным инструментом –

ответ

0

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

Во-первых, изменить существующий запрос на то, что вставляет во временную таблицу (тЕмп стол обозначается # перед его именем):

select <your select-clause> 
into #temp 
from <your from-clause> 
where <your where-clause> 

Так что теперь у нас есть 2 таблицы, как содержащий данные. Давайте позвоним в таблицу, которую мы добавляем к S, и временную таблицу, которая будет использоваться в качестве основы для данных, которые будут добавлены T.

Во-первых, нам нужно выяснить, какая из строк в T уже существует в S. Они, вероятно, имеют общий идентификатор строки, давайте назовем его id, и найти множество строк в T, которые имеют соответствующую строку в S через простое соединение:

select * from S s join T t on s.id = t.id; 

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

update S 
set c1 = (select t.c1 from T t where t.id = S.id), 
c2 = (select t.c2 from T t where t.id = S.id), 
... 
cN = (select t.cN from T t where t.id = S.id) 
where S.id in (
    select t.id 
    from S s join T t on s.id = t.id); 

Мы обновляем все строки в S, которая существует в обоих T и S, и «выбрать» значение из T с внутренними выбирает.

Далее мы должны вставить строки в T, которых еще нет в S. Этот запрос будет сделать:

insert into S (id, c1, c2, ..., cN) 
select id, c1, c2, ..., cN 
from T where id not in (select id from S); 

(Может быть использован присоединиться к where -clause, но это работает точно так же ..)

Этот запрос будет вставлять строки в T, которые не являются уже в S - S.