SQL Server 2008-целочисленные типы данных без знака
Я использую SQL SERVER 2008, у меня есть несколько полей INT, SMALLINT в моих различных таблицах, и я знаю, что все они будут равны 0 или больше 0, т. е. я могу взять их без знака.
Существует ли простой способ создания / использования неподписанных типов данных или мне придется создать type- > Make Rule - >Use the Created Type; как указано в следующей статье?
Http://www.julian-kuiters.id.au/article.php/sqlserver2005-unsigned-integer
Если это единственный способ использовать Unsigned в SQL есть ли какой-либо недостаток / недостаток его использования?
3 ответа:
Главный (и довольно критический) недостаток заключается в том, что ссылка, которую вы предоставляете, на самом деле не делает того, что вы думаете.
Он просто создает новый целочисленный тип, который может быть только положительным, он не обеспечивает вам никакой экономии места, которая в противном случае была бы результатом использования беззнакового поля (что, похоже, является вашей главной целью). это означает, что максимальное значение их
unsignedSmallint
будет таким же, как и максимальное значение дляsmallint
, поэтому вы все равно будете тратить эти дополнительные Бит (но тем более, что вы не можете вставить отрицательные значения).То есть их
Я понимаю и ценю, что в 100 миллионах строк экономия от использования int32 vs int64 в одном столбце составляет около 380 МБ. Возможно, лучший способ для вас сделать это, чтобы справиться с этим, чтобы компенсировать ваше сохраненное значение после того, как вы прочитали его, в идеале в пределах представления и только когда-либо читать из этого представления, а затем при выполнении вставки добавить -2^31 к значению.. Но проблема в том, что синтаксический анализ для int32 происходит до вставки, поэтому триггерыunsignedInt
не допускают значений выше 2^31-1.INSTEAD OF
не будут работать.. (Я не знаю никакого способа сделать триггер INSTEAD OF, который принимает различные типы к таблице owning)Вместо этого ваш единственный вариант в этом отношении-использовать хранимые процедуры для
set
значения, затем вы можете использовать представление или сохраненный proc, чтобы получить значение обратно: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
Вы увидите, что значения возвращаются unsigned, однако возвращаемые значения int64, а не unsigned32, поэтому ваше приложение должно будет обращаться с ними, как если бы они все еще были int64.
Если у вас есть случай, когда вы увидите значительное улучшение от выполнения этого (например, почти каждый столбец в таблице в два раза больше, чем он должен быть в противном случае), то усилия выше могут быть оправданы, иначе я бы просто остался с
bigint
вместо этого.
Чтобы преобразовать знак smallint в беззнаковое число, попробуйте сделать следующее:
CAST(yourSignedSmallInt AS int) & 0xffff
Чтобы преобразовать signed int в unsigned number, попробуйте
CAST(yourSignedInt AS bigint) & 0xffffffff
Например, если ваше поле таблицы x является smallint и вы хотите вернуть значение
unsigned
, то попробуйтеSELECT (CAST(x AS int) & 0xffff) FROM ... WHERE ....
Подходящее решение зависит от проблемы, которую вы пытаетесь решить. Если это поле идентификатора, и ваша цель состоит в том, чтобы удвоить число строк, которые может содержать ваша таблица, не сохраняя 4 дополнительных байта с каждой строкой, чтобы использовать bigint, то просто посеять поле в -2,147,483,648, а не 1. Если вам нужно хранить значения, превышающие 2,147 миллиарда, то используйте более крупный тип данных.