2012-05-18 40 views
0

我正在编写一个基于Perl的应用程序,它将SQLite数据库转换为Excel工作簿并再次返回。它按原样工作,但缺少一小块。我不知道如何确定是否为特定列设置了UNIQUE约束。你如何确定列是否在SQLite数据库中设置了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 
); 

我想知道我怎么能随后询问这种方式创建,以确定哪些列具有UNIQUE约束集SQLite数据库表。在这种情况下,它将是发票栏。

有什么建议吗?

+0

不知道它的问题在这里,但不要忘了,多列唯一约束是可能的('UNIQUE(A,B)')。 – ikegami

+0

它很重要。好点子。 – Rodney

回答

1

您需要使用PRAGMA index_list声明。

该子例程确定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; 
} 
+0

谢谢。该解决方案适用于我正在转换的数据库。但是在每张表格中,我最多只有一列具有唯一约束。从你的描述来看,如果我更加严格,听起来就像代码破裂了。 – Rodney

+0

如果列有'UNIQUE' *列约束*,或者它出现在'UNIQUE(col1,col2,...)'(或等同的'PRIMARY KEY')*表约束*中,我的解决方案将返回true。 。我不太了解Excel,但如果它有像​​这样声明组合键的功能,我会感到惊讶。如果需要的话,可以很简单地更改代码,以便复合索引被忽略,并且仅当列是唯一索引的唯一成员时才将列声明为“UNIQUE”。 – Borodin