2013-08-30 41 views
1

我想寫一個查詢,它會給我關於給定的數據庫的列的某些關鍵信息,但到目前爲止我的查詢似乎返回一些奇怪的結果!我需要了解有關色譜柱尺寸,可空性,唯一性等方面的信息。information_schema視圖每列返回多個行

那麼,爲什麼每列都得到多個結果呢?

SELECT 
C.COLUMN_NAME AS COLUMN_NAME, 
C.TABLE_NAME AS TABLE_NAME, 
C.CHARACTER_MAXIMUM_LENGTH AS CHARACTER_MAXIMUM_LENGTH, 
C.COLUMN_DEFAULT AS COLUMN_DEFAULT, 
C.DATA_TYPE AS DATA_TYPE, 
C.IS_NULLABLE AS IS_NULLABLE, 
CASE WHEN EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
AND CONSTRAINT_NAME = CC.CONSTRAINT_NAME) THEN 1 ELSE 0 END AS IS_PRIMARY_KEY, 
CASE WHEN EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'UNIQUE' 
AND CONSTRAINT_NAME = CC.CONSTRAINT_NAME) THEN 1 ELSE 0 END AS IS_UNIQUE, 
C.NUMERIC_PRECISION AS NUMERIC_PRECISION, 
C.NUMERIC_SCALE AS NUMERIC_SCALE, 
FK.TABLE_NAME AS FOREIGN_KEY_TABLE_NAME, 
FK.COLUMN_NAME AS FOREIGN_KEY_COLUMN_NAME 

FROM INFORMATION_SCHEMA.COLUMNS C 
LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE CC 
ON C.COLUMN_NAME = CC.COLUMN_NAME 
AND C.TABLE_NAME = CC.TABLE_NAME 
LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC 
ON CC.CONSTRAINT_NAME = TC.CONSTRAINT_NAME 

LEFT OUTER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC 
ON TC.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 
LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE FC 
ON RC.UNIQUE_CONSTRAINT_NAME = FC.CONSTRAINT_NAME 

LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE FK 
ON FC.COLUMN_NAME = FK.COLUMN_NAME 
AND FC.TABLE_NAME = FK.TABLE_NAME 
WHERE COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME, 'IsComputed') = 0 
AND TC.CONSTRAINT_TYPE = 'FOREIGN KEY' 
+0

是的,對不起,您對,刪除 – Yaroslav

+0

@Yaroslav沒有問題。我必須說,編碼風格看起來讓人想起MS/Sybase/Oracle。 :) – IMSoP

+0

說實話,我通常只是大寫我的關鍵字。 :) –

回答

2

你可能有每列一個以上的約束,因此,如果您使用含有限制信息的意見加入,你會得到多個行,一個用於在列每個約束。

另一個原因可能是相同的列名和表名出現在不同的模式中。

您可以檢查與下面的查詢,這只是表明你出現一次以上的列重複:

WITH a as(
    SELECT 
    C.COLUMN_NAME AS COLUMN_NAME, 
    C.TABLE_NAME AS TABLE_NAME, 
    C.CHARACTER_MAXIMUM_LENGTH AS CHARACTER_MAXIMUM_LENGTH, 
    C.COLUMN_DEFAULT AS COLUMN_DEFAULT, 
    C.DATA_TYPE AS DATA_TYPE, 
    C.IS_NULLABLE AS IS_NULLABLE, 
    CASE WHEN EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE  CONSTRAINT_TYPE = 'PRIMARY KEY' 
    AND CONSTRAINT_NAME = CC.CONSTRAINT_NAME) THEN 1 ELSE 0 END AS IS_PRIMARY_KEY, 
    CASE WHEN EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE  CONSTRAINT_TYPE = 'UNIQUE' 
    AND CONSTRAINT_NAME = CC.CONSTRAINT_NAME) THEN 1 ELSE 0 END AS IS_UNIQUE, 
    C.NUMERIC_PRECISION AS NUMERIC_PRECISION, 
    C.NUMERIC_SCALE AS NUMERIC_SCALE, 
    FK.TABLE_NAME AS FOREIGN_KEY_TABLE_NAME, 
    FK.COLUMN_NAME AS FOREIGN_KEY_COLUMN_NAME 

    FROM INFORMATION_SCHEMA.COLUMNS C 
    LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE CC 
    ON C.COLUMN_NAME = CC.COLUMN_NAME 
    AND C.TABLE_NAME = CC.TABLE_NAME 
    LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC 
    ON CC.CONSTRAINT_NAME = TC.CONSTRAINT_NAME 

    LEFT OUTER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC 
    ON TC.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 
    LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE FC 
    ON RC.UNIQUE_CONSTRAINT_NAME = FC.CONSTRAINT_NAME 

    LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE FK 
    ON FC.COLUMN_NAME = FK.COLUMN_NAME 
    AND FC.TABLE_NAME = FK.TABLE_NAME 
    WHERE COLUMNPROPERTY(OBJECT_ID(C.TABLE_SCHEMA + '.' + C.TABLE_NAME), C.COLUMN_NAME,  'IsComputed') = 0 
    AND TC.CONSTRAINT_TYPE = 'FOREIGN KEY' 
), b as (
    SELECT COLUMN_NAME, TABLE_NAME 
     FROM a 
    GROUP BY COLUMN_NAME, TABLE_NAME 
    HAVING count(*) > 1 
) 
SELECT a.* 
    FROM a JOIN b ON a.COLUMN_NAME = b.COLUMN_NAME AND a.TABLE_NAME = b.TABLE_NAME 

的CTE a正是從上面查詢。

+0

啊,但我會假設'AND TC.CONSTRAINT_TYPE ='FOREIGN KEY''會限制返回的約束。一列不能同時有兩個外鍵,或者至少不在我的數據庫中! –

+0

雖然列可能是多個外鍵的目標,並且列出了這些方法的信息? – IMSoP

0

無論何時將JOIN添加到查詢中,該關係都有可能是一對多的,因此會將結果乘以。你在這裏有5 JOIN,所以大概其中一個陷入了這種情況。

我的猜測是多個約束條件可以應用於單個列,而且您沒有篩選出足夠的可能性來實現這種情況。

關鍵是看看你得到的結果,看看「重複」行中實際上有什麼不同。我有時使用像SELECT C.*, '--' as [--], CC.*, '--' as [--], ...這樣的查詢來顯示所有連接表的所有列。 (as [--]將在Postgres中爲as "--",在MySQL中爲'--`。)

+0

另外:任何人都知道如何在SO的格式化語法中輸出'code span'中間的文字'? – IMSoP