2016-12-07 12 views
4

Я пытаюсь преобразовать поле TIMESTAMP в таблицу в строку, чтобы ее можно было распечатать или выполнить как часть динамического SQL. SSMS может это сделать, поэтому для этого должен быть встроенный метод. Однако я не могу заставить его работать с использованием T-SQL.Как преобразовать значения TIMESTAMP в VARCHAR в T-SQL, как SSMS?

Следующая правильно отображает результат таблицы:

SELECT TOP 1 RowVersion FROM MyTable 

Это показывает 0x00000000288D17AE. Однако мне нужно, чтобы результат был частью большей строки.

DECLARE @res VARCHAR(MAX) = (SELECT TOP 1 'test' + CONVERT(BINARY(8), RowVersion) FROM MyTable) 
PRINT(@res) 

Это дает ошибку: The data types varchar and binary are incompatible in the add operator

DECLARE @res VARCHAR(MAX) = (SELECT TOP 1 'test' + CONVERT(VARCHAR(MAX), RowVersion) FROM MyTable) 
PRINT(@res) 

Это приводит к мусорным символов: test (®

В самом деле, пространства просто нулевые символы и завершает строку с целью запуска динамического SQL с использованием EXEC().

DECLARE @sql VARCHAR(MAX) = 'SELECT TOP 1 ''test'' + CONVERT(VARCHAR(MAX), RowVersion) FROM MyTable' 
EXEC (@sql) 

Это просто отображает результат таблицы со словом «тест». Все после «теста» в динамическом SQL отключается, потому что функция CONVERT сначала возвращает завершающие нулевые символы.

Очевидно, что я хочу, чтобы результирующая строка была «test0x00000000288D17AE» или даже десятичный эквивалент, который в этом случае был бы «test680335278».

Любые идеи были бы весьма признательны.

+0

SSMS не делает любое такое преобразование. Он отображает данные в сетке так же, как * любое * другое приложение .NET. Двоичные значения обычно отображаются как hex или Base64. Почему вы хотите преобразовать двоичное значение в строку? Почему бы не передать его как есть или использовать его в качестве параметра? BTW 'rowversion' также не может использоваться в качестве идентификатора, если вы считаете, что можете использовать его как читаемый человеком ключ –

+0

[rowversion] (https://msdn.microsoft.com/en-us/library/ms182776 .aspx) является «двоичным (8)» значением, как «bigint». Вы можете передать его в bigint, затем использовать [FORMAT] (https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k (format_TSQL); k (sql13.swb.tsqlresults.f1); к (sql13.swb.tsqlquery.f1); k (MiscellaneousFilesProject); k (DevLang-TSQL) & rd = true), чтобы получить его шестнадцатеричное представление, например 'FORMAT (cast (RowVersion) как bigint)," x ")' или 'FORMAT (литье (литье (RowVersion) как бинарный (8)) как bigint), «x») '. Формат не будет содержать строку с нулями, хотя –

+1

Хотя это недокументировано, я считаю, что 'master.sys.fn_varbintohexstr' преобразует любое значение типа VARBINARY в значение« NVARCHAR ». См. [Здесь] (http://www.sqlservercentral.com/Forums/FindPost1708985.aspx) для получения дополнительной информации о том, как эта функция работает вместе с исходным кодом. – 3N1GM4

ответ

10

SELECT 'test' + CONVERT(NVARCHAR(MAX), CONVERT(BINARY(8), RowVersion), 1). Уловкой является 1 до CONVERT в качестве стиля, за documentation. (Pass 2, чтобы опустить 0x.)

+0

Вы пробовали это? Он возвращает 'Явное преобразование из временной метки типа данных в nvarchar (max) не допускается'. Если я изменю его на «VARCHAR», ошибки нет, но он все еще показывает мусор, как описано в Вопросе. – Neo

+1

@Neo: Неплохо, я неправильно предположил, что SQL Server будет рассматривать «ROWVERSION» как двоичный тип. Это не так, поэтому для выполнения этой работы необходим промежуточный шаг перехода. –

+0

Принимаемый ответ - лучшее решение, которое я думаю. 'SELECT TOP 1 'test' + master.sys.fn_varbintohexstr (RowVersion) FROM MyTable' получает меня именно то, что мне нужно. – Neo

2

Как уже упоминалось в комментариях, недокументированная функция master.sys.fn_varbintohexstr преобразует двоичный в строку таким образом, чтобы вы могли затем сцепить с другим значением строки:

DECLARE @binary BINARY(8) 
SELECT @binary = CAST(1234567890 AS BINARY(8)) 

SELECT @binary AS BinaryValue, 
     LEFT(master.sys.fn_varbintohexstr(@binary),2) + UPPER(RIGHT(master.sys.fn_varbintohexstr(@binary),LEN(master.sys.fn_varbintohexstr(@binary))-2)) AS VarcharValue, 
     'test' + LEFT(master.sys.fn_varbintohexstr(@binary),2) + UPPER(RIGHT(master.sys.fn_varbintohexstr(@binary),LEN(master.sys.fn_varbintohexstr(@binary))-2)) AS ConcatenatedVarcharValue 

Я пошел вперед и разделить первые два символа и не примените к ним функцию UPPER, чтобы точно воспроизвести формат, отображаемый при двоичном значении.

Результаты:

/--------------------------------------------------------------------\ 
|  BinaryValue | VarcharValue | ConcatenatedVarcharValue | 
|--------------------+--------------------+--------------------------| 
| 0x00000000499602D2 | 0x00000000499602D2 | test0x00000000499602D2 | 
\--------------------------------------------------------------------/ 
+0

Спасибо. 'SELECT TOP 1 'test' + master.sys.fn_varbintohexstr (RowVersion) FROM MyTable' получает меня именно то, что мне нужно. – Neo

0

Посмотрите на это:

SELECT 
substring(replace(replace(replace(replace(cast(CAST(GETDATE() AS datetime2) as 
varchar(50)),'-',''),' ',''),':',''),'.',''),1,18) 
+1

Добавьте объяснение в ответ на вопрос, почему это работает. – GiantsLoveDeathMetal