【问题标题】:How to generate a uniqueidentifier in sql if null如果为null,如何在sql中生成唯一标识符
【发布时间】:2017-08-05 02:23:08
【问题描述】:

我正在尝试向现有的唯一标识符类型 SQL 表添加一列。该列不能为空,当然也是唯一的。我已经尝试过这段代码:

ALTER TABLE ScheduleJobs ADD CurrentInstanceID uniqueidentifier not null

接着是:

ALTER TABLE ScheduleJobs ADD CONSTRAINT DF_CurrentInstanceID DEFAULT newsequentialid() FOR CurrentInstanceID

但是,当我创建一个新记录(来自 C#)时,唯一标识符始终全为零(可能为 null。)我可以在 C# 中创建 GUID,并在创建一个工作正常的新记录时将其传递给 sql,但我我担心可能会创建重复的 GUID。根据我的阅读,这似乎是一种极其罕见的情况,但是让任何类型的潜在错误四处飘荡似乎总是不好的做法。请注意,该字段不会是表的 PK。为了教育,欢迎提出建议和意见。

我正在使用带有 MS SQL SERVER 2008 的 C# 4.0 框架

【问题讨论】:

  • 你考虑过使用 GUID 吗?
  • 尝试在 sql 端使用 NEWID()
  • 您使用哪种技术访问数据库?我知道实体框架默认情况下不会从 db 中设置默认值,因此没有设置默认值。您几乎可以在代码中生成一个新的 guid,它是唯一的,但不是连续的。
  • guid 在表中不是唯一的可能性极低。即使你点击它,如果你已经有约束,SQL Server 也会抛出同样的错误。我认为你过度设计了。我想说不要修复没有损坏的东西。
  • 我无法仅在 T-SQL 中重现这一点。在表中插入没有 ID 的行将创建一个新的 GUID。您是否可能向服务器发送零 GUID 而不是 NULL? GUID 是一个结构,这意味着它不能为空。除非您将其定义为 Guid?在您的代码中,传递一个空值将导致一个带有零的 Guid

标签: c# sql


【解决方案1】:

抱歉耽搁了,但我很高兴地说我已经解决了这个问题。感谢大家的大力支持。虽然没有人一针见血(顺便说一句,有一些非常好的建议),但 Eldog 在他的评论中提出了 Entity Framework 的表现不佳。多亏了他,我简单地用谷歌搜索了 Entity Framework + GUID 并找到了解决方案。

This article 逐步解决问题,并就问题、解决方案和解决问题的步骤给出了很好的解释。我会注意到,我决定一次通过并测试一个步骤,并且我不必执行最后一步。这让我相信部分问题可能已在实体框架的更高版本中得到解决。

我只是在设计视图(不是 xml)中提取了 edmx 文件并将StoreGeneratedPattern 属性设置为“身份”。

再次感谢您的帮助和建议。你们真是一群了不起的人。

【讨论】:

  • 该链接不再可用。总是建议在 StackOverflow 上提供一些答案以避免这种情况。
  • 请重新阅读我的答案并注意:我只是在设计视图(不是 xml)中提取了 edmx 文件并将 StoreGeneratedPattern 属性设置为“Identity”
【解决方案2】:

在创建记录时,您的 C# 代码是否尝试传入 CurrentInstanceID?如果是这样,您可以从 INSERT 语句中删除该列吗?

我们使用数字主键来做到这一点。我们的 C# 代码调用存储过程以对我们的记录进行 CRUD 操作。 C# 代码在客户端生成一个否定键供自己使用。当它准备好创建记录时,它会将这个键传递给存储过程。

proc 忽略此键并插入其余数据。 proc 的输出是 SQL 分配给记录的实际键。最后,C# 代码将新键合并到现有数据中。

【讨论】:

    【解决方案3】:

    我不会为此使用 GUID。 GUID 用于 Windows 中的很多操作,因此这将不是一个仅在您的应用程序中唯一的标识符,它将是一个在您的操作系统中唯一的标识符。除非这对你的情况有意义,否则我不会使用它。

    您可以使用增量值,例如简单的uint。如果您的表已经有一些数据,您可以编写一个脚本,用新列的增量值填充现有行,并在执行该脚本后将唯一约束添加到您的列。

    【讨论】:

    • 这有点误导,在其他操作中使用 GUID 作为唯一 id 的事实是没有意义的,碰撞的机会是如此之小。 stackoverflow.com/a/2977648/1246040
    • 我基本上用它来进行版本控制。老实说,使用 GUID 不是我的想法(哎呀,我对它们一无所知。)但是,我的老板特别指示我使用 GUID。我的观点是,GUID 不需要对整个世界都是唯一的。
    • newsequentialid 对于 Windows 安装是唯一的。 msdn.microsoft.com/library/ms189786.aspx
    • @Mataniko 是的,你是对的,达到相同 GUID 的机会非常小。但对我来说,如果某件事必须仅在一种情况下是独一无二的,那么它不需要在更大的情况下是独一无二的。这只是关于分离关注点。它也可以在不使用 GUID 的情况下以简单的方式完成。这是一种观点和一种做事方式,还有其他的;)
    • 为了更好地说明我的意思:如果您正在制作客户管理应用程序(在国家范围内),您不会使用他们的国民身份证号码作为标识符,您将使用增量价值。即使他们的国民身份证号码更大,并且您确定不会发生冲突,也没有多大意义。
    【解决方案4】:

    在您原来的 Create table 或 alter table 中使用如下内容

    create table ScheduleJobs (keyval int, id2 uniqueidentifier not null default newsequentialid())
    

    然后不要在插入中引用该列,并且将添加一个新的 GUID 值

    【讨论】:

    • 这和他已经写的一样。事实上,如果您从 SSMS 编写表格,语法将与 OP 的相同
    • 好地方。错过了。因此,如果 OP 没有引用第二列,那么它将有一个默认值?我还缺少其他东西吗?
    • 这里只是一个注释...我读过一篇文章,说 SQL Server 存在一个错误。该帖子声明将列生成和 newsequentialid() 声明分开,就像我在我的 OP 中所做的那样。我没有测试也无法确认,但以防万一其他人有问题。我不确定是否要创建一个新表作为示例,我的场景是更改现有表。感谢您的评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多