<\/HEAD>
Als je een component van ESRI enterprise technologie hebt gebruikt, ben je de alomtegenwoordige Global ID unieke identifier tegengekomen. <\/P>
<\/P>
Waarschijnlijk door met de rechtermuisknop op een feature class te klikken en "Add Global ID's" te selecteren en het daarna te vergeten. <\/P>
<\/P>
Deze post is meer een klaagzang en uitbarsting tegen willekeurige <\/STRONG>GUID's dan iets anders. Je hebt zeker een GUID-kolom nodig als je data repliceert, of offline bewerkingen uitvoert. <\/P><\/P>Ik haat ze gewoonweg! Mijn probleem met de Global ID-kolom is hoe ESRI het implementeert. Niet alleen is het uniek (zoals het hoort), het is willekeurig. Ik gebruik SDE\/SQL data voor veel meer dan alleen punten op een kaart tonen. We koppelen die data aan andere applicaties, zoals die welke de niet-GIS data beheren die aan dat punt op de kaart is gekoppeld. In sommige applicaties heb ik tientallen relaties en tabellen gekoppeld aan die "GIS-tabel". Dit alles bereikt met slim gebruik van de Global ID-kolom als een manier om niet-GIS data te relateren aan de GIS-data. Natuurlijk, ik zou iets anders kunnen gebruiken, maar dan had ik niet zo'n aandacht trekkende blogtitel gehad. <\/P><\/P>Mijn probleem met de Global ID-kolom is de willekeurigheid ervan. Stel je een feature class voor met 10.000 (ik heb er een paar met 500.000) punten. Dat zijn 10.000 willekeurige GUID's. Koppel nu aan die tabel via die kolom, of sorteer het, of filter het. Gooi er een clustered (of non-clustered) index op de Global ID-kolom. Die willekeurige GUID's vertragen dingen zeker, nietwaar? <\/P><\/P>Laten we eens kijken hoe dit werkt. Wanneer je dat rechtsklikken doet en het vergeet, voegt SDE een constraint toe aan het Global ID veld: <\/P><\/P>ALTER TABLE [dbo].[TEST] ADD DEFAULT ('{00000000-0000-0000-0000-000000000000}') FOR [GlobalID]<\/PRE><\/P>Elke nieuwe feature die aan die feature class wordt toegevoegd roept een stored procedure aan die een SQL newid (GUID waarde) neemt en deze omzet naar een string. <\/P><\/P>CREATE PROCEDURE [dbo].[next_globalid]
@guid NVARCHAR(38) OUTPUT
AS SET NOCOUNT ON
BEGIN
SELECT @guid = '{' + CAST (NEWID() AS NVARCHAR(38)) + '}'
END
GO<\/PRE><\/P>Maar wat als we de GUID sequentieel kunnen maken en niet willekeurig, maar toch uniek? Zoiets bestaat, en een zoektocht op internet zal je een zeer verhitte discussie laten zien met veel meningen die stevig geworteld zijn voor of tegen sequentiële GUID's. Niet hier....<\/P><\/P>Proberen om de SP te wijzigen naar standaard SQL newSEQUENTIALID werkt niet...<\/P><\/P>CREATE PROCEDURE [dbo].[next_globalid]
@guid NVARCHAR(38) OUTPUT
AS SET NOCOUNT ON
BEGIN
SELECT @guid = '{' + CAST (NEWSEQUENTIALID() AS NVARCHAR(38)) + '}'
END
GO
De newsequentialid() ingebouwde functie kan alleen worden gebruikt in een DEFAULT expressie voor een kolom van het type 'uniqueidentifier' in een CREATE TABLE of ALTER TABLE statement. Het kan niet worden gecombineerd met andere operatoren om een complexe scalare expressie te vormen.<\/PRE>Dus hier is mijn oplossing: Zet een trigger tussen de delta- en basistabel en negeer de ESRI SP die de willekeurige GUID schrijft. We kunnen dit doen met een instead of insert trigger en door de default van de Global ID-kolom te veranderen. <\/P><\/P>Eerst: <\/P><\/P>ALTER TABLE [dbo].[TEST] DROP CONSTRAINT [DF__TEST__GlobalID__65FFA925]
GO
ALTER TABLE [dbo].[TEST] ADD CONSTRAINT [DF__TEST__GlobalID__65FFA925] DEFAULT (newsequentialid()) FOR [GlobalID]
GO<\/PRE><\/P>Dan: <\/P><\/P>CREATE TRIGGER [dbo].[TEST_GLOBAL_ID]
ON [dbo].[TEST]
INSTEAD OF INSERT NOT FOR REPLICATION
AS BEGIN
SET NOCOUNT ON;
INSERT [TEST](
OBJECTID, SOMEFIELD, SHAPE, LON, LAT, QuadName, Watershed, County, State, PARKDISTRICT, ELEVATION, StreamName, RiverOrder
)
SELECT
OBJECTID, a.SOMEFIELD, a.SHAPE, a.LON, a.LAT, a.QuadName, a.Watershed, a.County, a.State, a.PARKDISTRICT, a.ELEVATION, a.StreamName, a.RiverOrder
From
(SELECT
OBJECTID, SOMEFIELD, SHAPE, LON, LAT, QuadName, Watershed, County, State, PARKDISTRICT, ELEVATION, StreamName, RiverOrder
FROM inserted)
AS a
;
end
GO<\/PRE>Voeg een paar nieuwe punten toe en<\/P><\/P>SELECT
[GlobalID]
FROM [FISH].[dbo].[TEST]<\/PRE><\/P><\/P>GlobalID
C10EB116-8B14-45AB-924D-0C734E5AB5B6
61AE23FA-F02D-45C1-991D-571B77592014
0695789D-35A7-4BE4-B5F6-5EAF68D2A50B
5A20B628-6048-4D48-8380-AC005A0E70EC
CF52E6DE-5F60-456E-9DEF-C006D9BBD348
58F80A07-F8A8-4D62-BBB3-D012EA781F0C
5E7B9C91-2891-E411-B57C-E41F134196DA
BE30E498-2891-E411-B57C-E41F134196DA
BF30E498-2891-E411-B57C-E41F134196DA
C030E498-2891-E411-B57C-E41F134196DA
C130E498-2891-E411-B57C-E41F134196DA
38C5A6F2-60FF-4C39-BF37-F7AFCBDFDE90<\/PRE><\/P>Let op hoe mijn nieuwe punten (beginnend bij regel 08 en eindigend bij 12) sequentiële ID's bevatten. Ik gebruik hier een instead of in plaats van een after update trigger omdat ik wil dat dit GEBEURT VOORDAT het de basistabel bereikt. <\/P><\/P>Helaas is deze "wijziging" niet erg robuust en kan niet worden gebruikt als je data versiebeheer heeft ZONDER edits naar base te verplaatsen, of helemaal niet versiebeheer heeft (zoals nodig bij gebruik van Collector for ArcGIS). Ook niet besproken hier is mijn zeer overtuigende reden om het Global ID veld te gebruiken in sommige van de niet-GIS applicaties die deze data gebruiken. Laten we dit onder "knutselen" scharen. ESRI heeft vast een heel goede reden om de Global ID default zo te implementeren als ze doen, en deze post zal zeker wat verhitte discussies en reacties opleveren. <\/P><\/P>Dit samen met de after update\insert trigger gepresenteerd in Hey Neighbor? What's Your Value?<\/A> zal resulteren in een nette feature class waar bijna alle attributen automatisch worden ingevuld en je Global ID's geordend zijn. <\/P><\/P>
<\/P>