这是我对系统和约束的描述。我有一个存储xml文件的MSSQL数据库。这些文件供我的Windows应用商店中的最终用户使用。基本上,用户使用此GUI应用程序创建设备配置,将其转换为xml,并上载到数据库。这些xml配置中的每一个都代表设备配置的表示。我希望能够为每个唯一配置分配一个唯一的ID,这个ID将在我的所有用户中保持一致。这意味着如果有人使用应用程序创建相同的设备配置,那么使用应用程序的设备配置的XML唯一ID将是相同的。这就是说,最终构成设备配置的组成部分是可以通过我可以存储的单个值来识别的。
如何创建此唯一ID?创建我要创建的XML文件时可以运行什么功能是唯一ID?请描述执行此操作的过程。
答案 0 :(得分:2)
计算xml文档和索引的校验和,以便您将来检查的速度很快。
注意,xml可以是"等效的"但不能等于一个字符串。如果你只有一个xml的生产者,这对你来说可能不是问题。
这是一个简单的例子:
create table dbo.Devices
(
DeviceId int identity(1,1) primary key,
Configuration xml,
ConfigurationChecksum as binary_checksum(cast(Configuration as varchar(max))),
constraint ck_Configuration unique(ConfigurationChecksum)
);
go
--insert new (OK)
insert into dbo.Devices(Configuration)
values('<root><Config>123</Config></root>');
--insert new (OK)
insert into dbo.Devices(Configuration)
values('<root><Config>456</Config></root>');
-- insert existing (Violation of UNIQUE KEY constraint 'ck_Configuration')
insert into dbo.Devices(Configuration)
values('<root><Config>456</Config></root>');
--check if exists (lookup will seek on our ck_Configuration index)
declare @x xml = '<root><Config>789</Config></root>'
declare @i int;
if exists(select 1 from dbo.Devices where ConfigurationChecksum = binary_checksum(cast(@x as varchar(max))))
begin
raiserror('Already exists!', 10, 1) with nowait;
end else
begin
insert into dbo.Devices(Configuration)
values(@x);
set @i = scope_identity();
raiserror('Created new config %d', 10, 1, @i) with nowait;
end
正如Shnugo所提到的,只有当XML文档完全相同时才会有效。如果您需要约束XML文档的子集,那么您仍然可以使用相同的策略,但需要在元素子集上计算校验和:
declare @x xml = '<root><Name>ABC</Name><Port>80</Port><Created>2001-01-01</Created></root>'
select @x.query('/*/*[local-name()=("Name","Port")]'), binary_checksum(cast(@x.query('/*/*[local-name()=("Name","Port")]') as varchar(max)))
要做到这一点,你需要包装一个函数并从你的约束中引用它。
答案 1 :(得分:1)
最简单的方法是对所有相关值进行简单连接,例如value1|value2|value3|value4
给定顺序中的所有这些值必须是唯一的。
如果你愿意,你可以
NEWID()
)或IDENTITY值,以便轻松处理...