Как вставить строки байтов в SAP HANA

Я пытаюсь вставить две строки байтов в таблицу SAP HANA со столбцами VARBINARY, но постоянно получаю синтаксическую ошибку.

Мои две строки байтов, которые выглядят так:

STRING1 = b'G\xa2ac\xa0av\xf6'  
type(STRING1) == <class 'bytes'>
STRING2 = b'708ca7fbb701799bb387f2e50deaca402e8502abe229f705693d2d4f350e1ad6' 
type(STRING2) == <class 'bytes'>

Мой запрос на вставку значений выглядит так:

INSERT INTO testTable VALUES(
CAST(b'708ca7fbb701799bb387f2e50deaca402e8502abe229f705693d2d4f350e1ad6' AS VARBINARY),
CAST(b'G\xa2ac\xa0av\xf6' AS VARBINARY));

Я также попытался сделать запрос, как документация предлагает:

INSERT INTO testTable VALUES(
CAST(x'708ca7fbb701799bb387f2e50deaca402e8502abe229f705693d2d4f350e1ad6' AS VARBINARY),
CAST(x'G\xa2ac\xa0av\xf6' AS VARBINARY));

Также как и:

INSERT INTO testTable VALUES(
b'708ca7fbb701799bb387f2e50deaca402e8502abe229f705693d2d4f350e1ad6',
b'G\xa2ac\xa0av\xf6');

Но все это дает мне некоторую синтаксическую ошибку. Любая помощь будет принята с благодарностью. Спасибо!


person AOyung    schedule 26.07.2017    source источник
comment
В чем собственно ошибка?   -  person Dai    schedule 27.07.2017
comment
@Dai Ошибка выглядит так: SAP DBTech JDBC: [257]: синтаксическая ошибка sql: неверный синтаксис рядом с G\xa2ac\xa0av\xf6: строка 1, столбец 98 (на позиции 98)   -  person AOyung    schedule 27.07.2017
comment
Я не ожидаю SAP HANA, но я думаю, вам нужно избегать обратной косой черты в строке имени файла.   -  person Dai    schedule 27.07.2017


Ответы (2)


Проблема здесь заключается в вашем значении STRING1 ( b'G\xa2ac\xa0av\xf6' ). Это недопустимая шестнадцатеричная строка, которая может представлять двоичное значение в SAP HANA. Вот почему любое приведение типов здесь не работает. Вместо этого кажется, что на самом деле это строка, а некоторые символы представлены шестнадцатеричными значениями (может быть, кодовые точки UNICODE?).
По крайней мере, так я понимаю последовательность \x escpace в строке.

Итак, теперь вы можете делать разные вещи.

  1. вы можете сохранить строку как есть с управляющими последовательностями в столбце VARBINARY. Для этого вы можете использовать to_binary('G\xa2ac\xa0av\xf6') в операторе вставки.
  2. вы можете преобразовать эту строку в допустимую строку UNICODE в коде вашего приложения и вместо этого сохранить данные в столбце NVARCHAR.
person Lars Br.    schedule 27.07.2017
comment
Эй, спасибо! Это помогло. Если бы я мог спросить продолжение... Когда я сейчас пытаюсь запросить свои данные с помощью PyHDB и этого оператора select: SELECT col2 FROM testTable WHERE col1=x'708ca7fbb701799bb387f2e50deaca402e8502abe229f705693d2d4f350e1ad6'; Данные, которые я получаю, выводятся в такой форме: b'\\xa2ac\\xa0av\\xf6'. Обратите внимание, что символы обратной косой черты экранированы. Тип данных - байты, и я хотел бы сохранить этот тип данных, но можно ли удалить двойную обратную косую черту и просто сохранить ее как 1 обратную косую черту? Спасибо! - person AOyung; 27.07.2017

Насколько мне известно, HANA не понимает байтовое кодирование, такое как python, поэтому я думаю, что есть путаница, если вы используете это представление в консоли sql. Таким образом, в python при печати b'G\xa2ac\xa0av\xf6' байт, который не может быть представлен в ascii (ваша локальная кодировка?), имеет префикс \x.

Если вы хотите это сделать, вы можете сначала преобразовать это в шестнадцатеричное представление в python.

>>> import binascii
>>> binascii.hexlify(b'\xa2ac\xa0av\xf6')
b'47a26163a06176f6'

Это даст вам единообразное представление вашего массива байтов в шестнадцатеричном виде, которое вы теперь можете использовать в своей консоли SQL (например, в HANA Studio и т.п.):

INSERT INTO TestTable VALUES(x'47a26163a06176f6');
-- OR
INSERT INTO TestTable VALUES(HEXTOBIN('47a26163a06176f6'));

Обратите внимание, что префикс b изменяется на x в первом случае, чтобы указать HANA, что он должен рассматривать это как двоичные данные в шестнадцатеричном представлении.

Чтобы вставить значение из Python 2 в качестве подготовленного оператора:

>>> cursor.execute("INSERT INTO TestTable Values(?)", \
        parameters=[binascii.hexlify(b'G\xa2ac\xa0av\xf6')])

PyHDB, кажется, ожидает, что строка справится правильно, но в Python 3 hexlify даст массив байтов, поэтому вам нужно снова превратить результат в строку

>>> param = str(binascii.hexlify(b'G\xa2ac\xa0av\xf6'), 'ascii')
>>> cursor.execute("INSERT INTO TestTable Values(?)", parameters=[param])

Я думаю, это можно считать ошибкой в ​​​​PyHDB или, по крайней мере, несоответствием. Просто для полноты картины в клиенте SAP dbapi есть класс Binary для переноса байтовых массивов для этой цели.

Теперь запросите это с вашим клиентом

>>> import pyhdb
>>> con = pyhdb.connect(....)
>>> cursor = con.cursor()
>>> cursor.execute('SELECT * FROM TestTable')
>>> cursor.fetchall()
[(b'G\xa2ac\xa0av\xf6',)]

Подводя итог: b'G\xa2ac\xa0av\xf6' не является представлением, которое HANA понимает как таковое при использовании его в операторе SQL. Нам нужно найти общий язык, для этого мы преобразовали массив байтов в шестнадцатеричное представление (hexlify) и сказали HANA обрабатывать его как таковое (x-prefix/HEXTOBIN).

Как Ларс Бр. упомянуто, если это действительно литералы Unicode, вы можете рассмотреть NVARCHAR как тип данных.

person Goldfishslayer    schedule 03.08.2017