我需要从头开始加载50多个表,这些表有很多FK约束,现在我只丢弃所有FK,以任何顺序加载表(我的数据符合所有FK),然后添加FK。 有什么方法可以做到这一点,我可以看到FK定义的顺序是至关重要的,所以让我们看看我的样本,这是正确的方法吗?
ALTER TABLE CUST ADD CONSTRAINT CUS_BatchID_FK FOREIGN KEY (BatchID) REFERENCES Batch(BatchID);
ALTER TABLE CYCLE ADD CONSTRAINT CL_BatchID_FK FOREIGN KEY (BatchID) REFERENCES Batch(BatchID);
ALTER TABLE QOUTE ADD CONSTRAINT QT_BatchID_FK FOREIGN KEY (BatchID) REFERENCES Batch(BatchID);
ALTER TABLE MD_LOC ADD CONSTRAINT MLOC_FK FOREIGN KEY (LOC_ID) REFERENCES LOC(LOC_ID);
ALTER TABLE CUST ADD CONSTRAINT CUST_PROV_FK FOREIGN KEY (PROV_ID) REFERENCES PROVIDER(PROV_ID);
ALTER TABLE REFER ADD CONSTRAINT RF_CUST_ID_FK FOREIGN KEY (CUST_ID) REFERENCES CUST(CUST_ID);
/*--------------------
1. load Batch
2. load LOC
2a. Load MD_LOC
3. load PROVIDER
3a. load CUST
.....
即我首先加载没有FK的表,然后按顺序进行,我测试了几个表并且它可以工作,只是想确认在我使用其余表之前是否有任何遗漏。
答案 0 :(得分:3)
通过考虑父/子关系之类的外键,可以实现表插入的顺序,在T-SQL中,我们可以对这种层次结构使用递归公用表表达式。以下将列出将遵守FK约束的表插入的顺序:
WITH
ctefk (pktable, fktable) AS (
SELECT
s1.name + '.' + o1.name AS pktable
, ISNULL(s2.name + '.' + o2.name, '') as fktable
FROM sys.objects o1
LEFT OUTER JOIN sys.sysforeignkeys fk ON o1.object_id = fk.fkeyid
LEFT OUTER JOIN sys.objects o2 ON o2.object_id = fk.rkeyid
LEFT OUTER JOIN sys.schemas s1 ON o1.schema_id = s1.schema_id
LEFT OUTER JOIN sys.schemas s2 ON o2.schema_id = s2.schema_id
WHERE o1.type_desc = 'user_table'
AND o1.name NOT IN ('dtproperties', 'sysdiagrams')
GROUP BY
s1.name + '.' + o1.name
, ISNULL(s2.name + '.' + o2.name, '')
),
cterec (tablename, fkcount) AS (
SELECT
tablename = pktable
, fkcount = 0
FROM ctefk
UNION ALL
SELECT
tablename = pktable
, fkcount = 1
FROM ctefk
CROSS APPLY cteRec
WHERE ctefk.fktable = cteRec.tablename
AND ctefk.pktable <> cteRec.tablename
)
SELECT
TableName
, insertorder = DENSE_RANK() OVER (ORDER BY MAX(fkcount) ASC)
FROM (
SELECT
tablename = fktable
, fkcount = 0
FROM ctefk
GROUP BY
fktable
UNION ALL
SELECT
tablename = tablename
, fkcount = SUM(ISNULL(fkcount, 0))
FROM cterec
GROUP BY
tablename
) x
WHERE x.tablename <> ''
GROUP BY
tablename
ORDER BY
insertorder ASC
, TableName ASC
;
注意:任何具有FK的表本身(显然)仍然是一个问题,希望这根本不会发生。上面的查询会跳过这样一个条件,因为它会导致递归循环。