2014-02-07 86 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

是的,合併可以是一個非常有用的工具 –

回答

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存在於兩個TS更新所有的行,並從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