我可以在更新t-sql中嵌入插入t-sql吗?

时间:2014-05-28 19:37:36

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

是否可以在更新语句中嵌套insert语句?

背景

我第一次使用merge子句来转换某些数据。也就是说,我有一个包含许多列的单个源表但需要,因为缺少一个更好的词,转换到更结构化的模型/模式;与BI模型类似。我对BI建模也缺乏经验(刚开始阅读它不到一个月)。任何帮助都会很大 赞赏。

我很乐意提供可能需要帮助的任何其他信息。

错误:

  

Msg 156,Level 15,State 1,Line 47
  关键字附近的语法不正确'选择'。

     

Msg 102,Level 15,State 1,Line 48
  “#”;'附近的语法不正确。

我尝试将插入到tertiary.WEBADDRESS 行中时抛出这些。

代码:

--Transform operation
--web address dimension insert
use UniversityUS
merge tertiary.INSTITUTION as target
using(
        select UNITID,
             INSTNM,
             ADDR,
             CITY,
             STABBR,
             ZIP,
             OBEREG,
             WEBADDR,
             ADMINURL,
             FAIDURL,
             APPLURL,
             HLOFFER,
             GENTELE,
             LOCALE,
             CARNEGIE,
             FAXTELE,
             IALIAS,
             F1SYSNAM,
             COUNTYNM,
             LONGITUD,
             LATITUDE
             --geography::Point(LATITUDE,LONGITUD,4326)) as [LOCATION]
        from staging.secondary_university
        where closedat = -2
    ) as source
on ( source.UNITID = target.ROWSOURCECONTROLID )
when not matched by target then

        --this would represent my fact table
        insert (INSTNM,IALIAS,GENTELE,F1SYSNAM,ROWSOURCECONTROLID)
        values (source.INSTNM,source.IALIAS,source.GENTELE,source.F1SYSNAM,source.UNITID)       

when matched then

        update set target._WEBADDRID = 
        (
            select wa.wid
            from
            (
                --this would represent one of my many dimension tables
                --if i comment the next two lines it works
                --but i need to know how will these be updated.
                insert into tertiary.WEBADDRESS 
                values(source.WEBADDR,source.ADMINURL,source.FAIDURL,source.APPLURL)

                select scope_identity() as wid
            )wa 
        )

when not matched by source then
    delete
output $action;

1 个答案:

答案 0 :(得分:2)

我知道这是一个古老的问题,但这是一个有趣的问题,所以我会尽可能地回答任何可能在研究自己的好奇心时偶然发现它的人。

我首先要说这可能是不好的做法。通过尝试嵌套这样的语句,你冒着无法读取的代码的风险,如果出现一些并发问题,对我来说就不会太令人惊讶了。但是,如果你完全卖掉了,你可能会用存储过程完成类似的事情。但同样,那些副作用不明显的东西可能是不可读的。您还可以查看该插入的OUTPUT子句。我不确定,但是你能够添加一个OUTPUT INSERTED.ID(或任何你的标识列被命名)并运行你的选择,而不是使用插入后跟一个选择是有道理的。同样,我不确定这是否有效。但这听起来很合理。

所有人都说,正如Aaron在评论中提到的那样,最好将其分成几个单独的操作。我个人对MERGE没关系,我已经习惯了它,它还没有引起我在该帖子中提出的任何问题,尽管它们现在也可能是旧闻,因为我们有几个版本但我至少建议你把插件分成一个单独的,甚至是交易共享的声明:

INSERT INTO tertiary.WEBADDRESS 
SELECT WEBADDR, ADMINURL, FAIDURL, APPLURL
    FROM staging.secondary_university
    WHERE closedat = -2 AND
          EXISTS (SELECT *
                  FROM tertiary.INSTITUTION
                  WHERE tertiary.Institution.ROWSOURCECONTROLID = staging.secondary_university.UNITID)

然后,您可以轻松修改WHEN MATCHED子句,以获取适当的标识值,给出建立唯一性所需的任何键。

 ...
 WHEN MATCHED THEN
      UPDATE SET target._WEBADDRID = (SELECT TOP 1 [whatever_your_ID_column_is]
                                      FROM staging.secondary_university
                                      WHERE staging.secondary_university.WebAddr = source.WebAddr AND
                                            staging.secondary_university.ADMINURL = source.ADMINURL AND
                                            staging.secondary_university.FAIDURL = source.FAIDURL AND
                                            staging.secondary_university.APPLURL = source.APPLURL)
 ...