1

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

背景

merge第一次使用该子句来转换一些数据。也就是说,我有一个包含许多列的单个源表,但如果缺少更好的词,我需要转换为更结构化的模型/模式;类似于BI模型。我在 BI 建模方面也缺乏经验(现在才开始阅读它不到一个月)。任何帮助将不胜感激。

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

错误:

消息 156,级别 15,状态 1,第 47 行
关键字“选择”附近的语法不正确。

消息 102,级别 15,状态 1,第 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;
4

1 回答 1

2

I know this is kind of an old question, but it's an interesting one so I'll answer as best I can for anyone who might stumble across it in researching their own curiosities.

I'll start by saying that this is probably bad practice. By attempting to nest statements like this, you're risking unreadable code and it wouldn't be overly surprising to me if some concurrency issues came up. If you're completely sold on this, though, you could probably accomplish something like it with a stored procedure. But again, something that side-effects unclearly like that will probably be unreadable. You might also look into the OUTPUT clause of that insert. I'm not sure, but it makes sense that you'd be able to add in an OUTPUT INSERTED.ID (or whatever your identity column is named) and run your select against that, rather than utilizing an insert followed by a select. Again, I'm not sure if that would work. But it sounds reasonable.

That all said, as it looks like Aaron alluded to in his comment, it would be better to separate this out into a few separate operations. I'm personally okay with MERGE, I've used it and it has yet to cause me any of the problems warned of in that post, although they could also be old news by now since we are a few versions in. But I would at least advise that you pull your insert out into a separate, even transaction-sharing, statement:

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)

Then you could easily modify your WHEN MATCHED clause to fetch the appropriate identity value given whatever keys you need to establish uniqueness.

 ...
 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)
 ...
于 2014-07-06T07:57:11.037 回答