我正在进行从程序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文件中的每种记录类型。这是Fruit
和Colour
。这很好地映射到程序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的唯一性吗?
答案 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)
请参阅这篇关于企业密钥的两篇文章: