Arhn - архитектура программирования

Как получить большой двоичный объект MySQL в виде двоичных данных с помощью SQLGetData в С++

У меня есть база данных MySQL со столбцом mediumblob. Я хочу получить двоичные данные из поля BLOB-объектов в строковый поток С++ с помощью ODBC в Windows.

Сначала я вызываю SQLDescribeCol, и это указывает, что это тип SQL_LONGVARBINARY.

Затем я вызываю SQLGetData следующим образом:

SQLLEN indicator;
SQLCHAR SqlChar[8000];
SQLGetData(m_sqlstatementhandle, i, SQL_CHAR, &SqlChar, sizeof(SqlChar), (SQLLEN*)&indicator);

Затем я продолжаю и записываю данные в stringstream:

stringstream ss;
ss.write((char*)&SqlChar, indicator);

Это дает мне данные BLOB-объекта, но они хранятся в SqlChar в виде строки HEX.

Моя программа ожидает, что данные в строковом потоке будут храниться как двоичные. Теперь я мог бы сначала преобразовать строку HEX в двоичную, а затем записать ее в поток строк, но мне это кажется неправильным. Я бы очень хотел получить его как двоичный файл прямо из SQLGetData.

Итак, пара вопросов:

  1. Правильно ли я использую SQLGetData для типа BLOB-объектов?
  2. Является ли массив SQLCHAR подходящим контейнером для записи?
  3. Есть ли способ получить данные в виде двоичных файлов непосредственно из MySQL через ODBC?

Спасибо.

14.03.2016

  • но он хранится в SqlChar как шестнадцатеричная строка. -- Откуда вы знаете, что данные действительно являются шестнадцатеричной строкой? Возможно, ваш отладчик показывает вам данные в виде шестнадцатеричной строки, а не то, что данные на самом деле являются шестнадцатеричной строкой. Кроме того, вы должны проверять свои коды возврата при вызове функций ODBC. Какое значение возвращается после вызова SQLGetData? 14.03.2016
  • @PaulMcKenzie Спасибо за ваш комментарий. Выше приведен лишь минимальный код, чтобы прояснить вопрос. Я проверяю коды возврата в своем фактическом коде. Как оказалось, исправление было довольно простым, как только я его нашел. 14.03.2016

Ответы:


1

Предоставление SQL_BINARY в качестве аргумента неверно (даже если это работает здесь, потому что SQL_BINARY и SQL_C_BINARY, похоже, определены для одного и того же значения). Из документа SQLGetData о третьем аргументе TargetType:

[Ввод] Идентификатор типа данных C буфера *TargetValuePtr. Список допустимых типов данных C и идентификаторов типов см. в разделе «Типы данных C» в Приложении D: Типы данных.

См.: https://msdn.microsoft.com/en-us/library/ms715441%28v=vs.85%29.aspx

Идентификатор ввода должен идентифицировать C-тип используемого буфера. Все идентификаторы c-типа имеют имена вроде SQL_C_foobar.

Таким образом, вы должны либо передать SQL_C_BINARY в качестве аргумента (если вы хотите указать драйверу получить простые двоичные данные), либо SQL_C_CHAR (если вы хотите указать драйверу преобразовать данные в некоторые «символьные данные»). Обратите внимание, что оба, SQL_C_CHAR и SQL_CHAR, определены как 1.

Еще несколько объяснений вашего случая, когда драйвер преобразовал данные в «строку». Как видно из списка типов данных C, тип буфера SQLCHAR может использоваться для нескольких «идентификаторов типа C»: если вы используете SQLCHAR и передать SQL_C_CHAR как InputType, драйвер "знает", что буфер имеет тип SQLCHAR и что вы хотели бы получить данные как "символьные данные". Итак, в вашем случае MySql преобразует двоичные данные во что-то удобочитаемое, например шестнадцатеричную строку. С другой стороны, если вы передаете SQL_C_BINARY как InputType, драйвер «знает», что буфер имеет тип SQLCHAR и что вас интересуют чисто двоичные значения, поэтому драйверу не нужно преобразовывать двоичные данные в человеческий формат. -readable строка, и она просто заполнит буфер простыми двоичными данными.

См. здесь список c-типов и соответствующих им типов буферов: https://msdn.microsoft.com/en-us/library/ms714556%28v=vs.85%29.aspx

В качестве общего примечания: следите за тем, говорится ли в документации о «типе Sql C» или «типе Sql». Первый используется для определения C-типа буфера, другой — для определения логического типа базы данных столбца.

15.03.2016
  • Хорошее объяснение того, почему он давал мне шестнадцатеричные данные. 15.03.2016

  • 2

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

    Я заметил в этом вопросе, что плакат использует SQL_C_BINARY, < s>то же самое, что и SQL_BINARY. Поэтому, когда я вызываю SQLGetData следующим образом, я получаю то, что ожидаю.

    SQLGetData(m_sqlstatementhandle, i, SQL_C_BINARY, &SqlChar, sizeof(SqlChar), (SQLLEN*)&indicator);
    

    Таким образом, все сводилось к предоставлению неправильного типа цели.

    Изменить: отредактировано, чтобы отразить правильную информацию из сообщения @erg.

    14.03.2016
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..