Netezza SQL 将 VARCHAR 转换为二进制字符串
Netezza SQL convert VARCHAR to binary string
我在 Netteza 中将位图存储为 VARCHAR
。需要将 VARCHAR
转换为 Netezza 中的二进制字符串。
输入(Netezza 列值 - VARCHAR
)='0xFFFFFFFFFFFFFFFF'
期望的输出 (VARCHAR
)->
'1111111111111111111111111111111111111111111111111111111111111111'
有没有办法使用 Netezza 查询来做到这一点?
我试过了
SELECT CAST('0xFFFFFFFFFFFFFFFF' AS VARBINARY(64) );
但这会引发错误
ERROR [HY000]ERROR: Cannot cast type 'VARCHAR' to 'VARBINARY'
我认为您需要在 C 中定义一个 UDF,将其注册到数据库,然后在您的专栏中调用它。
我先看看 this answer or this one。在这两种情况下,您可能都必须去除领先的 0x
.
您可以将十六进制字符串转换为二进制数据并将其存储在 VARCHAR 或 VARBINARY 列中。我倾向于更喜欢 VARCHAR,因为可用于 VARBINARY 的 CAST 相当有限。
要将十六进制字符串转换为二进制并将其存储在 VARCHAR 中,请使用 SQL 扩展工具包提供的 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 放在一起,我相信它们会适合您的目的。
FirstBit returns 第一个非零位的位置。
BitCount returns 非零位的总数。
CharToBase2 将二进制值转换为 1 和 0 的 VARCHAR。
我认为前两个可以在没有第三个的情况下得到你需要的最终结果,但如果你仍然想要那个,就在这里。
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=
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=
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=
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_*
遵循@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=
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)
我在 Netteza 中将位图存储为 VARCHAR
。需要将 VARCHAR
转换为 Netezza 中的二进制字符串。
输入(Netezza 列值 - VARCHAR
)='0xFFFFFFFFFFFFFFFF'
期望的输出 (VARCHAR
)->
'1111111111111111111111111111111111111111111111111111111111111111'
有没有办法使用 Netezza 查询来做到这一点?
我试过了
SELECT CAST('0xFFFFFFFFFFFFFFFF' AS VARBINARY(64) );
但这会引发错误
ERROR [HY000]ERROR: Cannot cast type 'VARCHAR' to 'VARBINARY'
我认为您需要在 C 中定义一个 UDF,将其注册到数据库,然后在您的专栏中调用它。
我先看看 this answer or this one。在这两种情况下,您可能都必须去除领先的 0x
.
您可以将十六进制字符串转换为二进制数据并将其存储在 VARCHAR 或 VARBINARY 列中。我倾向于更喜欢 VARCHAR,因为可用于 VARBINARY 的 CAST 相当有限。
要将十六进制字符串转换为二进制并将其存储在 VARCHAR 中,请使用 SQL 扩展工具包提供的 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 放在一起,我相信它们会适合您的目的。
FirstBit returns 第一个非零位的位置。 BitCount returns 非零位的总数。 CharToBase2 将二进制值转换为 1 和 0 的 VARCHAR。
我认为前两个可以在没有第三个的情况下得到你需要的最终结果,但如果你仍然想要那个,就在这里。
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=
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=
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=
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_*
遵循@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=
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)