我设置了多语种数据库(实际上它比这更复杂 - 但我保持简单)。可转换数据放在名为Fact
的表中。数据链接到一个名为FactLink
的表(只有一个名为FactLinkID
的列。它被表中的多个列引用。但有时FactLink
表可以是当数据组成它自己的集合时间接引用。例如,
CREATE TABLE FactLink
( FactLinkID INT NOT NULL IDENTITY(1,1) Primary KEY
)
CREATE TABLE [Language]
( LanguageID INT NOT NULL IDENTITY(1,1) Primary KEY
, Code varchar(50) not null
)
CREATE TABLE Fact
( FactLinkID INT NOT NULL
, LanguageID INT NOT NULL
, PRIMARY KEY CLUSTERED (FactLinkID ASC, LanguageID ASC)
, CONSTRAINT fk_Fact_FactLinkID FOREIGN KEY (FactLinkID) REFERENCES dbo.FactLink (FactLinkID)
, CONSTRAINT fk_Fact_LanuageID FOREIGN KEY (LanguageID) REFERENCES dbo.[Language] (LanguageID)
)
CREATE TABLE LimitedTranslateableItem
( LimitedTranslateableItemID INT NOT NULL PRIMARY KEY
, [Order] INT NOT NULL
, CONSTRAINT fk_LimitedTranslateableItem_Table1ID FOREIGN KEY (LimitedTranslateableItemID) REFERENCES dbo.FactLink (FactLinkID)
)
CREATE TABLE [All]
( AllID INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, TranslateableItemID INT NOT NULL
, LimitedTranslateableItemID INT NOT NULL
, CONSTRAINT fk_All_TranslateableItemID FOREIGN KEY (TranslateableItemID) REFERENCES dbo.FactLink (FactLinkID)
, CONSTRAINT fk_All_LimitedTranslateableItemID FOREIGN KEY (LimitedTranslateableItemID) REFERENCES dbo.LimitedTranslateableItem (LimitedTranslateableItemID)
)
我想直接或间接地获取引用FactLink
表的所有列。获得直接链接很容易。我想我需要通过Recursive CTE
获得间接链接。但我不知道该怎么做。我是Recursive CTE
的新手。这也是问题的一部分但是,对FactLink
约束的引用与匹配约束的行不同。
-- Get constraint for FactLink table
DECLARE @FactLinkPKConstraint sysname
SELECT @FactLinkPKConstraint = t.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t
WHERE t.TABLE_NAME = 'FactLink'
AND t.CONSTRAINT_TYPE = 'PRIMARY KEY'
SELECT
t.TABLE_SCHEMA
, t.TABLE_NAME
, t.CONSTRAINT_NAME
, t.COLUMN_NAME
, rc.UNIQUE_CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE t.TABLE_NAME = 'All'
AND t.TABLE_SCHEMA = 'dbo'
AND rc.UNIQUE_CONSTRAINT_NAME = @FactLinkPKConstraint
这是我到目前为止所拥有的:
;WITH CTE AS (
SELECT
t.TABLE_SCHEMA
, t.TABLE_NAME
, t.CONSTRAINT_NAME
, t.COLUMN_NAME
, rc.UNIQUE_CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE t.TABLE_NAME = 'All'
AND t.TABLE_SCHEMA = 'dbo'
UNION ALL
SELECT
t.TABLE_SCHEMA
, t.TABLE_NAME
, t.CONSTRAINT_NAME
, t.COLUMN_NAME
, rc.UNIQUE_CONSTRAINT_CATALOG
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE rc.UNIQUE_CONSTRAINT_NAME IN (
SELECT ct.UNIQUE_CONSTRAINT_NAME
FROM CTE ct
WHERE ct.UNIQUE_CONSTRAINT_NAME <> @FactLinkPKConstraint)
--AND t.TABLE_NAME NOT IN (SELECT c.TABLE_NAME FROM CTE c)
)
SELECT *
FROM CTE t
当然,由于Recursive CTE
无法在子查询中引用,因此无法正常工作。它并没有让我得到与FactLink
表约束匹配的行。
也许当我睡在这上面时,我已经弄清楚了。但是一些指示会有所帮助。
提前致谢!
更新
这是我能想到的最好的。它并不完全符合我的标准,但实际上有点好,因为它发现了比我原先计划的更多的依赖性。这将获得FactLink
表也引用的表的All
列。
;WITH AFactLinkPKConstraint AS (
SELECT t.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t
WHERE t.TABLE_NAME = 'FactLink'
AND t.CONSTRAINT_TYPE = 'PRIMARY KEY'
), APrimary AS (
SELECT *
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
WHERE t.CONSTRAINT_NAME IN (
SELECT DISTINCT rc.UNIQUE_CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE t.TABLE_NAME = 'All' )
)
SELECT *
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
AND rc.UNIQUE_CONSTRAINT_NAME = (SELECT pk.CONSTRAINT_NAME FROM AFactLinkPKConstraint pk)
JOIN APrimary p
ON p.TABLE_NAME = t.TABLE_NAME
AND p.TABLE_SCHEMA = t.TABLE_SCHEMA
答案 0 :(得分:0)
以下是我测试过的两个 Scenario :
不使用cte:
DECLARE @FactLinkPKConstraint sysname
SELECT @FactLinkPKConstraint = t.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t
WHERE t.TABLE_NAME = 'FactLink'
AND t.CONSTRAINT_TYPE = 'PRIMARY KEY'
SELECT
TABLE_SCHEMA
, TABLE_NAME
, CONSTRAINT_NAME
, COLUMN_NAME
, UNIQUE_CONSTRAINT_NAME from
(SELECT
t.TABLE_SCHEMA
, t.TABLE_NAME
, t.CONSTRAINT_NAME
, t.COLUMN_NAME
, rc.UNIQUE_CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE t.TABLE_NAME = 'All'
AND t.TABLE_SCHEMA = 'dbo'
UNION ALL
SELECT
t.TABLE_SCHEMA
, t.TABLE_NAME
, t.CONSTRAINT_NAME
, t.COLUMN_NAME
, rc.UNIQUE_CONSTRAINT_CATALOG
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME) as result
WHERE UNIQUE_CONSTRAINT_NAME =@FactLinkPKConstraint
--AND t.TABLE_NAME NOT IN (SELECT c.TABLE_NAME FROM CTE c)
使用cte:
DECLARE @FactLinkPKConstraint sysname
SELECT @FactLinkPKConstraint = t.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t
WHERE t.TABLE_NAME = 'FactLink'
AND t.CONSTRAINT_TYPE = 'PRIMARY KEY'
;with cte as
(
select @FactLinkPKConstraint as col1
),
FactLinkPKConstraint as
(
select * from cte
),result as
(
SELECT
t.TABLE_SCHEMA
, t.TABLE_NAME
, t.CONSTRAINT_NAME
, t.COLUMN_NAME
, rc.UNIQUE_CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE t.TABLE_NAME = 'All'
AND t.TABLE_SCHEMA = 'dbo'
UNION ALL
SELECT
t.TABLE_SCHEMA
, t.TABLE_NAME
, t.CONSTRAINT_NAME
, t.COLUMN_NAME
, rc.UNIQUE_CONSTRAINT_CATALOG
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE t
JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.CONSTRAINT_NAME = t.CONSTRAINT_NAME
)
select * from result where UNIQUE_CONSTRAINT_NAME = (select col1 from FactLinkPKConstraint)
--AND t.TABLE_NAME NOT IN (SELECT c.TABLE_NAME FROM CTE c)