Question

I want to find out, with an SQL query, whether an index is UNIQUE or not. I'm using SQLite 3.

I have tried two approaches:

SELECT * FROM sqlite_master WHERE name = 'sqlite_autoindex_user_1'

This returns information about the index ("type", "name", "tbl_name", "rootpage" and "sql"). Note that the sql column is empty when the index is automatically created by SQLite.

PRAGMA index_info(sqlite_autoindex_user_1);

This returns the columns in the index ("seqno", "cid" and "name").

Any other suggestions?

Edit: The above example is for an auto-generated index, but my question is about indexes in general. For example, I can create an index with "CREATE UNIQUE INDEX index1 ON visit (user, date)". It seems no SQL command will show if my new index is UNIQUE or not.

Was it helpful?

Solution

PRAGMA INDEX_LIST('table_name');

Returns a table with 3 columns:

  1. seq Unique numeric ID of index
  2. name Name of the index
  3. unique Uniqueness flag (nonzero if UNIQUE index.)

Then just loop through the resulting rows until you see the name of the index you wish to query (unfortunately you can't have a WHERE clause in a PRAGMA statement.)

OTHER TIPS

Since noone's come up with a good answer, I think the best solution is this:

  • If the index starts with "sqlite_autoindex", it is an auto-generated index for a single UNIQUE column
  • Otherwise, look for the UNIQUE keyword in the sql column in the table sqlite_master, with something like this:

    SELECT * FROM sqlite_master WHERE type = 'index' AND sql LIKE '%UNIQUE%'

you can programmatically build a select statement to see if any tuples point to more than one row. If you get back three columns, foo, bar and baz, create the following query

select count(*) from t
group by foo, bar, baz
having count(*) > 1

If that returns any rows, your index is not unique, since more than one row maps to the given tuple. If sqlite3 supports derived tables (I've yet to have the need, so I don't know off-hand), you can make this even more succinct:

select count(*) from (
    select count(*) from t
    group by foo, bar, baz
    having count(*) > 1
)

This will return a single row result set, denoting the number of duplicate tuple sets. If positive, your index is not unique.

You are close:

1) If the index starts with "sqlite_autoindex", it is an auto-generated index for the primary key . However, this will be in the sqlite_master or sqlite_temp_master tables depending depending on whether the table being indexed is temporary.

2) You need to watch out for table names and columns that contain the substring unique, so you want to use:

SELECT * FROM sqlite_master WHERE type = 'index' AND sql LIKE 'CREATE UNIQUE INDEX%'

See the sqlite website documentation on Create Index

As of sqlite 3.16.0 you could also use pragma functions:

SELECT distinct il.name
  FROM sqlite_master AS m,
       pragma_index_list(m.name) AS il,
       pragma_index_info(il.name) AS ii
 WHERE m.type='table' AND il.[unique] = 1;

The above statement will list all names of unique indexes.

SELECT DISTINCT m.name as table_name, ii.name as column_name
  FROM sqlite_master AS m,
       pragma_index_list(m.name) AS il,
       pragma_index_info(il.name) AS ii
 WHERE m.type='table' AND il.[unique] = 1;

The above statement will return all tables and their columns if the column is part of a unique index.

From the docs:

The table-valued functions for PRAGMA feature was added in SQLite version 3.16.0 (2017-01-02). Prior versions of SQLite cannot use this feature.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top