SQL Server 2008 – 无符号整数数据类型
Posted
技术标签:
【中文标题】SQL Server 2008 – 无符号整数数据类型【英文标题】:SQL Server 2008 – Unsigned Integer Data Types 【发布时间】:2011-11-08 04:41:36 【问题描述】:我使用的是 SQL SERVER 2008,我的各种表中有许多 INT、SMALLINT 字段,而且我知道它们都将为 0 或大于 0,即我可以将它们设为无符号。
是否有一种创建/使用无符号数据类型的简单方法,或者我必须创建类型->制定规则->使用创建的类型;如下文所述?
http://www.julian-kuiters.id.au/article.php/sqlserver2005-unsigned-integer
如果这是在 SQL 中使用 Unsigned 的唯一方法,那么使用它有什么缺点/缺点吗?
【问题讨论】:
如果原因是您只想确保该值大于等于零,那么您可以在列上使用简单的CHECK
约束。
通过Unsigned,我们可以更好地使用内存/存储。原因不是确保该值大于 0 或不。纯粹是为了节省内存。
看起来你正在尝试优化一些你不应该做的事情。让 DBMS 管理它的内存,它很擅长。
我的表中有十万行,并且有一列的值将在 50000-60000 的范围内,将其作为 unsigned smallint 不是一个好主意。另外,我还有一种情况,可以使用 Unsigned Int 代替 Bigint。
只需使用integer
并添加CHECK
约束或触发器来检查值。
【参考方案1】:
主要(也是相当关键的)缺点是,您提供的链接似乎并没有真正发挥您的作用。
它只是创建一个只能为正数的新整数类型,它不会为您提供任何节省空间,否则会因使用无符号字段而导致(这似乎是您的主要目标)。也就是说unsignedSmallint
的最大值与smallint
的最大值相同,因此您仍然会浪费这些额外的位(但更是如此,因为您不能插入负值)。
也就是说他们的unsignedInt
不允许超过 2^31-1 的值。
我理解并赞赏在 1 亿行中,在单个列上使用 int32 与 int64 可节省大约 380MB。也许你最好的方法是处理这个问题是在你读取它之后偏移你的存储值,理想情况下在一个视图中并且只从那个视图中读取,然后在执行插入时将 -2^31 添加到值..但问题是 int32 的解析发生在插入之前,因此INSTEAD OF
触发器将不起作用..(我不知道有什么方法可以制作一个接受与拥有不同类型的触发器的 INSTEAD OF 触发器表)
在这方面你唯一的选择是使用存储过程来set
值,然后你可以使用视图或存储过程来取回值:
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
这可以使用以下方法进行测试:
exec set_foo 123
exec set_foo 555
select * FROM bar
select * FROM foo
exec set_foo 0
exec set_foo 2147483648
exec set_foo 4147483648
select * FROM bar
select * FROM foo
您将看到返回的值是无符号的,但返回的值是 int64 而不是 unsigned32,因此您的应用程序需要将它们视为仍然是 int64。
如果您有这样的情况,您会看到这样做有显着改进(例如表中的几乎每一列都是原本需要的两倍大),那么上述努力可能是有道理的,否则我会留下来用bigint
代替。
【讨论】:
【参考方案2】:要将有符号的 smallint 转换为无符号数,请尝试以下操作:
CAST(yourSignedSmallInt AS int) & 0xffff
要将有符号整数转换为无符号数,请尝试
CAST(yourSignedInt AS bigint) & 0xffffffff
例如,如果您的表字段 x 是一个 smallint,并且您想返回 unsigned
值然后尝试
SELECT (CAST(x AS int) & 0xffff) FROM ... WHERE ....
【讨论】:
【参考方案3】:适当的解决方案取决于您要解决的问题。如果这是一个身份字段,并且您的目标是将表可以容纳的行数增加一倍,而无需为每行存储 4 个额外字节以使用 bigint,那么只需将该字段设置为 -2,147,483,648 而不是 1。如果您需要存储大于 21.47 亿的值,然后使用更大的数据类型。
【讨论】:
以上是关于SQL Server 2008 – 无符号整数数据类型的主要内容,如果未能解决你的问题,请参考以下文章
如何将所有数据库(快速)自 sql server 2008 express 传递到 sql server 2008 R2(无 express)
[转]无网络环境,在Windows Server 2008 R2和SQL Server 2008R2环境安装SharePoint2013 RT