我有一张桌子:
CREATE TABLE [dbo].[DeliveryData](
[DeliveryId] [int] IDENTITY(1,1) NOT NULL,
...
CONSTRAINT [PK_DeliveryData] PRIMARY KEY CLUSTERED
(
[DeliveryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
代码:
public void GetPrimaryKeyColumns(SqlConnection conn) {
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select * from [dbo].[DeliveryData]";
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly);
DataTable schema = reader.GetSchemaTable();
DataColumn[] columns = schema.PrimaryKey;
...
}
cmd,reader和schema看起来都很好,但是列的结尾是零长度数组。不应该包含" DeliveryId"?如何获得主要列" DeliveryId"?
感谢您的帮助!
布雷克
答案 0 :(得分:0)
架构表不是DeliveryData
表。您必须检查IsKey
列为true的架构表,然后抓取ColumnName
字段。然后,您可以使用它在常规数据表中查找实际列。
更新
GetSchemaTable()
会返回元数据信息的数据表,您可以在文档中看到:https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getschematable(v=vs.110).aspx
如果要运行查询,最终返回的DataTable中的行数与查询中的列数一样多。这是我从数据库中的测试表中获得的模式表的部分屏幕截图。请注意,每列现在都是一行,IsKey字段将告诉您列是否为键列:
如果您想在DataTable上使用PrimaryKey
属性,请不要使用GetSchemaTable()
,只需使用SqlDataAdapter
填充常规DataTable。
更新2
使用CommandBehavior.KeyInfo
代替CommandBehavior.SchemaOnly
使用SMO
using Microsoft.SqlServer.Management.Smo;
....
Server svr = new Server("Your Server Name");
Database db = svr.Databases["Your Database Name"];
Table tbl = db.Tables["DeliveryData"];
foreach (Column c in tbl.Columns)
{
bool isAKeyColumn = c.InPrimaryKey
}
答案 1 :(得分:0)
使用GetSchemaTable,MSSQL在所有情况下都不会返回正确的主键信息。 (并不太令人惊讶。例如,几乎所有数据库供应商都支持ODBC比MS更好。)但是,以下查询确实有效:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = 'dbo'
AND tc.TABLE_NAME = 'DeliveryData'
ORDER BY ORDINAL_POSITION;
答案 2 :(得分:0)
这是一个完整的解决方案:
public List<string> GetPrimaryKeyColumns(DbConnection conn, string schema, string table) {
DbCommand cmd = conn.CreateCommand();
DbParameter p = cmd.CreateParameter();
p.ParameterName = "@schema";
p.Value = schema;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
p = cmd.CreateParameter();
p.ParameterName = "@table";
p.Value = table;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
cmd.CommandText = @"SELECT kcu.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
-- AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG doesn't work on MySQL
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = @schema
AND tc.TABLE_NAME = @table
ORDER BY ORDINAL_POSITION";
DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo);
List<string> res = new List<string>();
while (reader.Read()) {
var str = reader[0];
if (str != System.DBNull.Value)
res.Add((string) str);
}
reader.Dispose();
cmd.Dispose();
return res;
}