web-dev-qa-db-ja.com

SSMSのようにT-SQLでTIMESTAMP値をVARCHARに変換する方法は?

動的SQLの一部として印刷または実行できるように、テーブルのTIMESTAMPフィールドを文字列に変換しようとしています。 SSMSはそれを行うことができるので、それを行うには組み込みのメソッドが必要です。ただし、T-SQLを使用して動作させることはできません。

以下はテーブルの結果を正しく表示します:

_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 (®_

実際、スペースは単なるヌル文字であり、EXEC()を使用して動的SQLを実行するために文字列を終了します。

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

これは、Wordの「テスト」を含むテーブル結果を表示するだけです。 CONVERT関数が最初に終端のヌル文字を返すため、動的SQLの「テスト」以降はすべて切断されます。

明らかに、結果の文字列にしたいのは「test0x00000000288D17AE」または同等の10進数でさえあり、この場合は「test680335278」になります。

どんなアイデアでも大歓迎です。

12
Neo

SELECT 'test' + CONVERT(NVARCHAR(MAX), CONVERT(BINARY(8), RowVersion), 1)。トリックは、スタイルとして1CONVERTに、 ドキュメント ごとに指定します。 (2を省略するには、0xを渡します。)

21
Jeroen Mostert

コメントで述べたように、文書化されていない関数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

先に進み、最初の2文字を分割し、UPPER関数をそれらに適用せず、バイナリ値のときに表示される形式を正確に再現しました。

結果:

/--------------------------------------------------------------------\
|     BinaryValue    |    VarcharValue    | ConcatenatedVarcharValue |
|--------------------+--------------------+--------------------------|
| 0x00000000499602D2 | 0x00000000499602D2 |  test0x00000000499602D2  |
\--------------------------------------------------------------------/
2
3N1GM4

これを見てください:

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