Globally Unique Identifiers... ou GUIDs (pronunciado como Geoduck como o "uck" ou como "Gooo-id" para as pessoas que não consigam efectuar a outra pronúncia) são basicamente únicos através do tempo e do espaço. Eles são usados em toda a COM, e são usados pela replicação do Jet como a maneira de criar um identificador para os registos que se manterá constante e único apesar de outros valores (como as chaves) possam ser alterados.
Muitas pessoas consideram a possiblidade de utilizar GUIDs como as suas chaves primárias/chaves estrangeiras, porque estes vão garantir que elas serão únicas. Contudo, existem diversas razões para pensar duas vezes antes de optar por esta solução:
1) Numa aplicação, um "campo ReplicationID Autonumber" (um autonumber GUID), que por sua vez é tornado numa réplica, o Jet vai utilizar o teu campo em vez de criar um novo campo s_Guid. Infelizmente, o Assistente de Resolução de Conflitos do Access 95 e 97 e o Visualizador de Conflitos do Access 2000 estão a assumir um campo s_Guid e como tal as resoluções dos conflitos não vão funcionar correctamente através dos assistentes, e então estás por tua conta.
2) Um GUID é literalmente guardado como um valor binário de 16-byte. Tem também uma parte canónica (texto) e uma parte específica ao DAO/Jet também, constituída por {guid {xxx}} onde xxx é o valor "canónico". Este último formato é o que o Jet vai mostrar de qualquer das vezes que selecionares um campo GUID através do DAO... a forma canónica vai ser utilizada se utilizares o Jet directamente (como por exemplo através da folhas de dados do Access) ou ADO através do Jet OLE DB provider. Adicionando a isto, as regras do DAO vs. ADO como filtros, pesquisas, Funções Access Domain, Access filter by form, form/subform links, .Text vs. .Value para controles ligados (bound) a campos GUID, e todos os metódos de pesquisa, são muito difíceis de acompanhar e alterar com cada versão. O Access tem funções built-in para ajudar a converter entre o formato binário e o canónico nomeadas StringFromGUID e GUIDFromString, mas infelizmente elas usam a sintaxe do DAO, mesmo que em toda a COM e a maioria de outas fontes prefiram o formato simplesmente canónico. Toda esta confusão significa que a tentar utilizar um campo GUID para estas operações significa que estás a tentar atingir um alvo em movimento.
3) As regras do #2 mudam em quase todas as versões e quase universalmente quebram o que funcionava na versão anterior. Portanto no essencial tu terás de rever de novo todo o trabalho quando estiveres a efectuar uma actualização de versão.
4) Muitas vezes Autonumbers estão visíveis para os utilizadores, para o melhor e o pior, e isto é obviamente muito pouco prático com os GUIDs, mesmo que a grande quantidade de maus assuntos com as pesquisas e outros listados acima não fossem efectivamente problemas. Os GUIDs simplesmente confundem os utilizadores e ninguém quer um GUID para o identificar.
Agora, é verdade que todos os problemas abordados no #2 podem ser ultrapassados utilizando diversas técnicas, incluindo:
1) Experimentar, utilizar o verdadeiro formato canónico vs. o formato canónico {guid {xxx}}
2) Conversão utilizando as duas funções do Access
3) Utilizar CStr() no comando SELECT para os valores dos campos que devolvam GUIDs de modo a obteres o verdadeiro formato canónico
4) Anotar todos os lugares onde fizeste qualquer alteração para que se/quando fizeres uma actualização de versão possas rever todos eles (pois a maioria estará estragada e alterada com a próxima versão).
5) Perceber que o campo por trás do DAO é um campo do tipo dbGuid e ue o campo por trás do ADO é um campo do tipo adGuid... apesar do facto que ambos devolvem um campo do tipo "texto" quando estás simplesmente a visualizar os valores dos campos ajuda a perceber o grande esforço que todos tiveram de maneira a tentarem parecer flexiveis... é a principal razão porque todo o #2 é tão difícil de prever.
Aqui está (por falar nisso) as funções não-Access para fazer manipulação de Guid/String e String/Guid se estás a trabalhar através do VB. Simplesmente copia-as para um módulo, etc.
Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Private Declare Function _
StringFromGUID2 Lib "ole32.dll" _
(rclsid As GUID, ByVal lpsz As Long, _
ByVal cbMax As Long) As Long
Private Declare Function _
CLSIDFromString Lib "ole32.dll" _
(pstCLS As Long, clsid As GUID) As Long
Function GuidFromStGuid(stGuid As String) As GUID
Call CLSIDFromString(ByVal StrPtr(stGuid), _
GuidFromStGuid)
End Function
Function StGuidFromGuid(rclsid As GUID) As String
Dim stGuid As String
Dim cch As Long
' 39 chars for the GUID plus room for the Null char
stGuid = String$(40, vbNullChar)
cch = StringFromGUID2(rclsid, StrPtr(stGuid), 39)
StGuidFromGuid = Left$(stGuid, cch)
End Function
RECOMENDAÇÃO FINAL:
Enquanto é possível evitar ambos os problemas descritos em #2 e #3, os do #2 são muito problemáticos e é muito difícil considerar a manutenção face ao descrito em #3. Na generalidade não vale o risco de erros e problemas ou dos problemas de actualização de versões. Existem maneiras melhores de escolher PKs que não envolvem estes riscos.... é portanto quase sempre mais aconselhável seguir esse rumo se pretendes construir bases de dados que possam ser facilmente mantidas e aplicações que possam ser replicadas.
MichKa
ReplicaID: {E5D50A9B-33D2-11D3-AAB3-00104BA31425}