Где я могу проверить коды типов ключей SQL?

На основе коллекций схем SQL Server Я хотел бы использовать sqlConnection.GetSchema("IndexColumns");, чтобы определить, какие столбцы являются первичными ключами.

Я провел несколько экспериментов и обнаружил, что с помощью вышеуказанного запроса я получаю таблицу данных со следующей информацией:

table_catalog   table_schema   table_name              column_name ordinal_position   KeyType   index_name
---------------------------------------------------------------------------------------------------------------------------
TestDb          dbo            TestTableWithPrimaryKey     Id              1             56      PK_TestTableWithPrimaryKey 

Я предполагаю, что KeyType = 56 означает первичный ключ, но это выводится только из этого определения таблицы:

CREATE TABLE [dbo].[TestTableWithPrimaryKey]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Foo] [nvarchar](50) NOT NULL,

    CONSTRAINT [PK_TestTableWithPrimaryKey] 
        PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]

Я хотел бы убедиться, что мой вывод верен, прежде чем использовать его в каком-либо проекте. Есть ли место, где я могу получить все типы ключей?


person t3chb0t    schedule 24.12.2017    source источник


Ответы (2)


Глядя на внутренний SqlMetaDataFactory, вызов sqlConnection.GetSchema("IndexColumns"); выполняет поиск команды для выполнения, найденной в файле ресурсов System.Data.SqlClient.SqlMetaData.xml, и это покажет нам запись IndexColumns

 <MetaDataCollections>
    <CollectionName>IndexColumns</CollectionName>
    <NumberOfRestrictions>5</NumberOfRestrictions>
    <NumberOfIdentifierParts>4</NumberOfIdentifierParts>
    <PopulationMechanism>SQLCommand</PopulationMechanism>
    <PopulationString>EXEC sys.sp_indexcolumns_managed @Catalog, @Owner, @Table, @ConstraintName, @Column</PopulationString>
    <MinimumVersion>10.00.0000</MinimumVersion>
  </MetaDataCollections>

Это означает, что он выполнит EXEC sys.sp_indexcolumns_managed. Эта хранимая процедура покажет с помощью EXEC sp_helptext 'sys.sp_indexcolumns_managed', что она выбирает из sys.spt_indexcolumns_view_managed, и это представление определяется как:

select distinct 
    db_Name() as constraint_catalog, 
    constraint_schema = SCHEMA_NAME(o.schema_id), 
    constraint_name = x.name, 
    table_catalog  = db_name(), 
    table_schema = SCHEMA_NAME(o.schema_id), 
    table_name = o.name, 
    column_name = c.name, 
    ordinal_position = xc.key_ordinal, 
    KeyType  = c.system_type_id, 
    index_name = x.name 
from 
    sys.objects o INNER JOIN sys.indexes x ON
        (
            o.object_id = x.object_id AND
            o.type in ('U')
        )  INNER JOIN 
    sys.index_columns xc ON
        (
            xc.object_id = x.object_id AND
            xc.index_id = x.index_id
        ) INNER JOIN
    sys.columns c ON
        (
            o.object_id = c.object_id AND
            xc.column_id = c.column_id
        )

(Вы можете найти его определение с помощью SELECT OBJECT_DEFINITION(OBJECT_ID('sys.sp_indexcolumns_managed'));, поскольку оно является частью База данных ресурсов)

Теперь мы видим, что столбец KeyType проецируется на sys.columns.system_type_id, что задокументировано в sys.columns как

ID системного типа столбца.

и Где найти метаданные Sql Server для типов данных столбцов? подробности о том, что объединение с sys.types даст вам информацию о типе столбца.

Вооружившись этой информацией, мы уже можем заключить, что я думаю, KeyType = 56 означает первичный ключ, это неверно и работает.

select name, system_type_id, user_type_id, schema_id, max_length,  precision scale
from sys.types 
where system_type_id = 56

вернется

name system_type_id user_type_id schema_id max_length scale 
---- -------------- ------------ --------- ---------- ----- 
int  56             56           4         4          10    

и это тип столбца, а не первичный ключ.

Кажется, нет надежного способа найти первичный ключ с помощью вызова GetSchema, AFAICT. Используйте запрос, предоставленный Дэном Гузманом.

person rene    schedule 24.12.2017
comment
Это действительно потрясающий детектив. Я не так хорошо знаю SQL, поэтому я бы не продвинулся даже наполовину - и я многому научился из вашего ответа. Жаль, что они выбрали такое запутанное название KeyType, которое в других местах правильно называется DataType. Я приму этот ответ, потому что он идет к самому низу магического числа 56, которое я хотел проверить, а также показывает несколько новых инструментов, как сделать это самостоятельно в будущем - хотя и как Plan B решение Мне придется переключиться на то, что предложил @DanGuzman, поскольку моя теория оказалась ложной. - person t3chb0t; 25.12.2017

Столбец KeyType сопоставляется с типом данных столбца, перечисленным столбцом system_type представления каталога SQL Server sys.types (значение 56 равно int). Следовательно, это не поможет идентифицировать столбец как элемент первичного ключа.

Существует несколько способов получения столбцов первичного ключа SQL Server, включая SMO и запросы представления каталога. Вот один пример получения всех столбцов первичного ключа в базе данных для SQL Server. Если вам необходимо поддерживать несколько продуктов СУБД, вы можете вместо этого использовать представления каталога INFORMATION_SCHEMA для продуктов СУБД, которые реализуют эти стандартные представления ANSI.

SELECT 
      OBJECT_SCHEMA_NAME(i.object_id) AS SchemaName
    , OBJECT_NAME(i.object_id) AS TableName
    , c.name AS ColumnName
    , ic.key_ordinal AS KeyOrdinal
FROM sys.key_constraints AS kc
JOIN sys.indexes AS i ON i.object_id = kc.parent_object_id AND kc.name = i.name
JOIN sys.index_columns AS ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
JOIN sys.columns AS c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
WHERE kc.type_desc = N'PRIMARY_KEY_CONSTRAINT'
ORDER BY
      SchemaName
    , TableName
    , KeyOrdinal;
person Dan Guzman    schedule 24.12.2017