3

我目前正在尝试通过在 C# 中调用以下 SQL 来检索每个表的表名和主键。这是我迄今为止尝试过的:

SELECT t.TABLE_NAME As 'Table Name',
       Keys.COLUMN_NAME AS 'Primary Key'
FROM INFORMATION_SCHEMA.TABLES t 
left outer join INFORMATION_SCHEMA.TABLE_CONSTRAINTS Constraints
         on  t.TABLE_NAME = Constraints.Table_name 
         and t.Table_Schema = Constraints.Table_Schema 
left outer join INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS Keys 
         ON  Constraints.TABLE_NAME = Keys.TABLE_NAME 
         and Constraints.CONSTRAINT_NAME = Keys.CONSTRAINT_NAME 
         and Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY'

问题是如果表没有主键,我希望结果只包含一个“空”条目。虽然它正在工作,但由于某种原因,结果包含“薪水”表的副本,如下所示。Salary 和Employees 表都有主键,而“Test”表没有:

我怎样才能摆脱第三条记录?

编辑:我现在已经尝试过了,它似乎有效。这样做有什么缺点吗?

SELECT T.TABLE_NAME As 'Table Name'
    ,       (
            Select K1.COLUMN_NAME
            From INFORMATION_SCHEMA.TABLE_CONSTRAINTS As C1
                Join INFORMATION_SCHEMA.KEY_COLUMN_USAGE As K1
                    On C1.TABLE_SCHEMA = K1.TABLE_SCHEMA
                        And C1.TABLE_NAME = K1.TABLE_NAME 
                        And C1.CONSTRAINT_NAME = K1.CONSTRAINT_NAME 
            Where C1.CONSTRAINT_TYPE = 'PRIMARY KEY'
                And T.TABLE_SCHEMA = C1.TABLE_SCHEMA 
                And T.TABLE_NAME = C1.TABLE_NAME 
            )As PrimaryKeyColumns
FROM INFORMATION_SCHEMA.TABLES As T 
4

4 回答 4

2

尝试替换此条件Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY'

SELECT t.TABLE_NAME As 'Table Name',
       Keys.COLUMN_NAME AS 'Primary Key'
FROM INFORMATION_SCHEMA.TABLES t 
left outer join INFORMATION_SCHEMA.TABLE_CONSTRAINTS Constraints
         on  t.TABLE_NAME = Constraints.Table_name 
         and t.Table_Schema = Constraints.Table_Schema  
         and Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY'       
left outer join INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS Keys 
         ON  Constraints.TABLE_NAME = Keys.TABLE_NAME 
         and Constraints.CONSTRAINT_NAME = Keys.CONSTRAINT_NAME 
于 2012-09-10T19:20:01.693 回答
1

您应该考虑您的 PK 有多列。您可以通过更改为子查询来做到这一点:

SELECT T.TABLE_NAME As 'Table Name'
    ,   Stuff(
            (
            Select ', ' + K1.COLUMN_NAME
            From INFORMATION_SCHEMA.TABLE_CONSTRAINTS As C1
                Join INFORMATION_SCHEMA.KEY_COLUMN_USAGE As K1
                    On C1.TABLE_SCHEMA = K1.TABLE_SCHEMA
                        And C1.TABLE_NAME = K1.TABLE_NAME 
                        And C1.CONSTRAINT_NAME = K1.CONSTRAINT_NAME 
            Where C1.CONSTRAINT_TYPE = 'PRIMARY KEY'
                And T.TABLE_SCHEMA = C1.TABLE_SCHEMA 
                And T.TABLE_NAME = C1.TABLE_NAME 
            For Xml Path(''), type
            ).value('.', 'nvarchar(max)')
            , 1, 2, '') As PrimaryKeyColumns
FROM INFORMATION_SCHEMA.TABLES As T 

顺便说一句,如果您真的想对 TABLES 视图使用联接,则需要嵌套联接。问题是您有两个外连接,并且外键中的列正在输出中生成行。应该注意的是,与前面提到的子查询方法相比,以下方法的缺点是,如果主键由多列组成,您将获得多行。也就是说,您可以在 SQL Server 中嵌套联接,以便它首先处理内部联接、内部联接,然后处理外部联接:

SELECT T.TABLE_NAME As 'Table Name'
    , Keys.COLUMN_NAME AS 'Primary Key'
FROM INFORMATION_SCHEMA.TABLES As T
    Left Join( INFORMATION_SCHEMA.TABLE_CONSTRAINTS Constraints
        Join INFORMATION_SCHEMA.KEY_COLUMN_USAGE As Keys 
            On  Constraints.TABLE_SCHEMA = Keys.TABLE_SCHEMA 
                And Constraints.TABLE_NAME = Keys.TABLE_NAME 
                And Constraints.CONSTRAINT_NAME = Keys.CONSTRAINT_NAME 
                And Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY' )
        On T.TABLE_SCHEMA = Constraints.TABLE_SCHEMA 
            And T.TABLE_NAME = Constraints.TABLE_NAME 

在此查询中,首先处理和之间的内连接,TABLE_CONSTRAINTS并将KEY_COLUMN_USAGE结果组合在左连接中TABLES查看。

于 2012-09-10T19:08:37.933 回答
1

我看到您已经接受了您的答案,但如果有人感兴趣,这是一个纯 C# 答案:

static void Main(string[] args)
{
    Server server = new Server("serverName");
    Database db = server.Databases["DatabaseName"];

    string tableName = "TableName";

    Table table = db.Tables[tableName];

    if (table != null)
    {
        Console.WriteLine("Table:  {0}", tableName);
        if (table.Columns.Count > 0)
        {
            Console.WriteLine("  Primary Key Columns:");
            foreach (Column column in table.Columns)
            {
                if (column.InPrimaryKey)
                {
                    Console.WriteLine(string.Format("    {0}", column.Name));
                }
            }
        }
        else
        {
            Console.WriteLine("  No primary key.", tableName);
        }
    }
    Console.WriteLine("Press ENTER to exit...");
    Console.ReadLine();
}

您将需要添加对 Microsoft.SqlServer.Management.Sdk.Sfc 和 Microsoft.SqlServer.Smo 程序集的引用并导入适当的命名空间。

于 2012-09-10T20:30:27.870 回答
0
select
  TABLE_SCHEMA, 
  TABLE_NAME 
from 
  INFORMATION_SCHEMA.TABLES
where 
  objectproperty(object_id(table_name),'TableHasPrimaryKey')=0
ORDER BY 
  TABLE_NAME
于 2012-09-10T19:03:00.443 回答