SQL Query获取misc列信息

Yah*_*hya 11 sql t-sql sql-server

我需要编写一个查询,我可以获取有关所有列的信息(包含数据类型),也可以知道哪些列PK/FK.因为FK,需要额外的信息,如其他表.我有查询可行,但看起来有点矫枉过正.

这可以做得更好吗?我不喜欢子查询加入它.它必须是一个查询,不能通过SP.

我的例子是反对的Northwind(FK我正在测试一些额外的关系)

SELECT 
    t.name AS TableName, 
    t.object_id AS TableObjectId,
    tCols.column_name AS ColumnName, 
    tCols.data_type AS ColumnDataType, 
    ISNULL(tCols.numeric_scale, 0) AS ColumnDecimalPlaces,
    CASE tConstraints.CONSTRAINT_TYPE
        WHEN 'PRIMARY KEY'
            THEN '1'
            ELSE '0'
    END AS ISPK, 
    CASE tConstraints.CONSTRAINT_TYPE
        WHEN 'FOREIGN KEY'
            THEN '1'
            ELSE '0'
    END AS ISFK, 
    tConstraints.CONSTRAINT_TYPE,
    tConstraints.CONSTRAINT_NAME,
    fkInfo.FK_name,
    fkInfo.PK_column,
    fkInfo.PK_table,
    fkInfo.PK_name
FROM sys.objects t
LEFT JOIN information_schema.columns tCols ON tCols.TABLE_NAME = t.name 
LEFT JOIN (
    SELECT  
        tc.CONSTRAINT_NAME, 
        tc.TABLE_NAME, 
        tc.CONSTRAINT_TYPE, 
        kcu.COLUMN_NAME
    FROM information_schema.table_constraints tc
    INNER JOIN  information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
) AS tConstraints
     ON t.name = tConstraints.TABLE_NAME
    AND tCols.column_name = tConstraints.COLUMN_NAME
LEFT JOIN (
    SELECT
        o1.name AS FK_table,
        c1.name AS FK_column,
        fk.name AS FK_name,
        o2.name AS PK_table,
        c2.name AS PK_column,
        pk.name AS PK_name
    FROM sys.objects o1
    INNER JOIN sys.foreign_keys fk
        ON o1.object_id = fk.parent_object_id
    INNER JOIN sys.foreign_key_columns fkc
        ON fk.object_id = fkc.constraint_object_id
    INNER JOIN sys.columns c1
         ON fkc.parent_object_id = c1.object_id
        AND fkc.parent_column_id = c1.column_id
    INNER JOIN sys.columns c2
         ON fkc.referenced_object_id = c2.object_id
        AND fkc.referenced_column_id = c2.column_id
    INNER JOIN sys.objects o2
        ON fk.referenced_object_id = o2.object_id
    INNER JOIN sys.key_constraints pk
         ON fk.referenced_object_id = pk.parent_object_id
        AND fk.key_index_id = pk.unique_index_id
) AS fkInfo ON t.name = fkInfo.FK_table
    AND tCols.column_name = fkInfo.FK_column
WHERE t.name = 'Products'
ORDER BY 3
Run Code Online (Sandbox Code Playgroud)

这是输出

Ada*_*nko 7

尝试我的查询(我在分隔列中有pk_name和fk_name,所以不需要大小写),它在系统视图上,并且速度很快:

with 
  pk as (select pki.object_id, pki.column_id, _pk.name 
      from sys.index_columns pki  
      join sys.key_constraints _pk 
      on _pk.unique_index_id = pki.index_id and _pk.parent_object_id = pki.object_id
      where 1=1),
  fk as (select fkc.parent_object_id, fkc.parent_column_id, fk.name name, pkt.name pk_table, pkc.name pk_column, pkc.object_id, pkc.column_id
    from sys.foreign_keys as fk
    join sys.tables pkt
    on pkt.object_id = fk.referenced_object_id
    join sys.foreign_key_columns as fkc
    on fkc.constraint_object_id = fk.object_id
    join sys.columns as pkc
    on pkc.object_id = fkc.referenced_object_id and pkc.column_id = fkc.referenced_column_id
    where 1=1)
select t.name TableName
, t.object_id TableObjectId
, c.column_id CId
, c.name AS ColumnName
, typ.name AS ColumnDataType
, c.is_identity
, c.precision
, c.scale
, pk.name pk_name
, fk.name fk_name
, fk.pk_table
, fk.pk_column
, fkpk.name pk_for_fk
from sys.tables as t
inner join sys.columns as c on t.object_id = c.object_id
inner join sys.types as typ on typ.user_type_id = c.user_type_id
left join pk on pk.object_id = t.object_id and pk.column_id = c.column_id
left join fk on fk.parent_object_id = c.object_id and fk.parent_column_id = c.column_id
left join pk as fkpk on fkpk.object_id = fk.object_id and fkpk.column_id = fk.column_id
WHERE t.name = 'Products'
Run Code Online (Sandbox Code Playgroud)


Mic*_*een 5

但它看起来有点矫枉过正

如果你想从很多表中提取很多值,那么你最终会得到一个大的查询.这就是它的工作原理.随着这些事情的发展,这一点并不那么大.

您是否担心SQL Server无法处理它?不要,它可以.性能?您可以做很多事情,因为这些是内部目录表.重构选项是有限的,因为您需要一个语句并且SP已经用完.将其作为内联表值函数包装可能会有所帮助,但如果出错则可能会损害性能.

如果您只想清楚SQL的表示,那么子查询可以写成CTE,转换为视图(或函数,但不是)或unnested,因此所有连接都处于相同的缩进级别.然而,后者更容易模糊而不是阐明.

总而言之,我认为您最好的希望是编写干净的代码 - 良好的缩进,一致的命名,合理的别名等 - 并在评论中描述目标和技术.你所呈现的内容实现了大部分.