将文本转换为二进制代码 - TSQL

时间:2011-03-25 19:04:54

标签: sql-server tsql sql-server-2000

我使用搜索功能找到了一些线程,但纯粹的T-SQL解决方案没有。

需求 - 系统以字符串格式存储每周时间表为0和1表示一周。 1表示是,0表示不....所以1100111表示星期日是(第一个),星期一是(第二个),星期二不是(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 个答案:

答案 0 :(得分:2)

这是一个将从base-10转换为任何其他基础的UDF,包括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 :(得分:1)

您的解决方案返回一个可变长度的字符串。不确定它是否是设计或你只是忽略了这一事实。

无论如何,这是我的解决方案,它始终返回7 0 s或1 s:

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;
  ...

答案 2 :(得分:0)

回答我自己的问题......虽然好奇,如果有人有更优雅的东西。我使用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函数将char获取为ascii十进制值:

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

似乎有点乱,但我可以从中解决。更好的解决方案?

答案 3 :(得分:0)

我只是鞭打了它,它可能是马车......但是它有效:

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