2012-09-10 44 views
3

我目前正在尝试通过在C#中调用以下SQL来检索每个表的表名和主键。这是我到目前为止已经试过:如何获取表和主键,并在表没有主键时显示null?

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”表的副本,如下所示。薪酬与员工的表都有主键和“测试”表不:

How can I get rid of the 3rd record?

编辑:我试过这个,现在,它似乎工作。这样做有什么不利吗?

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 
+0

“工资”是否有一个约束? – Parado

+0

是的,还有一个外键 –

回答

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 
+0

这个伎俩!谢谢 :) –

0
select 
    TABLE_SCHEMA, 
    TABLE_NAME 
from 
    INFORMATION_SCHEMA.TABLES 
where 
    objectproperty(object_id(table_name),'TableHasPrimaryKey')=0 
ORDER BY 
    TABLE_NAME 
+0

这不是他要求的。他希望桌子PK中的表名和列名。如果表没有PK,只显示空。 – Josh

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 

顺便说一句,如果你真的想用加入到表视图,您需要嵌套联接。问题是你有两个外连接,而外键的列在你的输出中产生行。应该指出的是,与前面提到的子查询方法相比,以下方法的缺点是如果主键由多个列组成,您将获得多行。这就是说,你可以窝连接在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_CONSTRAINTSKEY_COLUMN_USAGE之间加入处理第一和结果在左连接到TABLES视图。

+0

请问什么是“nvarchar(max)”部分?我不完全理解查询 –

+0

@DotNET - “For Xml路径”将查询转换为Xml流。 ',type).value('。','nvarchar(max)')位确保结果正确处理Xml实体(例如,不会为'&'返回'&amp')。最后,'Stuff'函数用于删除第一个分隔符,它是两个字符:逗号和空格。 – Thomas

+0

如果我要删除那部分,是否会发生任何事情?请看看我对这个问题的编辑,看看我试过的是什么 –

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程序集并导入适当的名称空间。