2013-08-30 1 views
1

주어진 데이터베이스의 열에 대한 특정 핵심 정보를 제공하는 쿼리를 작성하려고하는데, 내 쿼리가 이상한 결과를 반환하는 것 같습니다! 열 크기, null 허용 여부, 고유성 등에 대해 알아야합니다.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 No prob. 코딩 스타일은 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 

열팽창 계수 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

관련 문제