I wrote this 域名消失了,但胆子在这里....
无论我真正关心正确数据库设计的同事如何看待用于关键字段的 UUID 和 GUID。我经常发现我需要这样做。我认为它比自动增量有一些优势,这使它值得。
过去几个月我一直在优化 UUID 列类型,我想我终于把它搞定了。
from sqlalchemy import types
from sqlalchemy.dialects.mysql.base import MSBinary
from sqlalchemy.schema import Column
import uuid
class UUID(types.TypeDecorator):
impl = MSBinary
def __init__(self):
self.impl.length = 16
types.TypeDecorator.__init__(self,length=self.impl.length)
def process_bind_param(self,value,dialect=None):
if value and isinstance(value,uuid.UUID):
return value.bytes
elif value and not isinstance(value,uuid.UUID):
raise ValueError,'value %s is not a valid uuid.UUID' % value
else:
return None
def process_result_value(self,value,dialect=None):
if value:
return uuid.UUID(bytes=value)
else:
return None
def is_mutable(self):
return False
id_column_name = "id"
def id_column():
import uuid
return Column(id_column_name,UUID(),primary_key=True,default=uuid.uuid4)
# Usage
my_table = Table('test',
metadata,
id_column(),
Column('parent_id',
UUID(),
ForeignKey(table_parent.c.id)))
我相信存储为二进制(16 字节)最终应该比字符串表示(36 字节?)更有效,而且似乎有迹象表明在 mysql 中索引 16 字节块应该比字符串更有效。无论如何,我不认为情况会更糟。
我发现的一个缺点是,至少在 phpymyadmin 中,您不能编辑记录,因为它隐式地尝试对“select * from table where id =...”进行某种字符转换,而且还有杂项显示问题。
除此之外,一切似乎都运行良好,所以我把它扔掉了。如果您看到明显的错误,请发表评论。我欢迎任何改进它的建议。
除非我遗漏了什么,否则如果底层数据库具有 UUID 类型,上述解决方案将有效。如果没有,您可能会在创建表时遇到错误。我想出的解决方案最初是针对 MSSqlServer,然后最终使用了 MySql,所以我认为我的解决方案更灵活一些,因为它似乎在 mysql 和 sqlite 上运行良好。还没有打扰检查postgres。