Sql 带有偏移行的递归CTE,用于来自信息架构的元数据
我建立了一个多语种的数据库(实际上比这更复杂,但我保持简单)。可翻译数据放在名为Sql 带有偏移行的递归CTE,用于来自信息架构的元数据,sql,sql-server,tsql,recursion,information-schema,Sql,Sql Server,Tsql,Recursion,Information Schema,我建立了一个多语种的数据库(实际上比这更复杂,但我保持简单)。可翻译数据放在名为Fact的表中。数据从名为FactLink的表链接到(只有一列名为FactLinkID。一个表中的多列正在引用该数据。但有时,当数据构成自己的集合时,可以间接引用FactLink表。例如 CREATE TABLE FactLink ( FactLinkID INT NOT NULL IDENTITY(1,1) Primary KEY ) CREATE TABLE [Language] ( LanguageID IN
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
表的所有列。获取直接链接很容易。我想我需要通过递归CTE
获取间接链接。但我不确定如何实现。我对递归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
以下是我已经测试过的两个场景: 不使用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)
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)
使用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)
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)
感谢您花时间解决此问题。但是您的解决方案将获取对
@FactLinkPKConstraint
的所有引用。也就是说,如果是另一个表,比如说所有2
引用@FactLinkPKConstraint
,那么它也将获取这些引用。我需要它们只获取引用所有中的列LinkPKConstraint
或其子表中的一个子表引用它。