11

我今天遇到了类似的代码。

SELECT AuditDomain, 
    ObjectId,
    AuditSubdomain = CONVERT(VARCHAR(50), NULL),
    SubDomainObjectId = CONVERT(INT, NULL)
FROM Audit

这似乎暗示数据类型信息可以与 NULL 值相关联。这是否将元数据附加到将其标识为指定数据类型的 NULL 值?

这篇文章详细介绍了一种在 Sql Server 中查找数据类型的方法,但是当我尝试以下行时,它返回为 NULL:

SELECT CAST(SQL_VARIANT_PROPERTY(CONVERT(INT, NULL), 'BaseType') AS VARCHAR(20))
4

5 回答 5

16

在 SQL Server中,默认情况下在我能想到的所有场景中都是一个NULLINT您可以使用以下代码确定这一点:

SELECT x = NULL INTO #x;
EXEC tempdb..sp_columns '#x';

结果:

TABLE_QUALIFIER TABLE_OWNER TABLE_NAME COLUMN_NAME DATA_TYPE TYPE_NAME
--------------- ----------- ---------- ----------- --------- ---------
tempdb          dbo         #x___...   x           4         int

在您将其放入表格或以其他方式将其与一些上下文元数据相关联之前,这对您有什么好处?INT它有什么区别DATETIME呢?你将如何处理这些信息?

SQL_VARIANT_PROPERTY返回NULL,因为它似乎需要元数据值才有意义。观察(使用不同的类型只是为了混合):

SELECT SQL_VARIANT_PROPERTY(NULL, 'BaseType');

DECLARE @x DATE;

SELECT SQL_VARIANT_PROPERTY(@x, 'BaseType');

DECLARE @y DATE = SYSDATETIME();

SELECT SQL_VARIANT_PROPERTY(@y, 'BaseType');

结果:

NULL

NULL

date

所以它似乎需要一个类型一个值才能准确地确定基本类型。

至于它为什么会这样工作,耸耸肩。您必须询问具有源代码访问权限的人。

请注意,NULL只有在您强制 SQL Server 使用时才需要采用基本类型:您已经基于它创建了一个表。在这种情况下,SQL Server 很可能会返回错误(实际上在许多情况下,它必须猜测您所指的数据类型)。避免这种情况的方法是不要创建 SQL Server 必须猜测的情况(这就是为什么我问,你将如何处理这些信息?)。

于 2013-03-26T21:24:57.297 回答
0

Null 没有数据类型。null 的目的是在值和类型上表示“未知”。

ISNULL() 返回第一个参数的数据类型以及提供给它的数据类型。

http://msdn.microsoft.com/en-us/library/ms187928.aspx

于 2013-03-26T21:47:28.727 回答
0

我知道您已经有了一些好的答案,但我认为 SQL_VARIANT_PROPERTY 被误解了。

您将 SQL_Variant_Property 与列一起使用,然后在其元数据属性上指示您想要什么。但是,如果它为空,它不会告诉你太多。

例如:

declare 
    @Start date = getdate()
,   @End datetime= getdate()
,   @Int int = 1
,   @DateNull date
;


select 
    sql_variant_property(@Start, 'BaseType')
,   sql_variant_property(@End, 'BaseType')
,   sql_variant_property(@Int, 'BaseType')
,   sql_variant_property(@DateNull, 'BaseType')

将返回三个数据类型和一个空值。处理 NULL 是 SQL 的重要组成部分。很多人,包括我自己,有时都想用一个值来处理 null 来表示它,或者在其他时候不在乎。SQL Variant 仅适用于带有参数的填充值:'BaseType',否则它将返回 null。据我所知,这是由于 SQL 说:“你这里没有数据,没有什么可确定的内存使用情况。”

通常我会在使用整数时指定 isnull(@thing, 0) 如果我明确希望数据集包含未知数的零。在其他时候,我可能希望让用户知道 null 出现对报告做了其他 isnull(@thing, 'not present') 的事情。还有一些时候,你可以使用 coalesce 来处理一系列可能性,coalesce(@thing, @otherthing, @yetotherthing, 'unknown')。

我认为在代码中,当我不确定您真正需要在哪里做这样的事情时,您正在目睹某人正在转换某些东西。表中列的数据类型被维护为它需要的数据类型,当它为 NULL 时 SQL 不会在其中存储内存。因此,恕我直言,需要更改它似乎是任意的。我确实知道,当您期望使用我相信在 SQL 2008 中引入的 SPARSE 选项有更多空值时,您可以处理更好的内存消耗。但我不知道何时将几乎不消耗任何东西的东西转换为更多。

于 2013-03-26T22:09:29.187 回答
0

当然 NULL 具有数据类型。尝试下一个代码以确认:

SELECT 
  CAST(NULL AS date) AS c1,
  CAST(NULL AS time) AS c2
INTO #x;
EXEC tempdb..sp_columns '#x';

而且我认为 SQL_VARIANT 实现中存在错误,因为它丢失了有关 NULL 类型的信息。太糟糕了!

于 2016-03-17T15:07:37.347 回答
0

我不同意@aaron-bertrand。由于默认情况下 SQl 服务器创建了具有整数数据类型的列来存储 NULL 值,因为 Null 可以插入到 Int、Datetime、Date、Varchar 任何其他列中。

当使用 SELECT x = NULL INTO #x; 在表中插入 Null 时

SQl 服务器默认创建整数类型列,因为可以将 Null 插入 Integer 列。

所以可能是由于我们编写的查询的性质“SELECT x = NULL INTO #x;” 这使列成为整数并放入 NULL 值。

于 2017-07-20T14:06:38.823 回答