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 8

3 ответа:

Главный (и довольно критический) недостаток заключается в том, что ссылка, которую вы предоставляете, на самом деле не делает того, что вы думаете.

Он просто создает новый целочисленный тип, который может быть только положительным, он не обеспечивает вам никакой экономии места, которая в противном случае была бы результатом использования беззнакового поля (что, похоже, является вашей главной целью). это означает, что максимальное значение их unsignedSmallint будет таким же, как и максимальное значение для smallint, поэтому вы все равно будете тратить эти дополнительные Бит (но тем более, что вы не можете вставить отрицательные значения).

То есть их unsignedInt не допускают значений выше 2^31-1.

Я понимаю и ценю, что в 100 миллионах строк экономия от использования int32 vs int64 в одном столбце составляет около 380 МБ. Возможно, лучший способ для вас сделать это, чтобы справиться с этим, чтобы компенсировать ваше сохраненное значение после того, как вы прочитали его, в идеале в пределах представления и только когда-либо читать из этого представления, а затем при выполнении вставки добавить -2^31 к значению.. Но проблема в том, что синтаксический анализ для int32 происходит до вставки, поэтому триггеры 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 миллиарда, то используйте более крупный тип данных.