【问题标题】:SQL Query to update or insert row with If Exists statement not working使用 If Exists 语句更新或插入行的 SQL 查询不起作用
【发布时间】:2019-01-27 11:06:17
【问题描述】:

以前在发帖时我错过了包含 urn 和 org_ref 的表 b。我有三张桌子。表a,b和c,我必须根据表a中的URN键更新表c的“total Emp”列。表 B 没有 URN 列,但它有 Org_ref,因此要连接表 a 和表 c,我们需要在 a.urn=b.urn 上连接表 b。我已经编写了一个查询来遍历记录并执行插入或更新,但它不工作并且不更新。只需在表 b 中插入空白的“员工总数”即可。

表一个

   |urn  |total employee
   |333  |25
   |123  |26
   |21   |2
   |11   |23

表 B

   |urn  |org_ref
   |333  |1234
   |123  |343
   |21   |2
   |11   |23

表 C

   org_ref    total employe 
   1234            0       --should update from table a 
    343            0       --should update from table a 
                           --add record from table a org_ref 21
                           --add record from table a org_ref 11

这是我的脚本

Create table #orgs(
iorgrowid int identity (1,1),
ORG_REF  varchar(255),
Total_Leader int,
urn int
)


insert into #orgs

select  ORG.organisation_ref,s.[TOTAL_LEADERSHIP_ROLE],s.urn

    from DiTestDatabase.dbo.organisation org

    JOIN DataConversion.dbo.School_plus_download_NI s on org.total_headcount=s.urn 

DECLARE 
@iReturnCode int,
@iNextcodeRowId int,
@icodeRowId int,
@iCurrentcodeRowId int,
@iNextattRowId int,
@iCurrentattRowId int,
@icodeLoopControl int,
@ORGREF INT,
@counter int,
@Ly_employees int,
@orgnamecount int,
@add1count int,
@urn int


SELECT @iCodeLoopControl = 1
SELECT @iNextCodeRowId = MIN(iorgrowId)
FROM #orgs


IF ISNULL(@iNextCodeRowId,0) = 0
BEGIN
SELECT 'No data in found in table!'
RETURN
END


SELECT
@iCurrentcodeRowId = iorgrowId,
@ORGREF=ORG_REF,
@Ly_employees=Total_Leader,
@urn=urn
FROM #orgs
WHERE iorgRowId = @iNextcodeRowId


set @counter = 0    
set @orgnamecount=0
set @add1count=0

--Start the main processing loop.
WHILE @iCodeLoopControl = 1



BEGIN


        begin
          set @counter = @counter + 1
         print 'The counter is ' + cast(@counter as char)  + cast(@ORGREF as char)
        end

IF EXISTS (SELECT OG.ORGANISATION_REF
FROM ORG_ACCOUNT OG WHERE OG.ORGANISATION_REF= @ORGREF
)

BEGIN
  UPDATE ORG_ACCOUNT
  SET LY_EMPLOYEES= (SELECT SP.TOTAL_LEADERSHIP_ROLE
            FROM DataConversion.dbo.School_plus_download_NI SP
            JOIN ORGANISATION ORG ON ORG.TOTAL_HEADCOUNT=SP.URN
            JOIN ORG_ACCOUNT OA ON OA.ORGANISATION_REF=ORG.ORGANISATION_REF
            WHERE OA.ORGANISATION_REF=@ORGREF)
            FROM DataConversion.dbo.School_plus_download_NI SP WHERE SP.URN=@urn

    END

ELSE

BEGIN

   alter table ditestdatabase.dbo.org_account disable trigger all   

    INSERT INTO ORG_ACCOUNT
    (ORGANISATION_REF,LY_TURNOVER,LY_PROFIT,LY_REMUN,LY_EMPLOYEES,PY_TURNOVER,PY_PROFIT,PY_REMUN,PY_EMPLOYEES,UK_TURNOVER,UK_PROFIT,UK_REMUN,UK_EMPLOYEES,CREATED_BY,
    CREATE_TIMESTAMP,UPDATED_BY,UPDATE_TIMESTAMP,PY_POT_SUB,LY_POT_SUB,LY_DATE,PY_DATE,UK_DATE)
    VALUES(@ORGREF,NULL,NULL,NULL,@Ly_employees,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,null,GETDATE(),null,null,null,null,null,null,null)

    set @orgref=(select organisation_ref from DiTestDatabase.dbo.ORG_ACCOUNT where ORGANISATION_REF=@ORGREF)

        end

        alter table ditestdatabase.dbo.org_account enable trigger all       







SELECT @iNextCodeRowId = NULL

--Get the next iRowId.
SELECT @iNextcodeRowId = MIN(iorgrowId)
FROM #orgs
WHERE iorgrowId > @iCurrentcodeRowId

--Did we get a valid next row id?
IF ISNULL(@iNextCodeRowId,0) = 0


BEGIN
BREAK
END

SELECT @iCurrentcodeRowId = iorgrowId,
@ORGREF=ORG_REF,
@Ly_employees=Total_Leader
FROM #orgs
WHERE iorgRowId = @iNextcodeRowId

END

DROP TABLE #orgs

RETURN

解决方案:- 由于表 a 和 c 之间没有任何共同点,因此我必须借助表 b,其中 a 和 b 之间唯一的共同点是 URN 列,b 和 c 之间唯一共同的列是 Org_ref。我已将我的更新更改为

SET LY_EMPLOYEES= (SELECT SP.TOTAL_LEADERSHIP_ROLE
            FROM DataConversion.dbo.School_plus_download_NI SP
            JOIN ORGANISATION ORG ON ORG.TOTAL_HEADCOUNT=SP.URN
            JOIN ORG_ACCOUNT OA ON OA.ORGANISATION_REF=ORG.ORGANISATION_REF
            WHERE sp.URN = @urn) --@ORGREF)

            FROM ORG_ACCOUNT WHERE ORGANISATION_REF=@ORG_REF

解决了这个问题。

谢谢大家

【问题讨论】:

  • 阅读Merge
  • 这是我的查询。
  • 代码是以非常程序化的编程方式编写的,而不是更适合数据库的基于集合的方式。 Abhishek 将您指向Merge 声明是正确的。此外,我认为您需要解释/考虑那些 BEGIN TRANSACTION 行,以及您打算何时/何地提交?在插入之前禁用触发器然后启用触发器似乎也很可疑。
  • @Andrew 是的,我的背景是核心 C#,作为反映我的查询的应用程序开发人员。我不得不禁用触发器以加快进程,每个表包含超过 3 个触发器。
  • 我忘记了我有 3 张桌子而不是 2 张。我已经更新了我的问题,请查看我的朋友们。

标签: sql sql-server database sql-server-2008 tsql


【解决方案1】:

不要在简单的 upsert 操作中使用 while 循环或游标!你会在网络上到处发现它适得其反!

我会用表 a/b 的简单术语来回答:

-- First, update the ones that exist
update alias_b -- Note that you NEED an alias to update using join
set [total employee]=a.[total employee]
from a 
inner join b alias_b on a.org_ref=alias_b.org_ref

-- Then, insert the ones that don't
insert b
select (the columns you want)
from a
where not exists (select 1 from b where a.org_ref=b.org_ref)

【讨论】:

  • @geroge 我已经改变了我的问题,我忘了提到我有 3 张桌子而不是 2 张桌子。
【解决方案2】:
--UPDATE
UPDATE B SET B.TOTAL_LEADER = A.TOTAL_LEADER FROM TABLEA A INNER JOIN TABLEB B ON 
A.ORG_REF = B.ORG_REF
--INSERT
INSERT INTO TABLEB(ORG_REF,URN,TOTAL_LEADER)
SELECT A.ORG_REF,A.URN,A.TOTAL_LEADER FROM TABLEA A LEFT OUTER JOIN  TABLEB B ON 
A.ORG_REF = B.ORG_REF WHERE B.ORG_REF IS NULL

我想你正在寻找这个。

【讨论】:

    【解决方案3】:

    这有用吗?

        CREATE TABLE #a(urn bigint,  total_employe bigint)
    
        CREATE TABLE #b(urn bigint,org_ref bigint)
    
        CREATE TABLE #c(org_ref bigint,total_employe bigint)
    
        INSERT INTO #a
        SELECT 333,25 Union ALL
        SELECT 123,26 Union ALL
        SELECT 21,2 Union ALL
        SELECT 11,23
    
    
    
    
        INSERT INTO #b
        SELECT 333,1234 Union ALL
        SELECT 123,343 Union ALL
        SELECT 21,2 Union ALL
        SELECT 11,23 
    
    
        INSERT INTO #c
        SELECT 1234,0 Union ALL
        SELECT 343,0
    
    
    
        ;with cte
        AS
        (
        SELECT b.org_ref,a.total_employe from #a a
        INNER JOIN #b b on a.urn=b.urn
        )
    
    
        MERGE INTO #c c
        USING cte  on c.org_ref=cte.org_ref 
        WHEN MATCHED THEN
        UPDATE
        SET c.total_employe=cte.total_employe
    
        WHEN NOT MATCHED THEN
        INSERT(org_ref,total_employe)
        VALUES(org_ref,total_employe);
    
        SELECT * FROM #c
    
    
        DROP TABLE #a
        DROP TABLE #b
        DROP TABLE #c
    

    【讨论】:

    • 我对我的问题进行了修改,请再看一遍。
    【解决方案4】:

    SELECT INTO 怎么样?比如:

    SELECT b.org_ref, a.totalemployee INTO c FROM a LEFT JOIN b ON (a.urn = b.urn)
    

    【讨论】:

    • 检查我的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 2013-05-09
    • 2013-09-19
    • 1970-01-01
    • 2021-02-26
    相关资源
    最近更新 更多