16

给定一个 SQLite 数据库,我需要获取给定表中的哪些列被索引的列表,以及排序顺序。我需要从代码中执行此操作(C#,尽管这无关紧要),所以我真正需要的是一个 SQL 语句,如果存在的话,它会执行此操作。

我知道我可以这样做:

SELECT sql FROM SQLite_master WHERE type = 'index' AND tbl_name = 'MyTableName'

然后手动解析生成的 SQL,但是在某处是否有一些元数据可以让我查询这些元数据?

----------------------------------
| 姓名 | 专栏 | 方向 |
 ----------------------------------
| idx_a | 科尔A | 升学 |
 ----------------------------------
| idx_a_b | ColB, ColB | 递减 |
 ----------------------------------
4

7 回答 7

29

使用PRAGMA index_list(table-name);PRAGMA index_info(index-name); 扩展名

更新:PRAGMA schema.index_xinfo(index-name);将返回键列的排序顺序。

于 2012-11-17T00:21:06.483 回答
12

在 where 子句中添加您想要的任何条件。字段是:

CREATE TABLE sqlite_master (
  type TEXT,
  name TEXT,
  tbl_name TEXT,
  rootpage INTEGER,
  sql TEXT
);

可粘贴的选择...索引要包含的重要字段是“sql”。不会列出创建表语句中定义的主键。

select type, name, tbl_name, sql
FROM sqlite_master
WHERE type='index'
于 2017-01-19T20:57:54.610 回答
2

这就是您的实际操作方式:所有索引元数据都可以通过“sqlite_master”表获得。请参阅 SQLite FAQ 的 Q7:http ://www.sqlite.org/faq.html#q7

于 2012-11-17T00:12:07.153 回答
1
SELECT 
    m.tbl_name as table_name,
    il.name as index_name,
    ii.name as column_name,
    CASE il.origin when 'pk' then 1 else 0 END as is_primary_key,
    CASE il.[unique] when 1 then 0 else 1 END as non_unique,
    il.[unique] as is_unique,
    il.partial,
    il.seq as sequence_in_index
FROM sqlite_master AS m,
    pragma_index_list(m.name) AS il,
    pragma_index_info(il.name) AS ii
WHERE 
    m.type = 'table'
    and m.tbl_name = 'YOUR TABLENAME HERE'
GROUP BY
    m.tbl_name,
    il.name,
    ii.name,
    il.origin,
    il.partial,
    il.seq
ORDER BY 1,6
于 2020-09-16T12:52:10.577 回答
1

@neil 简要提到了SQLite Pragma 语句 PRAGMA INDEX_LIST['table_name']PRAGMA INDEX_INFO['index_name']. 根据文档,这些既作为 SQLite 命令存在,也可以在函数中使用(即pragma_index_list(table_name)pragma_index_info(index_name).

为了更好地理解这一点,让我们看一下下面的 SQL:

CREATE TABLE Assets
(
    Asset_Id     INTEGER NOT NULL,
    Longitude    REAL    NOT NULL,
    Latitude     REAL    NOT NULL,
    Name         TEXT    NOT NULL,
    Installation REAL    NOT NULL,
    Constraint PK_Assets PRIMARY KEY (Asset_Id)
);
CREATE INDEX IX_Assets_Coordinate On Assets (Longitude, Latitude);
CREATE INDEX IX_Assets_Name On Assets (Name);

以下 SQLite 会话演示了如何查询索引:

.mode csv
sqlite> PRAGMA index_list('Assets');
seq,name,unique
0,IX_Assets_Name,0
1,IX_Assets_Coordinate,0
sqlite> PRAGMA index_info('IX_Assets_Name');
seqno,cid,name
0,3,Name
sqlite> PRAGMA index_info('IX_Assets_Coordinate');
seqno,cid,name
0,1,Longitude
1,2,Latitude
sqlite>

有趣的是这些PRAGMA命令可以像SELECT语句一样使用,因此在C#.

SQLite Pragma 语句中,他们有一个有趣的示例 SQL 语句,用于枚举所有表的所有索引列:

SELECT DISTINCT m.name || '.' || ii.name AS 'indexed-columns'
  FROM sqlite_master AS m,
       pragma_index_list(m.name) AS il,
       pragma_index_info(il.name) AS ii
 WHERE m.type = 'table'
 ORDER BY 1;
于 2018-03-16T00:03:54.300 回答
0

我找不到任何方法来简单地查询表元并获得我想要的 indo,所以如果有人需要它,这就是我使用的。是的,Regex 可能做得更干净,但你知道格言,如果 Regex 可以解决问题,那么现在你有两个问题。

public class SqlIndexInfo
{
    public string IndexName { get; set; }
    public string TableName { get; set; }
    public string[] Fields { get; set; }
    public bool IsAscending { get; set; }

    public bool IsComposite
    {
        get { return Fields.Length > 1; }
    }
}

public static class Extensions
{
    public static SqlIndexInfo ParseToIndexInfo(this string sql)
    {
        sql = sql.Trim();
        var info = new SqlIndexInfo();

        var i = sql.IndexOf("CREATE INDEX", 0, StringComparison.InvariantCultureIgnoreCase);
        if (i < 0) throw new ArgumentException("String is not valid CREATE INDEX SQL");
        var indexNameStart = i + "CREATE INDEX".Length + 1;

        i = sql.IndexOf(" ON ", 0, StringComparison.InvariantCultureIgnoreCase);
        if (i < 0) throw new ArgumentException("String is not valid CREATE INDEX SQL");
        var indexNameEnd = i;
        var tableNameStart = i + " ON ".Length;

        i = sql.IndexOf("(", 0, StringComparison.InvariantCultureIgnoreCase);
        if (i < 0) throw new ArgumentException("String is not valid CREATE INDEX SQL");
        var tableNameEnd = i;
        var fieldNamesStart = i + 1;

        i = sql.IndexOf(")", 0, StringComparison.InvariantCultureIgnoreCase);
        if (i < 0) throw new ArgumentException("String is not valid CREATE INDEX SQL");
        var fieldNamesEnd = i;
        var directionStart = i + 1;

        // TODO: strip brackets and/or single quotes?

        info.IndexName = sql.Substring(indexNameStart, indexNameEnd - indexNameStart).Trim();
        info.TableName = sql.Substring(tableNameStart, tableNameEnd - tableNameStart).Trim();
        info.Fields = (from f in sql.Substring(fieldNamesStart, fieldNamesEnd - fieldNamesStart).Split(',')
                      where !string.IsNullOrEmpty(f)
                      select f.Trim()).ToArray();

        if (directionStart >= sql.Length)
        {
            info.IsAscending = true;
        }
        else
        {
            info.IsAscending = sql.IndexOf("ASC", directionStart, StringComparison.InvariantCultureIgnoreCase) >= 0;
        }

        return info;
    }
}
于 2012-11-17T17:33:02.593 回答
0

根据@Steve Lloyd 的回答进行优化,按顺序排列ii.seqno

SELECT 
    m.tbl_name as table_name,
    il.name as index_name,
    ii.name as column_name,
    CASE il.origin when 'pk' then 1 else 0 END as is_primary_key,
    CASE il.[unique] when 1 then 0 else 1 END as non_unique,
    il.[unique] as is_unique,
    il.partial,
    il.seq as sequence_in_index,
    ii.seqno as sequence_in_column
FROM sqlite_master AS m,
    pragma_index_list(m.name) AS il,
    pragma_index_info(il.name) AS ii
WHERE 
    m.type = 'table'
    and m.tbl_name = 'YOUR TABLENAME HERE'
GROUP BY
    m.tbl_name,
    il.name,
    ii.name,
    il.origin,
    il.partial,
    il.seq
ORDER BY index_name,il.seq,ii.seqno
于 2021-02-15T07:33:31.710 回答