Запрос на получение уникального индекса и первичных ключей таблицы MsSQL

SELECT sysobjects.xtype, syscolumns.name, sysindexkeys.indid, sysobjects.type
FROM
    syscolumns
LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id
LEFT JOIN sysindexkeys ON (
     syscolumns.id = sysindexkeys.id AND syscolumns.colid = sysindexkeys.colid
)
WHERE sysobjects.name = '{$table}'
AND sysindexkeys.indid IS NOT NULL
ORDER BY sysindexkeys.indid, sysindexkeys.keyno

На самом деле я использую следующий запрос, чтобы получить имя столбца и номер ключа.

Проблема в том, что моя таблица имеет 3 поля:

user_id
config_name
config_value

С первичным ключом на user_id И config_name.

Я ожидаю получить коллекцию:

[
  ['name' => 'user_id', 'keyno' => 1],
  ['name' => 'config_name', 'keyno' => 1]
]

Но я получаю:

[
  ['name' => 'user_id', 'keyno' => 1],
  ['name' => 'config_name', 'keyno' => 2]
]

Что я делаю не так?

изменить: я получаю те же странные результаты, используя таблицу с двумя индексами

таблица: project_image_id project_id project_image_src

PK для project_image_id И уникальный индекс для project_id И project_image_src

Ожидал:

[
  ['name' => 'project_image_id', 'keyno' => 1],
  ['name' => 'project_id', 'keyno' => 2]
  ['name' => 'project_image_src', 'keyno' => 2]
]

Но я получаю:

[
  ['name' => 'project_image_id', 'keyno' => 1],
  ['name' => 'project_id', 'keyno' => 1]
  ['name' => 'project_image_src', 'keyno' => 2]
]

person Community    schedule 23.02.2009    source источник


Ответы (4)


Мне это кажется правильным, ваш индекс имеет 2 столбца, user_id имеет позицию 1, а config_name имеет позицию 2.

Из BOL keyno: Позиция столбца в индексе

почему вы думаете, что они оба будут 1?

Вот, вам нужно было присоединиться к таблице sysobject, но по индексу, а не к самой таблице.

SELECT s2.xtype, syscolumns.name, sysindexkeys.indid, sysobjects.type
FROM
    syscolumns
LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id
LEFT JOIN sysindexkeys ON (
     syscolumns.id = sysindexkeys.id AND syscolumns.colid = sysindexkeys.colid
)
join sysobjects s2 on s2.parent_obj = sysindexkeys.id
WHERE sysobjects.name = '{$table}'
and s2.type = 'K'
AND sysindexkeys.indid IS NOT NULL
ORDER BY sysindexkeys.indid, sysindexkeys.keyno
person SQLMenace    schedule 23.02.2009
comment
Хорошо, так что indexid indid? Как я могу определить, является ли ключ первичным или уникальным индексом, а не простым индексом? - person ; 23.02.2009
comment
посмотрите на xtype в sysobjects PK = ограничение PRIMARY KEY (тип K) UQ = ограничение UNIQUE (тип K) - person SQLMenace; 23.02.2009
comment
Правильно, оба моих sysobjects.type и sysobjects.xtype имеют значение «U». - person ; 23.02.2009
comment
Я обновил свой запрос (вверху), и я получаю как type, так и xtype = 'U'. В документе, который вы мне прислали, я прочитал, что U означает стол? Что это значит? - person ; 23.02.2009
comment
Остался один маленький вопрос :) Как узнать, уникален ли этот ключ? - person ; 23.02.2009
comment
Первичный ключ всегда уникален, поэтому является уникальным ограничением, разница в том, что таблица может иметь только 1 PK и много уникальных ограничений, а уникальное ограничение допускает один NULL, в то время как PK вообще не допускает никаких нулей. - person SQLMenace; 23.02.2009
comment
Я знаю об этом, но даже если я установлю для индекса «Уникальный» значение false, я получу его в своем запросе. Я хотел бы знать, чтобы не отклонять уникальные индексы. - person ; 23.02.2009

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

Вариант 1:

Для определения уникального индекса используется следующая системная функция, сообщающая вам о состоянии конкретного индекса «Имя_индекса» в таблице «Имя_таблицы»:

SELECT INDEXPROPERTY(OBJECT_ID('TableName'),'IndexName','IsUnique')

Вариант 2:

Однако приведенный выше вопрос связан с желанием узнать, является ли COLUMN уникальным индексом. Это означает, что вам нужен список всех индексов, для которых рассматриваемый столбец является единственным столбцом в индексе. Таким образом, можно использовать такую ​​комбинацию:

-- Note: If a "1" appears in the select below, the index (and by extension, the column) is a unique index.


SELECT si.name, INDEXPROPERTY(x.TableID,si.name,'IsUnique') [IsUnique]
FROM sysindexes si
JOIN (SELECT OBJECT_ID('TableName') [TableID]) x  -- HERE IS YOUR TABLE NAME
  ON si.id = x.TableID
-- This restricts the selection to your column.
JOIN (
    SELECT id, indid 
    FROM sysindexkeys
    WHERE colid IN (
        -- For 2005 and up: SELECT COLUMNPROPERTY(OBJECT_ID('TableName'), 'ColumnName', 'ColumnId')
        SELECT colid
        FROM syscolumns
        WHERE name IN ('ColumnName')              -- HERE IS YOUR COLUMN NAME
    )
) y
  ON si.indid = y.indid
 AND x.TableID = y.id
WHERE si.status <> 0
  -- This eliminates occurrences of the column found in indexes with multiple columns.
  AND si.indid NOT IN (
    SELECT indid
    FROM sysindexkeys
    WHERE id = x.TableID
    GROUP BY indid
    HAVING COUNT(*) > 1
)

Вариант 3:

Создайте таблицу (IndexTable) с index_name, index_description, index_keys и вставьте результаты следующей команды:

sp_helpindex 'TableName'

Затем выполните запрос из этого результата (или используйте аналогичный запрос):

SELECT *
FROM IndexTable
WHERE index_description LIKE '%unique%'
  AND index_keys = 'ColumnName'

Надеюсь, это поможет, или, пожалуйста, напишите, если у вас есть более краткое решение.

person Kurt Abbas    schedule 26.10.2010

Попробуйте этот запрос:

SELECT A.TABLE_NAME, A.CONSTRAINT_NAME, B.COLUMN_NAME
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS A, 
         INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE B
    WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND
          A.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND
          A.TABLE_NAME='{$tableName}'
    ORDER BY A.TABLE_NAME

Замените {$tableName} на имя вашей таблицы, и вы получите все первичные ключи для конкретной таблицы, независимо от того, имеет ли таблица один первичный ключ или несколько первичных ключей.

person sm.meditab    schedule 25.02.2011

Проблема в том, что вы получаете "Положение столбца в индексе". Таким образом, не существует двух столбцов с одинаковой позицией.

person rpf    schedule 23.02.2009
comment
Хорошо, спасибо, теперь есть способ определить, является ли столбец уникальным индексом? - person ; 23.02.2009