Netezza SQL将VARCHAR转换为二进制字符串

时间:2015-09-18 16:03:34

标签: sql netezza

我在Netteza中将位图存储为VARCHAR。需要将VARCHAR转换为Netezza中的二进制字符串。

输入(Netezza col值 - VARCHAR)= '0xFFFFFFFFFFFFFFFF'

期望的输出(VARCHAR) - >

'1111111111111111111111111111111111111111111111111111111111111111'

有没有办法使用Netezza查询?

我试过

SELECT CAST('0xFFFFFFFFFFFFFFFF' AS VARBINARY(64) ); 

但是会抛出错误

  

错误[HY000]错误:无法将“VARCHAR”类型转换为“VARBINARY”

3 个答案:

答案 0 :(得分:6)

您可以将十六进制字符串转换为二进制数据,并将其存储在VARCHAR或VARBINARY列中。我倾向于喜欢VARCHAR,因为可用于VARBINARY的CAST相当有限。

要将十六进制字符串转换为二进制并将其存储在VARCHAR中,请使用随SQL Extension Toolkit提供的hextoraw函数。这包含在Netezza中,但必须由管理员配置并提供。

要将十六进制字符串转换为二进制并将其存储在VARBINARY中,请使用Netezza附带的hex_to_binary函数(在v 7.2中添加)。

drop table test_table if exists;
DROP TABLE
create table test_table (col1 varchar(50), col2 varbinary(50));
CREATE TABLE

insert into test_table values (hextoraw('464F4F'), hex_to_binary('464F4F'));
INSERT 0 1

select * from test_table;
 COL1 |   COL2
------+-----------
 FOO  | X'464F4F'
(1 row)

从那里你需要一个UDF来处理你想要做的位计算。我已经把三个简单的UDF放在一起,我认为这些UDF适合你的目的。

FirstBit返回第一个非零位的位置。 BitCount返回非零位的总计数。 CharToBase2转换VARSAR为1s和0s的二进制值。

我认为前两个会得到你需要的最终结果而不是第三个,但如果你仍然想要它,它就在这里。

select firstbit(hextoraw('0000')), bitcount(hextoraw('0000')), chartobase2(hextoraw('0000'));
FIRSTBIT | BITCOUNT |   CHARTOBASE2
----------+----------+------------------
       -1 |        0 | 0000000000000000
(1 row)

select firstbit(hextoraw('0001')), bitcount(hextoraw('0001')), chartobase2(hextoraw('0001'));
 FIRSTBIT | BITCOUNT |   CHARTOBASE2
----------+----------+------------------
       15 |        1 | 0000000000000001
(1 row)

select firstbit(hextoraw('FFFF')), bitcount(hextoraw('FFFF')), chartobase2(hextoraw('FFFF'));
 FIRSTBIT | BITCOUNT |   CHARTOBASE2
----------+----------+------------------
        0 |       16 | 1111111111111111
(1 row)

以下是各自的来源。请注意,我是一个可怕的C ++编码器,如果这是我的工作,很可能会被解雇,所以请注意这一点。

<强> BitCount.cpp

#include "udxinc.h"
#include <string.h>

using namespace nz::udx;

class BitCount : public Udf
{
    public:
        static Udf* instantiate();

    ReturnValue evaluate()
    {
        StringArg* str = stringArg(0);
        int32 retval = 0;


        for(int i=0; i< str->length; i++)
                {

                for (int y=7; y>=0 ; y--)
                        {

                        if ((str->data[i] & (unsigned char)pow(2,y)) > 0)
                                {
                                        retval++;

                                }

                        }
                }

        NZ_UDX_RETURN_INT32(retval);
    }

};

Udf* BitCount::instantiate()
{
    return new BitCount;
}

<强> FirstBit.cpp

#include "udxinc.h"
#include <string.h>

using namespace nz::udx;

class FirstBit : public Udf
{
    public:
        static Udf* instantiate();

    ReturnValue evaluate()
    {
        StringArg* str = stringArg(0);
        int32 retval = -1;


        for(int i=0; i< str->length; i++) {

                for (int y=7; y>=0 ; y--) {

                        if ((str->data[i] & (unsigned char)pow(2,y)) > 0)
                                {
                                        retval = i*8 + 7 - y;

                                }

                        if (retval > -1) break;
                }
                if (retval > -1)         break;
                }

        NZ_UDX_RETURN_INT32(retval);
    }

};

Udf* FirstBit::instantiate()
{
    return new FirstBit;
}

<强> CharToBase2.cpp

#include "udxinc.h"
#include <string.h>

using namespace nz::udx;

class CharToBase2 : public Udf
{
    public:
        static Udf* instantiate();

    ReturnValue evaluate()
    {
        StringArg* str = stringArg(0);
        StringReturn* result = stringReturnInfo();
        result->size = str->length*8;
        //unsigned char stringbyte = 0 ;


        for(int i=0; i< str->length; i++)
                {


                  for (int y=7; y>=0 ; y-- )
                        {

                         if ((str->data[i] & (unsigned char)pow(2,y)) == 0) {
                                        result->data[i*8 + 7 - y] = '0'; }
                                else {
                                        result->data[i*8 + 7 - y] = '1';        }
                        }

                }

        NZ_UDX_RETURN_STRING(result);
    }

    uint64 calculateSize() const
    {
        return sizerStringSizeValue(sizerStringArgSize(0)*8);
    }
};

Udf* CharToBase2::instantiate()
{
    return new CharToBase2;
}

最后,这是我用来编译和安装每个脚本的脚本。

install_firstbit.sh DBNAME

DB=$1
if [[ -z $DB ]]; then
 DB=$NZ_DATABASE
fi

if [[ -z $DB ]]; then
 print "Usage: install <database>"
 return 1
fi

export NZ_DATABASE="${DB}"

nzudxcompile FirstBit.cpp \
 --fenced \
 --sig   "FirstBit(varchar(any))" \
 --return  "integer" \
 --class  "FirstBit"

rm FirstBit.o_*

install_bitcount.sh DBNAME

DB=$1
if [[ -z $DB ]]; then
 DB=$NZ_DATABASE
fi

if [[ -z $DB ]]; then
 print "Usage: install <database>"
 return 1
fi

export NZ_DATABASE="${DB}"

nzudxcompile BitCount.cpp \
 --fenced \
 --sig   "BitCount(varchar(any))" \
 --return  "integer" \
 --class  "BitCount"

rm BitCount.o_*

install_chartobase2.sh DBNAME

DB=$1
if [[ -z $DB ]]; then
 DB=$NZ_DATABASE
fi

if [[ -z $DB ]]; then
 print "Usage: install <database>"
 return 1
fi

export NZ_DATABASE="${DB}"

nzudxcompile CharToBase2.cpp \
 --fenced \
 --sig   "CharToBase2(varchar(any))" \
 --return  "varchar(any)" \
 --class  "CharToBase2"

rm CharToBase2.o_*

答案 1 :(得分:2)

我认为您需要在C中定义UDF,将其注册到数据库,然后在您的列上调用它。

我首先要查看this answerthis one。在这两种情况下,您可能必须删除前导0x

答案 2 :(得分:2)

根据@ScottMcG的建议 - 构建UDF以将十六进制字符串转换为二进制字符串。

输入 - &gt; &#39; F0F&#39; 期望的输出 - &gt; &#39; 11110000111&#39;

----------的 HexToBin.cpp ------

#include "udxinc.h"
#include <string.h>

using namespace nz::udx;

class HexToBin : public Udf
{
    public:
        static Udf* instantiate();

    ReturnValue evaluate()
    {
        StringArg* str = stringArg(0);
        StringReturn* result = stringReturnInfo();
        result->size = str->length*4; // binary representation
        string quads[16] = {"0000", "0001", "0010", "0011", "0100", "0101",
                     "0110", "0111", "1000", "1001", "1010", "1011",
                     "1100", "1101", "1110", "1111"};


        // iterate through the string characters 
        for(int i = 0, len = str->length; i < len; i++)
        {
            char c = str->data[i];
            // concatenate quad to result->data based on character c
            if (c >= '0' && c <= '9') strcat(result->data,  quads[c - '0'].c_str());
            if (c >= 'A' && c <= 'F') strcat(result->data,  quads[10 + c - 'A'].c_str());
            if (c >= 'a' && c <= 'f') strcat(result->data,  quads[10 + c - 'a'].c_str());

        }        

        NZ_UDX_RETURN_STRING(result);
    }

    uint64 calculateSize() const
    {
        return sizerStringSizeValue(sizerStringArgSize(0)*4);
    }
};

Udf* HexToBin::instantiate()
{
    return new HexToBin;
}

-------- install_hextobin.sh DBNAME -------

DB=$1
if [[ -z $DB ]]; then
 DB=$NZ_DATABASE
fi

if [[ -z $DB ]]; then
 print "Usage: install <database>"
 return 1
fi

export NZ_DATABASE="${DB}"

nzudxcompile HexToBin.cpp \
 --fenced \
 --sig   "HexToBin(varchar(any))" \
 --return  "varchar(any)" \
 --class  "HexToBin"

rm HexToBin.o_*

示例结果

select hextobin('F0F');
   HEXTOBIN
--------------
 111100001111
(1 row)

select hextobin('00F');
   HEXTOBIN
--------------
 000000001111
(1 row)

select hextobin('F00');
   HEXTOBIN
--------------
 111100000000
(1 row)