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

发布于 2024-10-26 20:40:28 字数 809 浏览 2 评论 0原文

我使用搜索功能找到了一些关于此问题的线程,但没有找到纯粹的 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)

I found a few threads on this using the search feature, but nothing for a purely T-SQL solution.

the need - A system is storing a weekly schedule as 0's and 1's in a string format to represent a week. 1 means yes, 0 means no....so 1100111 means sunday yes (first one), Monday yes (second 1), Tuesday no (the 0)...etc.

Short question - How do I go from an ascii char such as '>' to it's hex code '3E' and ultimately to it's binary '00111110' representation?

Long question - I'm extracting from a flat file system that stores a table as:

ID int,

priority_1 varchar(2)

...

It actually goes to priroity_128 (silly flat file), but I'm only interested in 1-7 and the logic for one should be easily reused for the others. I unfortunately have no control over this part of the extract. The values I get look like:

1 >

2 (edit, I actually put a symbol here that I receive from the system but the forum doesn't like.)

3 |

4 Y

I get the feeling these are appearing as their ascii chars because of the conversion as I extract.

select convert(varbinary,'>',2)

This returns 0x3E. The 0x part can be ignored... 3 in binary is 0011 and E is 1110...3E = 00111110. Trim the first 0 and it leaves the 7 bit code that I'm looking for. Unfortunately I have no idea how to express this logic here in T-SQL. Any ideas? I'm thinking as a function would be easiest to use...something like:

select id, binaryversionof(priority_1)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

半寸时光 2024-11-02 20:40:28

这是一个 UDF,它将从 10 进制转换为任何其他进制,包括 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

Here's a UDF that will convert from base-10 to any other base, including base-2...

Here's how you can use it:

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

Here's what it returns:

111110

And here's the function definition:

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
手长情犹 2024-11-02 20:40:28

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

无论如何,这是我的解决方案,它总是返回 7 01

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

Your solution returns a string of a variable length. Not sure whether it was by design or you simply overlooked that fact.

Anyway, here's my solution, which always returns 7 0s or 1s:

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;

The master..spt_values table is a system table used internally but also accessible to the user. It seems to have been inherited from Sybase so it's a very old tool, which, to my mind, means it won't go too soon.

But if you like, you can use your own number table, which you don't even have to materialise, like this:

  ...
  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;
  ...
以酷 2024-11-02 20:40:28

回答我自己的问题......虽然好奇是否有人有更优雅的东西。我使用谷歌找到了这个无源函数:

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('>'))

似乎有点绕,但我可以从中工作。有人有更好的解决方案吗?

Answering my own question...though curious if anyone has something more elegant. I found this unsourced function using 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

Then use the Ascii function to get the char to it's ascii decimal value:

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

Seems to be a bit of a run around, but I can work from that. Better solution anyone?

得不到的就毁灭 2024-11-02 20:40:28

我刚刚搞定了这个,可能有问题......但它有效:

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 

I just whipped this up, it maybe buggy... but it works:

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 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文