Преобразование текста в двоичный код - TSQL - PullRequest
1 голос
/ 25 марта 2011

Я нашел несколько потоков по этому вопросу, используя функцию поиска, но ничего для чисто решения T-SQL.

необходимость - система хранит еженедельное расписание в виде 0 и 1 в строковом формате дляпредставлять неделю.1 означает да, 0 означает нет .... итак, 1100111 означает воскресенье да (первый), понедельник да (второй 1), вторник нет (0) ... и т. Д.

Короткий вопрос - Как сделатьЯ иду от символа ascii, такого как>, к его шестнадцатеричному коду '3E' и, в конечном итоге, к его двоичному представлению '00111110'?

Длинный вопрос - я извлекаю из плоской файловой системы, в которой хранится таблицакак:

ID int,

priority_1 varchar (2)

...

Это на самом деле идет к priroity_128 (глупый плоский файл), но яМеня интересует только 1-7, и логику для одних можно легко использовать для других.К сожалению, я не контролирую эту часть выписки.Значения, которые я получаю, выглядят так:

1>

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

3 |

4 Y

Мне кажется, что они выглядят как их символы ascii из-за преобразования, которое я извлекаю.

select convert(varbinary,'>',2)

Возвращает 0x3E.Часть 0x можно игнорировать ... 3 в двоичном виде - 0011, а E - 1110 ... 3E = 00111110. Обрежьте первый 0, и он оставляет 7-битный код, который я ищу.К сожалению, я не знаю, как выразить эту логику здесь, в T-SQL.Есть идеи?Я думаю, как функцию было бы проще всего использовать ... что-то вроде:

select id, binaryversionof(priority_1)

Ответы [ 4 ]

2 голосов
/ 25 марта 2011

Вот UDF, который преобразует из base-10 в любую другую базу, включая base-2 ...

Вот как вы можете его использовать:

SELECT YourDatabase.dbo.udf_ConvertFromBase10(convert(varbinary, '>', 2), 2)

Вот что он возвращает:

111110

А вот определение функции:

CREATE FUNCTION [dbo].[udf_ConvertFromBase10]
(
    @num INT, 
    @base TINYINT
)

RETURNS VARCHAR(255) 

AS 

BEGIN 

  -- Check for a null value.
  IF (@num IS NULL)
    RETURN NULL

  -- Declarations
  DECLARE @string VARCHAR(255)
  DECLARE @return VARCHAR(255)
  DECLARE @finished BIT
  DECLARE @div INT
  DECLARE @rem INT
  DECLARE @char CHAR(1)

  -- Initialize
  SELECT @string   = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  SELECT @return   = CASE WHEN @num <= 0 THEN '0' ELSE '' END
  SELECT @finished = CASE WHEN @num <= 0 THEN 1 ELSE 0 END
  SELECT @base     = CASE WHEN @base < 2 OR @base IS NULL THEN 2 WHEN @base > 36 THEN 36 ELSE @base END

  -- Loop
  WHILE @finished = 0
  BEGIN

    -- Do the math
    SELECT @div = @num / @base
    SELECT @rem = @num - (@div * @base)
    SELECT @char = SUBSTRING(@string, @rem + 1, 1)
    SELECT @return = @char + @return
    SELECT @num = @div

    -- Nothing left?
    IF @num = 0 SELECT @finished = 1

  END

  -- Done
  RETURN @return

END
1 голос
/ 27 марта 2011

Ваше решение возвращает строку переменной длины. Не уверен, что это было задумано, или вы просто упустили этот факт.

В любом случае, вот мое решение, которое всегда возвращает 7 0 с или 1 с:

CREATE FUNCTION fnIntTo7Bits (@Value int)
RETURNS varchar(7)
AS BEGIN
  DECLARE @Bits varchar(7);

  SELECT @Bits = COALESCE(@Bits, '') + CAST(CAST(@Value & number AS bit) AS varchar)
  FROM master..spt_values
  WHERE type = 'P' AND number IN (1, 2, 4, 8, 16, 32, 64)
  ORDER BY number DESC;

  RETURN @Bits;
END;

Таблица master..spt_values является системной таблицей, используемой внутри, но также доступной для пользователя. Похоже, он унаследован от Sybase, так что это очень старый инструмент, который, на мой взгляд, означает, что он не скоро появится.

Но, если хотите, вы можете использовать свою собственную таблицу номеров, которую вам даже не нужно реализовывать, например:

  ...
  SELECT @Bits = COALESCE(@Bits, '') + CAST(CAST(@Value & number AS bit) AS varchar)
  FROM (
    SELECT  1 UNION ALL SELECT  2 UNION ALL
    SELECT  4 UNION ALL SELECT  8 UNION ALL
    SELECT 16 UNION ALL SELECT 32 UNION ALL SELECT 64
  ) s (number)
  ORDER BY number DESC;
  ...
0 голосов
/ 25 марта 2011

Я только что взбил это, возможно, глючит ... но это работает:

DECLARE @value INT, @binary VARCHAR(10)
SELECT @value = ASCII('m'), @binary = ''
;WITH [BINARY] ([Location], [x], [BIT])
AS
(
    -- Base case
    SELECT 64, @value, @value % 2 
    UNION ALL
    -- Recursive
    SELECT [BINARY].[Location] / 2, [BINARY].[x] / 2, ([BINARY].[x] / 2) % 2   
    FROM [BINARY]
    WHERE [BINARY].[Location] >= 2
)
SELECT @binary = CAST([BIT] AS CHAR(1)) + @binary FROM [BINARY]

SELECT @binary 
0 голосов
/ 25 марта 2011

Отвечая на мой собственный вопрос ... хотя любопытно, если у кого-то есть что-то более элегантное. Я нашел эту функцию без источников в Google:

CREATE FUNCTION udf_bin_me (@IncomingNumber int)
RETURNS varchar(200)
as
BEGIN

DECLARE @BinNumber  VARCHAR(200)
SET @BinNumber = ''

WHILE @IncomingNumber <> 0
BEGIN
    SET @BinNumber = SUBSTRING('0123456789', (@IncomingNumber % 2) + 1, 1) + @BinNumber
    SET @IncomingNumber = @IncomingNumber / 2
END

RETURN @BinNumber

END

Затем используйте функцию Ascii, чтобы получить десятичное значение ascii для символа:

select dbo.udf_bin_me(ascii('>'))

Кажется, это немного бегает, но я могу с этим работать. Лучшее решение для кого-либо?

...