0

SQLiteデータベースをExcelワークブックに変換して元に戻すPerlベースのアプリケーションを作成しています。そのまま動作しますが、小さなピースが1つ欠けています。特定の列にUNIQUE制約が設定されているかどうかを判断する方法がわかりません。

データベース内のテーブルのリストを取得するには、次を使用します。

select name from sqlite_master 
  where type = 'table' 
  and name <> 'sqlite_sequence' order by name;

次に、各テーブルの列と制約の情報を取得するには、次のようにします。

PRAGMA table_info($TableName);

これにより、列でUNIQUE制約が有効になっている場合を除いて、知っておく必要のあるすべてのことがわかります。

これが明確でない場合のために、ここに簡単な例があります。これを実行してデータベーステーブルを作成するとします。

CREATE TABLE DATA 
(
    ID integer primary key, 
    Invoice integer unique, 
    Product varchar, 
    Comment varchar
);

この方法で作成されたSQLiteデータベーステーブルに後で問い合わせて、UNIQUE制約が設定されている列を特定する方法を知りたいです。この場合、それは請求書の列になります。

助言がありますか?

4

3 に答える 3

2

PRAGMA index_listtheステートメントを使用する必要があります。

uniqueこのサブルーチンは、データベース ハンドルとテーブルおよびカラム名を指定して、属性の値を決定します。

sub column_unique {
  my ($dbh, $table, $column) = @_;
  my $sth = $dbh->prepare("PRAGMA index_list($table)");
  $sth->execute;
  my $rec = $sth->fetchall_hashref('name');
  return $rec->{$column} && $rec->{$column}{unique};
}

列がindex_listテーブルのプラグマに表示される場合、unique属性の値 ( または のいずれ'0''1') が返されます。そうでない場合undefは返されます。これにより、次のような呼び出しが可能になります

if (column_unique($dbh, 'DATA', 'Invoice')) { ... }

編集

申し訳ありませんが、私の最初の回答は間違っていました。SQLite ではインデックスのみを一意に宣言することができ、それらのインデックスは複数列の組み合わせにすることができます。この改訂されたサブルーチンは、テーブルの各一意のインデックスの構成を調べ、指定された列がその全体または一部であるかどうかを確認します。

これはあまり満足のいくものではありません。一意のインデックスの一部であることは、列自体についてはあまり意味がありませんが、情報を何に使用するかによって改善されるかどうかが異なります。

sub column_unique {

  my ($dbh, $table, $column) = @_;

  my $sth = $dbh->prepare("PRAGMA index_list($table)");
  $sth->execute;
  my $list = $sth->fetchall_hashref('name');

  foreach my $index (keys %$list) {

    next unless $list->{$index}{unique};

    my $sth = $dbh->prepare("PRAGMA index_info($index)");
    $sth->execute;
    my $info = $sth->fetchall_hashref('name');

    return 1 if $info->{$column};
  }

  return 0;
}
于 2012-05-18T16:09:40.453 に答える