Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server 2008–;无符号整数数据类型_Sql_Sql Server 2008_Sqldatatypes_Unsigned Integer - Fatal编程技术网

SQL Server 2008–;无符号整数数据类型

SQL Server 2008–;无符号整数数据类型,sql,sql-server-2008,sqldatatypes,unsigned-integer,Sql,Sql Server 2008,Sqldatatypes,Unsigned Integer,我使用的是SQL SERVER 2008,在我的各个表中有许多INT、SMALLINT字段,我知道它们都是0或大于0,也就是说,我可以不带符号地接受它们 是否有创建/使用未签名数据类型的简单方法,或者我必须创建类型->制定规则->使用创建的类型;如下文所述 如果这是在SQL中使用Unsigned的唯一方法,那么使用Unsigned有什么缺点/缺点吗?主要(也是非常关键的)缺点是,您提供的链接似乎实际上并没有达到您认为的效果 它只是生成一个只能为正的新整数类型,它不会为您提供任何因使用无符号字段

我使用的是SQL SERVER 2008,在我的各个表中有许多INT、SMALLINT字段,我知道它们都是0或大于0,也就是说,我可以不带符号地接受它们

是否有创建/使用未签名数据类型的简单方法,或者我必须创建类型->制定规则->使用创建的类型;如下文所述

如果这是在SQL中使用Unsigned的唯一方法,那么使用Unsigned有什么缺点/缺点吗?

主要(也是非常关键的)缺点是,您提供的链接似乎实际上并没有达到您认为的效果

它只是生成一个只能为正的新整数类型,它不会为您提供任何因使用无符号字段(这似乎是您的主要目标)而节省的空间。也就是说,它们的
unsignedSmallint
的最大值将与
smallint
的最大值相同,因此您仍然会浪费这些额外的位(但由于无法插入负值,因此更是如此)

也就是说,他们的
unsignedInt
不允许值大于2^31-1

我理解并欣赏在1亿行中,在单个列上使用int32和int64可以节省大约380MB的内存。也许最好的方法是在读取存储值后(理想情况下是在一个视图中,并且仅从该视图中读取)对其进行偏移,然后在执行插入操作时向该值添加-2^31。。但是问题是int32的解析发生在insert之前,因此
而不是
触发器将不起作用。。(我不知道有什么方法可以使INSTEAD of触发器接受与所属表不同的类型)

相反,您在这方面的唯一选择是使用存储过程设置值,然后您可以使用视图或存储过程取回值:

create table foo
(fooA int)
GO

CREATE VIEW [bar]
AS
SELECT CAST(fooA AS BIGINT) + 2147483647 AS fooA
FROM foo
GO

CREATE PROCEDURE set_foo
    @fooA bigint
AS
BEGIN
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    IF @fooA < 4294967296 AND @fooA >= 0
        INSERT INTO foo VALUES (@fooA - 2147483647)
    --ELSE
        -- throw some message here
END
GO
您将看到返回的值是无符号的,但是返回的值是int64而不是unsigned32,因此应用程序需要将其视为仍然是int64


如果您有这样一个案例,您将看到这样做的显著改进(例如表中的几乎每一列都是需要的两倍),那么上述工作可能是有保证的,否则,我将只使用
bigint

适当的解决方案取决于您试图解决的问题。如果这是一个标识字段,并且您的目标是使表可以容纳的行数翻倍,而不需要为每行存储4个额外字节来使用bigint,那么只需将该字段的种子设置为-2147483648,而不是1。如果需要存储大于21.47亿的值,请使用更大的数据类型。

要将带符号的smallint转换为无符号的数字,请尝试以下操作:

CAST(yourSignedSmallInt AS int) & 0xffff
要将有符号整数转换为无符号数,请尝试

CAST(yourSignedInt AS bigint) & 0xffffffff
例如,如果您的表字段x是smallint,并且希望返回
无符号
值,请重试

SELECT (CAST(x AS int) & 0xffff) FROM ... WHERE ....

如果原因是您只想确保值大于等于零,那么您可以对列使用简单的
检查
约束。通过采用Unsigned,我们可以更好地使用内存/存储。原因不是为了确保该值是否大于0。这纯粹是为了节省内存。看起来您正在尝试优化一些不应该优化的内容。让DBMS管理它的内存,这是非常好的。我的表中有10万行,有一列的值在50000-60000之间,将其作为无符号的smallint不是一个好主意吗。另外,我还有一个例子,可以使用Unsigned Int代替Bigint。只需使用
整数
,并添加
检查
约束或触发器来检查值。
SELECT (CAST(x AS int) & 0xffff) FROM ... WHERE ....