I’m doing a data format conversion from Program A’s CSV format to Program B’s CSV format.
Program A’s format looks like:
Fruit, Orange, $1.99
Fruit, Apple, $2.99
Fruit, Pear, $5.99
Colour, Red, #FF0000
Colour, Green, #00FF00
Colour, Blue, #0000FF
Colour, Orange, #FF8800
I’ve converted Program A’s CSV file into an SQLite database containing multiple tables, one for each type of record in the original CSV file. Here that would be Fruit and Colour. This maps well onto Program B’s file format, which uses similar tables (with a few funky conversions required.)
Each table in Program A’s CSV file has an ID primary key which is not required to be unique. That is, there can be a “Fruit” row with ID “Orange” and also a “Colour” row with ID “Orange“.
However Program B would consider this an error – it requires the ID primary key to be unique across ALL tables.
What is an efficient way to detect non-unique ID keys, either in the original file (formatted like above) or in the SQL database? There are dozens of tables and thousands of records.
My current approach is similar to (Python code):
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())
This seems hilariously inefficient. There must exist a more elegant/more Pythonic way of doing this, possibly using some kind of set notation.
Alternately, could I define my SQL schema (SQLite flavoured) so that SQLite enforces uniqueness of the ID across all tables?
There is no way that I know of to enforce this within the database, unless you create another table with all IDs, keep this up to date using triggers. I’m not sure you ever want to do something like that (whether it’s possible at all depends on your database engine).
A more efficient way to check for duplicates is using a Hash in stead of an array:
It doesn’t give quite te same output (especially when a key is present in 3 tables it won’t show all the permutations), but it will quickly show you where your problems are.