为啥我的 SQL Server 列看起来没有默认值,即使它的行为就像它一样?

Posted

技术标签:

【中文标题】为啥我的 SQL Server 列看起来没有默认值,即使它的行为就像它一样?【英文标题】:Why does my SQL Server column appear to have no default value even though it acts like it does?为什么我的 SQL Server 列看起来没有默认值,即使它的行为就像它一样? 【发布时间】:2015-02-15 04:12:02 【问题描述】:

我有一个 SQL Server 表,其中有四列,其中一列是默认值为 getdate() 的日期时间列。我有这个表的两个副本,一个在我可以完全控制的开发数据库服务器中,另一个在我几乎没有权限的生产数据库服务器中。

以下是开发表的外观:

我选择了 dtInsert 列。请注意,此列的默认值为 getdate()。我这张表的生产版本是完全一样的。当我向该表添加一行时,dtInsert 单元格默认为getdate(),就像我期望的那样。当数据库管理员生成生产表的脚本时,它包含默认值约束。但是,当我在 SQL Server Management Studio 2012 中查看表设计时,它显示该列没有默认值。见这里:

当我生成数据库图表时,它还显示 dtInsert 列没有默认值。同样,我通过测试知道我的生产数据库服务器中的 dtinsert 列确实默认为getdate()

这是 SQL Server Management Studio 2012 版中的错误吗?是否有一些我没有的权限会导致这种行为?是别的吗?为什么该列似乎没有默认值,即使它有?

【问题讨论】:

我的猜测是权限问题 - 但我不确定哪些权限。我的 google-fu 目前还不够强大。 我相信您需要对象的 DDL 权限才能查看默认值。 db_owner 或 db_ddladmin 会这样做。 您可以看到列但看不到约束似乎很奇怪?试试这个:SELECT * FROM sys.default_constraints WHERE [parent_object_id] = OBJECT_ID(N'_table_name_'); 在两种环境中查看是否存在差异。如果这在 prod 中返回 DEFAULT,那么它可能是 SSMS 的问题。如果没有行,那么它是一个权限,很可能是VIEW DEFINITION @srutzky 两个环境之间的定义不同。在生产服务器中是NULL,在开发服务器中是getdate() 这不是“不同的”;-)。这意味着您无权查看它。这指向@Kritner 的答案(应该更具体),因为您没有权限对VIEW DEFINITION 使用默认约束,或者可能还有其他对象。 【参考方案1】:

这是 SQL Server Management Studio 2012 版中的错误吗?

没有。

是否有一些我没有的权限导致了这种行为?

是的。

在对问题的评论中,我建议运行以下命令:

SELECT *
FROM sys.default_constraints
WHERE [parent_object_id] = OBJECT_ID(N'_table_name_');

结果是生产中的行返回,其中[definition] 列是NULL。这意味着 DEFAULT CONSTRAINT 存在,但您要么:

缺乏查看定义的明确和隐含权限

已被明确拒绝查看它的权限。

您可以在 Metadata Visibility Configuration 的 MSDN 页面上阅读此内容。

现在,有多种权限(VIEW DEFINITIONVIEW ANY DEFINITION 等)会影响此设置。这些可以应用于各个层面:

对象本身 架构 数据库 等

考虑到多个 Windows 组的成员身份(如果正在使用),权限会变得更加复杂。

甚至可以在多个级别授予权限。权限也是附加的:在您的登录名所属的 3 个 Windows 组中的 1 个中的 GRANT 就足以工作。但是,任何这些级别中的拒绝优先,在这种情况下,您没有定义。

正如我在对该问题的评论中提到的,这实际上是生产 DBA 的问题,他们配置了权限,以至于您看不到定义。如果不确切知道为什么看不到定义(缺少 GRANT 或存在 DENY?),发出 GRANT 语句试图获得此权限是没有用的(特别是因为无法看到定义意味着您同样不会能够向任何人授予此类权限)。请与负责生产的人交谈,告诉他们您看不到默认约束的定义,但您希望能够看到。如果您目前不能有特定原因,您会被告知。如果这是一个疏忽,他们应该以受控方式纠正它,可能需要复制到其他环境等。

【讨论】:

【参考方案2】:

在 SSMS 中查看对象时 dev 和 prod 之间的差异似乎是由于您的用户帐户在 dev 和 prod 之间的权限不同。

要查看表对象的默认值,您至少需要对该对象具有以下权限之一才能查看默认值:

ALTER 对 OBJECT 或 CONTROL 对 OBJECT 或 TAKE OWNERSHIP 对 OBJECT 或 查看对象的定义

找到这个https://dba.stackexchange.com/questions/78769/minimum-sql-server-rights-that-allow-viewing-column-default-values

这似乎几乎可以回答你的问题:)

【讨论】:

这是否意味着我需要做一个Grant View Permission on <mytable> to <username>?另外,我实际上并不知道 dba 堆栈交换。 几乎 - 请注意它是“查看定义”权限而不是“查看权限”请参阅 - technet.microsoft.com/en-us/library/ms175808(v=sql.105).aspx 或答案中指定的任何其他权限 - 更改、控制、取得所有权或查看定义跨度> Kritner,您可能想要更改该链接和图像。这些是指扩展属性。这是对象本身的定义问题。 @srutzky 啊,我猜你是对的,很难找到有关查看默认约束以替换它的权限的细节:O @srutzky 也很可能是这样,但是我没有理由确认或否认这一点。桌子肯定会得到它! :)

以上是关于为啥我的 SQL Server 列看起来没有默认值,即使它的行为就像它一样?的主要内容,如果未能解决你的问题,请参考以下文章

SQL server中某个表的字段值为啥不能修改?

SQL Server:通过查询找出列的默认值

如何在 SQL Server 中将函数设置为默认值?

如何在 SQL Server 的单个批次中为列添加默认值并使用默认值更新所有行?

如何更改sql server中的默认列值

将具有默认值的列添加到 SQL Server 中的现有表