2015-09-18 2 views
5

У меня есть растровое изображение, которое хранится как VARCHAR в Netteza. Необходимо преобразовать этот VARCHAR в двоичную строку в Netezza.Netezza SQL конвертировать VARCHAR в двоичную строку

ввода (Netezza цв значение - VARCHAR) = '0xFFFFFFFFFFFFFFFF'

Желаемая выход (VARCHAR) ->

'1111111111111111111111111111111111111111111111111111111111111111' 

Есть ли способ сделать это с помощью запроса Netezza?

Я попытался

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

но выдает ошибку

ERROR [HY000]ERROR: Cannot cast type 'VARCHAR' to 'VARBINARY'

+0

Кажется, что вы хотите преобразовать varchar, который содержит шестнадцатеричное представление в A) двоичное представление этого шестнадцатеричного значения или B) представление varchar двоичного представления с использованием символов ASCII '0' и '1 ». Можете ли вы уточнить, хотите ли вы A или B? – ScottMcG

+0

B - это то, что я ищу. \t Просто чтобы развернуть это - в конечном итоге, мне нужно сделать следующее: 1- найти позицию первого 1 в двоичной строке (0 в случае «0xFFFFFFFFFFFFFFFF»). 2- найти счетчик 1 в двоичной строке (64 в случае «0xFFFFFFFFFFFFFFFF») - с этой точки зрения B, вероятно, достаточно – user3206440

+1

Похоже, потребуется явное преобразование, но [это не поддерживается Netezza] (http : //www-01.ibm.com/support/knowledgecenter/SSULQD_7.1.0/com.ibm.nz.dbu.doc/r_dbuser_supported_im_ex_casts.html). Так выглядит (мне), как конвертация, возможно, придется делать вручную ... –

ответ

6

Вы можете преобразовать шестнадцатеричную строку в двоичные данные и сохранить ее в столбце VARCHAR или VARBINARY. Я предпочитаю VARCHAR из-за довольно ограниченных CAST, доступных для VARBINARY.

Чтобы преобразовать шестнадцатеричную строку в двоичную и сохранить ее в VARCHAR, используйте функцию hextoraw, предоставляемую с помощью набора расширений SQL. Это включено в Netezza, но должно быть настроено и доступно вашим администратором.

Чтобы преобразовать шестнадцатеричную строку в двоичную и сохранить ее в VARBINARY, используйте функцию hex_to_binary, включенную в Netezza (добавлено в 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, которые, я считаю, подойдут вашей цели.

FirstBit возвращает позицию первого ненулевого бита. BitCount возвращает общее количество ненулевых битов. CharToBase2 преобразует двоичные значения в VARCHAR из 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++-кодер и, скорее всего, буду уволен, если бы это была моя работа, поэтому предостерегайте emptor.

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.каст

#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_* 
+0

отлично - попробуем это! – user3206440

+0

за исключением преобразования шестнадцатеричной строки в двоичную строку, nzsql должен работать. Для преобразования шестнадцатеричной строки в двоичную строку, следуя вашему примеру, я написал UDF, надеясь, что это поможет сжать 'chartobase2 (hextoraw ('FFFF'))' to 'hextobin ('FFFF')' - собственный код CPP работает, однако переведенный Netezza UDF не проверен - теперь у вас нет доступа к одному. – user3206440

2

Я думаю, вам нужно определить в C в UDF, зарегистрировать его в базу данных, а затем вызвать его на ваш колонка.

Я начал бы с рассмотрения либо this answer, либо this one. В обоих случаях вам, вероятно, придется разбить ведущий 0x.

2

следующие рекомендации от @ScottMcG - построение UDF для преобразования шестнадцатеричной строки в двоичную строку.

вход -> 'F0F' требуемый выход -> '11110000111'

---------- 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) 
+1

Я быстро проверил это и должен был сделать два изменения, чтобы заставить его работать как UDX. Я удалил «result-> data =" ";" и изменил назначение результата на такую ​​форму: 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()); Я могу изменить ваш ответ, чтобы включить это в более разборчивую форму, если хотите. – ScottMcG

+0

@ScottMcG - это было бы здорово! – user3206440

+0

Только что отправил изменения. Надеюсь, что это работает для вас! – ScottMcG

Смежные вопросы