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