2013-08-30 39 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