非常感谢可以提供的任何帮助。
我有以下两个表
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。
答案 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
列或锁定的计数器模式 - 目前,代码不是并发安全的。