主要的(也是相当关键的)缺点是,您提供的链接似乎并没有真正做到您认为的那样。
它只是创建一个只能为正数的新整数类型,它不会为您提供任何空间节省,否则会因使用无符号字段而导致(这似乎是您的主要目标)。也就是说,它们的最大值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
来。