SQL Server 2008中的循环插入语句

时间:2014-02-04 14:31:33

标签: sql sql-server loops sql-insert

非常感谢可以提供的任何帮助。

我有以下两个表

TS_DEF_TRADER:

DEF_TRADER_ID  MANAGER_CD       INV_CLASS_CD    TRADER_CD
------         -------          ----------      ---------
101            HARRIT           EQTY            MMGR_DT
108            NAIDON           EQTY            MMGR_DT
123            MLONDG           EQTY            MMGR_DT

和PDF_USER_GROUP:

GRP_CD                    USER_CD       
------                    -------          
STANLIB_MULTI_MANAGER     HARRIT           
STANLIB_MULTI_MANAGER     NAIDON           
STANLIB_MULTI_MANAGER     MLONDG 
STANLIB_MULTI_MANAGER     FARRYM
STANLIB_MULTI_MANAGER     HOLMEM

我想要做的是创建某种循环SQL插入语句(如果这是正确的术语),它将检查PDF_USER_GROUP以及是否存在TS_DEF_TRADER中缺少GRP_CD = STANLIB_MULTI_MANAGER的USER_CD。如果缺少任何内容,则会插入相关的行。

我写了以下声明:

declare @DefTraderID INT
declare @Mgr varchar(200)
set @DefTraderID = (select MAX(DEF_TRADER_ID) + 1  from TS_DEF_TRADER)
set @Mgr = (select min(USER_CD) from PDF_USER_GROUP where not exists 
(select * from TS_DEF_TRADER where 
TRADER_CD = 'MMGR_DT' and 
INV_CLASS_CD = 'EQTY' and
TS_DEF_TRADER.MANAGER_CD = PDF_USER_GROUP.USER_CD)
and GRP_CD = 'STANLIB_MULTI_MANAGER'  and USER_CD not in ('MMGR_DT', 'SLIB_INDEX'))


insert into TS_DEF_TRADER (DEF_TRADER_ID,MANAGER_CD,INV_CLASS_CD, TRADER_CD)
values (@DefTraderID,@Mgr, 'EQTY', 'MMGR_DT')

如果我自己手动运行两次,我会得到以下结果:

DEF_TRADER_ID  MANAGER_CD       INV_CLASS_CD    TRADER_CD
------         -------          ----------      ---------
101            HARRIT           EQTY            MMGR_DT
108            NAIDON           EQTY            MMGR_DT
123            MLONDG           EQTY            MMGR_DT
124            FARRYM           EQTY            MMGR_DT
125            HOLMEM           EQTY            MMGR_DT

如果我第三次运行它会发生这种情况:

DEF_TRADER_ID  MANAGER_CD       INV_CLASS_CD    TRADER_CD
------         -------          ----------      ---------
101            HARRIT           EQTY            MMGR_DT
108            NAIDON           EQTY            MMGR_DT
123            MLONDG           EQTY            MMGR_DT
124            FARRYM           EQTY            MMGR_DT
125            HOLMEM           EQTY            MMGR_DT
126            NULL             EQTY            MMGR_DT

我需要它自己运行(即:循环)并在需要时停止一次,这样我们就不会得到NULL。

2 个答案:

答案 0 :(得分:3)

这根本不需要循环,你可以只做一个INSERT语句:

DECLARE @MaxDefTraderId INT

SELECT @MaxDefTraderId = MAX(DEF_TRADER_ID)
FROM TS_DEF_TRADER

INSERT INTO TS_DEF_TRADER(DEF_TRADER_ID, MANAGER_CD, INV_CLASS_CD, TRADER_CD)
SELECT  @MaxDefTraderId + ROW_NUMBER() OVER(ORDER BY USER_CD) DEF_TRADER_ID, 
        USER_CD MANAGER_CD,
        'EQTY' INV_CLASS_CD,
        'MMGR_DT' TRADER_CD
FROM PDF_USER_GROUP A
WHERE GRP_CD = 'STANLIB_MULTI_MANAGER'
AND NOT EXISTS(SELECT 1 FROM TS_DEF_TRADER
               WHERE MANAGER_CD = A.USER_CD)

Here is a demo这个。结果是:

╔═══════════════╦════════════╦══════════════╦═══════════╗
║ DEF_TRADER_ID ║ MANAGER_CD ║ INV_CLASS_CD ║ TRADER_CD ║
╠═══════════════╬════════════╬══════════════╬═══════════╣
║           101 ║ HARRIT     ║ EQTY         ║ MMGR_DT   ║
║           108 ║ NAIDON     ║ EQTY         ║ MMGR_DT   ║
║           123 ║ MLONDG     ║ EQTY         ║ MMGR_DT   ║
║           124 ║ FARRYM     ║ EQTY         ║ MMGR_DT   ║
║           125 ║ HOLMEM     ║ EQTY         ║ MMGR_DT   ║
╚═══════════════╩════════════╩══════════════╩═══════════╝

现在,我需要警告你计算DEF_TRADER_ID的方式。您应该使用IDENTITY列而不是以这种方式分配值。当另一个用户尝试向该表插入值时会发生什么?,您可能会插入重复项ID。

答案 1 :(得分:1)

您可以使用WHILE循环,并持续评估@Mgr是否为NULL:

declare @DefTraderID INT;
declare @Mgr varchar(200);

set @DefTraderID = (select MAX(DEF_TRADER_ID) + 1  from TS_DEF_TRADER);
set @Mgr = (select min(USER_CD) from PDF_USER_GROUP where not exists 
 (select * from TS_DEF_TRADER 
  where 
    TRADER_CD = 'MMGR_DT' and 
    INV_CLASS_CD = 'EQTY' and
    TS_DEF_TRADER.MANAGER_CD = PDF_USER_GROUP.USER_CD)
  and GRP_CD = 'STANLIB_MULTI_MANAGER'  
  and USER_CD not in ('MMGR_DT', 'SLIB_INDEX'));


WHILE (@Mgr IS NOT NULL)
  BEGIN

   insert into TS_DEF_TRADER (DEF_TRADER_ID,MANAGER_CD,INV_CLASS_CD, TRADER_CD)
   values (@DefTraderID, @Mgr, 'EQTY', 'MMGR_DT');

    set @DefTraderID = (select MAX(DEF_TRADER_ID) + 1  from TS_DEF_TRADER);
    set @Mgr = (select min(USER_CD) from PDF_USER_GROUP where not exists 
     (select * from TS_DEF_TRADER 
      where 
        TRADER_CD = 'MMGR_DT' and 
        INV_CLASS_CD = 'EQTY' and
        TS_DEF_TRADER.MANAGER_CD = PDF_USER_GROUP.USER_CD)
      and GRP_CD = 'STANLIB_MULTI_MANAGER'  
      and USER_CD not in ('MMGR_DT', 'SLIB_INDEX'));

  END

明显警告@Mgr在某些时候应该为NULL,否则你将永远循环。

AFAIK SqlServer中没有DO..WHILE / REPEAT..UNTIL构造,但是你可以干掉@Mgr + @DefTrader with one of these workarounds ~GOTO的重复评估:(

此外,重新考虑@DefTrader的增量可能是一个好主意,即(select MAX(DEF_TRADER_ID) + 1 from TS_DEF_TRADER),例如使用IDENTITY列或锁定的计数器模式 - 目前,代码不是并发安全的。