I'm looking to store GUIDs in my SQLite database, using C# and python clients.
Creating a database, and inserting a row, storing the GUID as a string:
conn = sqlite3.connect(filename)
c = conn.cursor()
# Create the table. Yes, I know GUID isn't a real SQLite datatype.
c.execute('CREATE TABLE test (guid GUID PRIMARY KEY, name text)')
u = uuid.uuid4()
print u
t = (str(u), 'foo')
c.execute('INSERT INTO test VALUES (?,?)', t)
conn.commit()
conn.close()
Fetching:
# ...
c.execute('SELECT * FROM test WHERE guid = "c1332103-6031-4ff7-b610-f8f3b940fa66"')
print c.fetchone()
This all works perfectly. Using the default Python __str__
representation of the UUID works well.
C:\Users\Jonathon>makedb.py test.db
c1332103-6031-4ff7-b610-f8f3b940fa66
C:\Users\Jonathon>opendb.py test.db
(u'c1332103-6031-4ff7-b610-f8f3b940fa66', u'foo')
My doubts arise from using SQLite Expert. It appears that SQLite Expert is happy with my GUID datatype declaration:
But, if I edit a row:
it seems that it changes the datatype! My SELECT
from before yields None
, and if I SELECT *
, I see that it is no longer a simple unicode string:
C:\Users\Jonathon>opendb.py test.db
(<read-write buffer ptr 0x02239520, size 16 at 0x02239500>, u'foo')
Looking at the data on disk, you can see that the GUID is stored in binary, after SQLite Expert touches it:
Before - the GUID is ASCII text:
After - the previous data is garbage, and a binary version of the GUID exists:
So what is the "correct" way to store GUIDs in SQLite, specifically using Python? Later, I will have C# code interacting with this as well, and want to make sure I'm going things the "right" way.
Your GUID is a string. Declare it as a VARCHAR or CHAR and it will pick up the text affinity correctly. As GUID is not a type the field has no type affinity, and thus will have the datatype of NONE.
This is described here: http://www.sqlite.org/datatype3.html
There is also a brief discussion of someone trying to use a Guid within SQLite Expert on their support forum here: http://sqliteexpert.com/forum/YaBB.pl?num=1368018774/0
Support talks about the mapping system and how to change a mapping, as well as the tool defaulting to the use of a Blob.
One can essentially add support for GUID datatypes to sqlite3 in Python. You can register conversion functions:
register_converter()
: convert SQLite types to Python typesregister_adapter()
: convert Python types to SQLite typesTo use these, you need to pass an argument for the
detect_types
parameter ofconnect()
.Example:
Output:
Results:
uuid.UUID
objects directly toexecute()
. The adapterlambda u: buffer(u.bytes)
tells sqlite3 how to convert those to abuffer
(which translates to anX'ABCD....'
blob in SQLite.fectchone()
is returninguuid.UUID
objects directly. The converterlambda u: buffer(u.bytes)
tells sqlite3 how to create those from a byte array when it encounters a declared type ofGUID
.