У чому причина цієї проблеми з CONVERT ()?


12

Розглянемо наступні два твердження:

PRINT CONVERT(NUMERIC(38, 0), 0x0100000001, 0);
PRINT CONVERT(NUMERIC(38, 0), 0x0100010001, 0);

Обидва твердження повертаються -1; Хіба це невірно, оскільки друге двійкове значення на десяткове 65,536 вище, ніж перше значення, чи не так?

Невже це не може бути пов’язано з тихим усіченням?

Якщо я запускаю такі твердження:

PRINT CONVERT(NUMERIC(38, 0),   0x00000001, 0);
PRINT CONVERT(NUMERIC(38, 0),   0x00010001, 0);

Мені подано таку помилку:

Msg 8114, Level 16, State 5, Line 1
Error converting data type varbinary to numeric.

Як я можу діагностувати, що відбувається тут?

Я запускаю це на SQL Server 2012, v11.0.5058. Результати однакові для SQL Server 2008 R2 SP2, SQL Server 2005 та SQL Server 2000.


4
Десяткові і цілі числа кодуються у варбінарі дуже різними. Десятникам потрібно більше місця. СпробуйтеSELECT CONVERT(VARBINARY(32), 1), CONVERT(VARBINARY(32), 1.0);
Аарон Бертран

4
Аарон на місці. Ваш мозок перетворює двійкові дані в цілі дані, а потім прямо в числові, але SQL Server не робить це неявне перетворення з двійкового -> цілого -> числового (х, у). Для SQL Server слідувати розумового процесу, ви повинні зробити що - щось на зразок цього: PRINT CONVERT(NUMERIC(38, 0), convert(int, 0x00000001), 0); PRINT CONVERT(NUMERIC(38, 0), convert(int, 0x00010001), 0);.
Томас Стрінгер

5
Перший байт - масштаб (0x01 = 1), другий байт - точність (0x00 = 0), кінцевий байт - значення (0x01 = 1). Не впевнений, для чого потрібні три та чотири байти. Знак є там, але для цього не потрібно два байти. Звичайно, перегортання цього біта, здається, ні на що не вплинуло.
Мартін Сміт

1
Спасибі, @MartinSmith - як же ти визначив, що перші два байти використовуються так? Це документально підтверджено?
Макс Вернон

3
@AaronBertrand: Чи хотіли б ви відповісти на це? Ми можемо відзначити це у списку "без відповіді".
Йон усіх торгів

Відповіді:


2

Десяткові і цілі числа кодуються у варбінарі дуже різними. Десятникам потрібно більше місця. Спробуйте:

SELECT CONVERT(VARBINARY(32), 1), CONVERT(VARBINARY(32), 1.0);

Що стосується вашої кінцевої мети - зберігати цілі номери як варбінарні, щоб заощадити простір, я думаю, що ви самі відповіли на це питання - не варто.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.