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