What is the purpose of a Row_GUID column?
ROWGUIDCOL
is primarily used for MERGE replication, and is also required for FILESTREAM
, but can be used in any scenario where you want an immutable column separate from the primary key (e.g. in the case where a primary key value can change, but you still want to be able to tell which row was which before and after the change).
USE tempdb;
GO
CREATE TABLE dbo.example
(
name sysname PRIMARY KEY,
rowguid uniqueidentifier NOT NULL DEFAULT NEWID() ROWGUIDCOL
);
INSERT dbo.example(name) VALUES(N'bob'),(N'frank');
SELECT * FROM dbo.example;
UPDATE dbo.example SET name = N'pat' WHERE name = N'bob';
UPDATE dbo.example SET name = N'bob' WHERE name = N'frank';
SELECT * FROM dbo.example;
DROP TABLE dbo.example;
Now, if replication, or your application, or what have you is paying attention, it will notice that:
See here, here, and the "Snapshot Considerations" section here for more info.
Marking a column as ROWGUIDCOL
allows it to be referenced via $ROWGUID
in queries. This allows for making queries more generic since you wouldn't need to look up, per each table, what the "unique" column is (this is quite useful for features such as Replication and FileStream as noted by @Aaron and @Martin, respectively). You could have a query constructed in the app layer, or in Dynamic SQL even, that does something like SELECT $ROWGUID AS [ID] FROM {table_name}
and simply iterate over a list of tables.
Just keep in mind that the ROWGUIDCOL
designation does not enforce uniqueness. You will still need to enforce that via a Primary Key, a Unique Index, or a Unique Constraint. Nor does this option enforce that the column is immutable. For that you would need either an AFTER UPDATE
Trigger or column-level permissions to DENY UPDATE
on that column.
For example:
SET NOCOUNT ON;
CREATE TABLE #RowGuidColTest
(
ID UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID()) ROWGUIDCOL,
SomeValue INT
);
INSERT INTO #RowGuidColTest (SomeValue) VALUES (12), (14), (1231);
DECLARE @Search UNIQUEIDENTIFIER;
SELECT TOP (1) @Search = $ROWGUID
FROM #RowGuidColTest;
SELECT @Search AS [@Search]
SELECT *, $ROWGUID AS [$ROWGUID]
FROM #RowGuidColTest;
SELECT *
FROM #RowGuidColTest
WHERE $ROWGUID = @Search;
-- No enforced uniqueness without a PK, Unique Index, or Unique Constraint.
UPDATE tmp
SET $ROWGUID = @Search
FROM #RowGuidColTest tmp
SELECT *
FROM #RowGuidColTest
WHERE $ROWGUID = @Search;
Returns something similar to:
@Search
E7166D18-5003-4D20-8983-E2402472CF82
ID SomeValue $ROWGUID
E7166D18-5003-4D20-8983-E2402472CF82 12 E7166D18-5003-4D20-8983-E2402472CF82
44FD48A4-AF38-41BF-AE4E-8A12D26B5B57 14 44FD48A4-AF38-41BF-AE4E-8A12D26B5B57
2D50C5C7-1E43-4ADA-A03B-ED202FC88D20 1231 2D50C5C7-1E43-4ADA-A03B-ED202FC88D20
ID SomeValue
E7166D18-5003-4D20-8983-E2402472CF82 12
ID SomeValue
E7166D18-5003-4D20-8983-E2402472CF82 12
E7166D18-5003-4D20-8983-E2402472CF82 14
E7166D18-5003-4D20-8983-E2402472CF82 1231
Similarly, one could use $IDENTITY
for tables that have an IDENTITY
column.