2014-06-19 131 views
0

我有一个SQL Server数据库,它将包含许多连接的表,每个表都有一个主键。我有一个Dictionary跟踪每个表的主键字段。我的任务是每天从以属性为中心的XML文件中提取数据并将它们插入到主数据库中。每个XML文件具有相同的模式。我通过使用XMLReader并将数据导入DataSet来完成此操作。生成一个唯一的主键

我无法使用AutoNumber作为密钥。比方说,昨天的XML文件产生了DataTable类似于以下,并将其导入到数据库

------------------------------------- 
| Key | Column1 | Column2 | Column3 | 
|-----------------------------------| 
| 0 | dsfsfsd | sdfsrer | sdfsfsf | 
|-----------------------------------| 
| 1 | dertert | qweqweq | xczxsdf | 
|-----------------------------------| 
| 2 | prwersd | xzcsdfw | qwefkgs | 
------------------------------------- 

如果今天的XML文件中生成以下DataTable

------------------------------------- 
| Key | Column1 | Column2 | Column3 | 
|-----------------------------------| 
| 0 | sesdfsd | hjghjgh | edrgffb | 
|-----------------------------------| 
| 1 | wrwerwr | zxcxfsd | pijghjh | 
|-----------------------------------| 
| 2 | vcbcvbv | vbnvnbn | bnvfgnf | 
------------------------------------- 

然后,当我去导入新数据输入数据库使用SqlBulkCopy,那么将会有重复的密钥。我的解决方案是使用DateTime.Now.Ticks来生成唯一的密钥。从理论上讲,这应该总是创造一个独特的关键。

但是,由于某种原因,DateTime.Now.Ticks不是唯一的。例如,即使我在不​​同时间生成该值,一行中的5个记录都可能具有密钥635387859864435908,并且接下来的7个记录可能具有密钥635387859864592164。我想说,问题的原因是我的脚本在更新时间之前多次调用DateTime.Now.Ticks

任何人都可以想到更好的方法来生成密钥吗?

+0

是否有一个原因,你不能只使用GUID? –

+1

'DateTime.Now.Ticks'不是唯一的。正如你发现的那样,一个处理器可以在* tick中完成的工作量实际上相当多。 –

+0

@ChrisHaas我还没有听说过GUID。我正在研究它们是否能解决问题 – TFischer

回答

3

出于性能原因,可能会将DateTime.Now的值缓存少量时间。我们做类似的事情,有两种可能的选择,我们使用:

  1. 保留您在服务器上使用的号码列表,如果可以确定号码已经增加已使用
  2. 将字段转换为字符串,并在其末尾附加GUID或其他随机标识符。 GUID可以用System.Guid.NewGuid().ToString();

显然这些计划都不会使碰撞风险为零,但它们可以帮助减少它。

2

如果你有大量的数据,你需要为每个行的唯一密钥只使用GUID

0

你可以做类似下面获得唯一的ID(SQL Fiddle):

SELECT 
CONCAT(YEAR(GETDATE()), DATEDIFF(DAY, STR(YEAR(GETDATE()), 4) + '0101', 
GETDATE()) + 1, ROW_NUMBER() OVER(ORDER BY id DESC)) UniqueID 
FROM supportContacts s 

如果您每天仅运行一次查询,则这将起作用。如果你每天跑不止一次,你需要抓住秒或其他东西(SQL Fiddle):

SELECT CONCAT(CurrYear, CurrJulian, CurrSeconds, Row) AS UniqueID 
FROM 
(
    SELECT 
    YEAR(GETDATE()) AS CurrYear, 
    DATEDIFF(DAY, STR(YEAR(GETDATE()), 4) + '0101', GETDATE()) + 1 AS CurrJulian, 
    ROW_NUMBER() OVER(ORDER BY id DESC) AS Row, 
    datediff(second, left(convert(varchar(20), getdate(), 126), 10), getdate()) AS CurrSeconds 
    from supportContacts s 
) AS m