2017-04-24 10 views
0

私は多言語データベースを設定しています(実際はそれより複雑ですが、単純なままです)。変換可能なデータはFactというテーブルに格納されます。データはFactLinkというテーブルからリンクされています(FactLinkIDという単一の列のみがテーブル内の複数の列によって参照されていますが、FactLinkテーブルはデータが独自のセットを構成するときに間接的に参照されることがあります。 、メタデータのオフセット行を持つ再帰的CTE(Information_Schemaから)

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とのマッチで私に行を取得しません。

多分私はこれで寝るとき、私はそれを考え出しました。しかし、いくつかの指針が役立ちます。

ありがとうございます!

UPDATE:

これは、私が思い付くことが最高です。それは私の基準に正確には合わないが、当初計画していた以上の欲求不満を見つけるので、実際には少し上手くいく。これにより、Allテーブルも参照するテーブルの列がFactLinkになります。

;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

ここで私がテストした2つのシナリオです:CTEを使用せずに

を: 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 [email protected] 
    --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) 
+0

おかげでこの問題に取り組む時間。しかし、あなたのソリューションは '@ FactLinkPKConstraint'への参照をすべて取得します。つまり、別のテーブルであれば、 'All2'が' @ FactLinkPKConstraint'を参照しているとしましょう。 '@ FactLinkPKConstraint'を参照する' All'からの列を取得するか、そのサブテーブルの1つがそれを参照する場合にのみ、それらを必要とします。 – Jon49

関連する問題