web-dev-qa-db-ja.com

SQLiteスキーマ情報メタデータ

SQLiteデータベースで列名とそのテーブルを取得する必要があります。必要なのは、2つの列を持つ結果セットです:_table_name | column_name_。

MySQLでは、データベース_INFORMATION_SCHEMA_のSQLクエリでこの情報を取得できます。ただし、SQLiteはテーブル_sqlite_master_を提供します。

_sqlite> create table students (id INTEGER, name TEXT);
sqlite> select * from sqlite_master;
  table|students|students|2|CREATE TABLE students (id INTEGER, name TEXT)
_

これはDDL構築クエリ(_CREATE TABLE_)になりますが、これは私には役に立たないので、これを解析して関連情報を取得する必要があります。

テーブルのリストを取得し、それらを列で結合するか、テーブル名の列とともに列を取得する必要があります。したがって、テーブル名がないため、PRAGMA table_info(TABLENAME)は機能しません。データベース内のすべての列メタデータを取得したい。

データベースにクエリを実行して、その情報を結果セットとして取得するより良い方法はありますか?

43
AhmetB - Google

基本的に、あなたは質問の中で解決策に名前を付けました。

テーブル(およびビュー)のリストを取得するには、次のようにsqlite_masterをクエリします

_SELECT name, sql FROM sqlite_master
WHERE type='table'
ORDER BY name;
_

SQLite FAQ を参照)

特定のテーブルの列に関する情報を取得するには、 SQLite PRAGMAドキュメント で説明されているPRAGMA table_info(table-name);を使用します。

単一のクエリの結果としてtablename | columnnameを取得する方法がわかりません。 SQLiteがこれをサポートしているとは思わない。おそらく、2つのメソッドを一緒に使用して、探している情報を返すことをお勧めします。最初にsqlite_masterを使用してテーブルのリストを取得し、次にそれらをループしてPRAGMA table_info()を使用して列を取得します。

79
Tom Juergens

「.tables」および「.schema [table_name]」コマンドがあり、「select * from sqlite_master;」から取得した結果に種類の分離されたバージョンを与えます。

「プラグマtable_info([table_name]);」もあります。構築クエリの代わりに解析のより良い結果を得るコマンド:


sqlite> .tables
students
sqlite> .schema students
create table students(id INTEGER, name TEXT);
sqlite> pragma table_info(students);
0|id|INTEGER|0||0
1|name|TEXT|0||0

それがある程度役立つことを願っています...

10
Mustafa Zengin

参考までに、.Netを使用している場合は、DbConnection.GetSchemaメソッド。通常はINFORMATION_SCHEMAにある情報を取得します。抽象化レイヤーがある場合は、すべてのタイプのデータベースに同じコードを使用できます(MySQLは制限配列の最初の2つの引数を切り替えるように見えることに注意してください)。

4
user276648

別の便利なトリックは、最初にすべてのテーブル名をsqlite_masterから取得することです。

次に、それぞれについて、「select * from t where 1 = 0」というクエリを実行します。結果のクエリの構造を分析する場合-呼び出し元の言語/ APIに依存します-列を説明する豊富な構造を取得します。

Pythonで

c = ...db.cursor()
c.execute("select * from t where 1=0");
c.fetchall();
print c.description;

ジュラジ

PS。レコードを制限する構文はdbごとに異なるため、「where 1 = 0」を使用する習慣があります。さらに、優れたデータベースは、このalways-false句を最適化します。

SQLiteでは、「制限0」で同じ効果が得られます。

4
Juraj

SQLiteの最近のバージョンでは、 今すぐPRAGMAの結果に対して選択 を使用できます。これにより、これが簡単になります。

SELECT 
  m.name as table_name, 
  p.name as column_name
FROM 
  sqlite_master AS m
JOIN 
  pragma_table_info(m.name) AS p
ORDER BY 
  m.name, 
  p.cid

ここで、p.cidは、ゼロインデックスのCREATE TABLEステートメントの列順序を保持します。

David Garoutteはこれに答えました here ですが、このSQLはより高速に実行されるはずで、列はアルファベット順ではなくスキーマによって順序付けられます。

table_infoにも含まれていることに注意してください

  • typeintegertextなどのデータ型)、
  • notnull(列に1制約がある場合はNOT NULL
  • dflt_value(デフォルト値がない場合はNULL
  • pk(列がテーブルの主キーの場合は1、そうでない場合は0

RTFM: https://www.sqlite.org/pragma.html#pragma_table_info

4
mrm

このsqliteテーブルスキーマパーサーを試してください。PHPでテーブル定義を解析するためにsqliteテーブルパーサーを実装しました。

完全な定義(一意、主キー、タイプ、精度、null以外、参照、テーブル制約など)を返します。

https://github.com/maghead/sqlite-parser

構文は、sqlite create tableステートメントの構文に従います。 http://www.sqlite.org/lang_createtable.html

2
c9s

これは古い質問ですが、それが表示された回数のために、ほとんどの回答がSQLiteデータベースでテーブル名を見つける方法を教えてくれる簡単な理由で質問に追加していますテーブル名のときに何をしますかIS NOT IN DATABASE?これは、プログラムでTABLESを作成しているため、アプリに発生します。したがって、以下のコードは、TABLEがデータベースにない、またはデータベースで作成された場合の問題を処理します

    public void toPageTwo(View view){

    if(etQuizTable.getText().toString().equals("")){
        Toast.makeText(getApplicationContext(), "Enter Table Name\n\n"
                +"           OR"+"\n\nMake Table First", Toast.LENGTH_LONG 
   ).show();
        etQuizTable.requestFocus();
        return;
    }

    NEW_TABLE = etQuizTable.getText().toString().trim();
    db = dbHelper.getWritableDatabase();
    ArrayList<String> arrTblNames = new ArrayList<>();
    Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE 
   type='table'", null);

    if (c.moveToFirst()) {
        while ( !c.isAfterLast() ) {
            arrTblNames.add( c.getString( c.getColumnIndex("name")) );
            c.moveToNext();
        }
    }
    c.close();
    db.close();

    boolean matchFound = false;
    for(int i=0;i<arrTblNames.size();i++) {
        if(arrTblNames.get(i).equals(NEW_TABLE)) {
            Intent intent = new Intent(ManageTables.this, TableCreate.class 
   );
            startActivity( intent );
            matchFound = true;
        }
    }
    if (!matchFound) {
        Toast.makeText(getApplicationContext(), "No Such Table\n\n"
                +"           OR"+"\n\nMake Table First", Toast.LENGTH_LONG 
 ).show();
        etQuizTable.requestFocus();
    }
}
0
James_Duh