在多个表中强制/检查主键的唯一性

时间:2012-02-14 09:04:26

标签: python sql set duplicates

我正在进行从程序A的CSV格式到程序B的CSV格式的数据格式转换。

程序A的格式如下:

Fruit,  Orange, $1.99
Fruit,  Apple,  $2.99
Fruit,  Pear,   $5.99
Colour, Red,    #FF0000
Colour, Green,  #00FF00
Colour, Blue,   #0000FF
Colour, Orange, #FF8800

我已将程序A的CSV文件转换为包含多个表的SQLite数据库,每个表对应原始CSV文件中的每种记录类型。这是FruitColour。这很好地映射到程序B的文件格式,它使用类似的表格(需要一些时髦的转换。)

程序A的CSV文件中的每个表都有一个ID主键,不需要是唯一的。也就是说,可能存在ID为“Fruit”的“Orange”行以及ID为“Colour”的“Orange”行。

但是程序B会认为这是一个错误 - 它要求ID主键在所有表中都是唯一的。

在原始文件(格式如上)或SQL数据库中检测非唯一ID密钥的有效方法是什么?有数十个表和数千条记录。

我目前的方法类似于(Python代码):

import sqlite3, collections
db_conn = sqlite3.connect('db.sqlite3')
db_conn.row_factory = sqlite3.Row

IDs = []    # build a list of (ID, table_name) pairs

tables = ['Fruit','Colour'];
for table in tables:
    rows = db_conn.execute("SELECT ID FROM %s" % table)
    for row in rows:
        IDs.append( (row['ID'],table) )

id_counts = collections.Counter([x(0) for x in IDs])
duplicated_ids = [x for x in id_counts if id_counts[x] > 1]
for duplicated_id in duplicated_ids:    
    duplicated_types = [x(1) for x in IDs if x(0) == duplicated_id ]
    print ("Duplicate ID %(duplicated_id)s used for %(duplicated_types)s" % locals())

这看起来非常低效。必须存在更优雅/更Pythonic的方式,可能使用某种设置符号。

或者,我可以定义我的SQL模式(SQLite风格),以便SQLite在所有表中强制执行ID的唯一性吗?

2 个答案:

答案 0 :(得分:1)

除非您使用所有ID创建另一个表,否则我无法在数据库中强制执行此操作,请使用触发器使其保持最新。我不确定你是否想做类似的事情(它是否可能取决于你的数据库引擎)。

检查重复项的更有效方法是使用哈希而不是数组:

IDs = {}

tables = ['Fruit','Colour'];
for table in tables:
  rows = db_conn.execute("SELECT ID FROM %s" % table)
  for row in rows:
    if IDs.has_key(row['ID']):
      print "Duplicate ID %s is present in both %s and %s" % (row['ID'], table, IDs[row['ID']])
    else:
      IDs[row['ID']] = table

它没有提供相同的输出(特别是当3个表中存在一个键时,它不会显示所有的排列),但它会很快显示你的问题所在。

答案 1 :(得分:0)

请参阅这篇关于企业密钥的两篇文章:

Primary Key Reengineering Projects by Tom Johnston