SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: blonduser  
Дата: 22.06.16 08:33
Оценка:
Всем доброго времени суток!

Через OLE DB вставляю в таблицу с использование хранимой процедуры файл большого размера.

Размер файла 200 МБ, то вставка завершается успешно.
Размер файла 300 МБ и больше, то вставка завершается с ошибкой "SQLErrorInfo: 22018".

Пример кода

_variant_t        objectInfo[3];

objectInfo[0] = _variant_t((long)1000); // ID
objectInfo[1] = _variant_t(TEXT("FileName.TXT")); 

        SAFEARRAY sar;

sar.cbElements = sizeof(BYTE);
sar.cDims = 1;
sar.cLocks = 1;
sar.pvData = pByte; // указатель на массив байт.
sar.fFeatures = FADF_FIXEDSIZE;
sar.rgsabound[0].lLbound = 0;  
sar.rgsabound[0].cElements = (ULONG)ullSize; // размер

objectInfo[2].vt = VT_ARRAY|VT_UI1;
objectInfo[2].parray = &sar;


Как избавится от ошибки и записать файл объемом больше 300 МБ?

Спасибо.
Re: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: LuciferNovoros Россия  
Дата: 22.06.16 08:54
Оценка:
Здравствуйте, blonduser, Вы писали:

B>Как избавится от ошибки и записать файл объемом больше 300 МБ?


Зачем?! Зачем в БД файлы такого размера? ИМХО, хранить их на диске, а в БД писать ссылку на файл.
Re[2]: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: blonduser  
Дата: 22.06.16 09:31
Оценка:
Здравствуйте, LuciferNovoros, Вы писали:

LN>Здравствуйте, blonduser, Вы писали:


B>>Как избавится от ошибки и записать файл объемом больше 300 МБ?


LN>Зачем?! Зачем в БД файлы такого размера? ИМХО, хранить их на диске, а в БД писать ссылку на файл.


В некоторых случаях так и делаем, но это не гарантирует целостность данных.
Re: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: BlackEric http://black-eric.lj.ru
Дата: 22.06.16 11:44
Оценка:
Здравствуйте, blonduser, Вы писали:

Какой тип поля в бд?
FileStream используется?
Самый интересный кусок кода вы и не показали. Вы же используете Odbc_SQLBindParam, какого типа параметры в запросе?
https://github.com/BlackEric001
Re[2]: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: blonduser  
Дата: 22.06.16 13:34
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, blonduser, Вы писали:


BE>Какой тип поля в бд?

varbinary(max)
BE>FileStream используется?
Это поле использует FileStream.
BE>Самый интересный кусок кода вы и не показали. Вы же используете Odbc_SQLBindParam, какого типа параметры в запросе?

Для всех колонок
acDBBinding[i].obLength = 0;
acDBBinding[i].obStatus = 0;
acDBBinding[i].pTypeInfo = NULL;
acDBBinding[i].pObject = NULL;
acDBBinding[i].pBindExt = NULL;
acDBBinding[i].dwPart = DBPART_VALUE;
acDBBinding[i].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
acDBBinding[i].dwFlags = 0;
acDBBinding[i].bScale = 0;

acDBBinding[i].iOrdinal = i + 1;
acDBBinding[i].obValue = sizeof(VARIANT) * i;
acDBBinding[i].eParamIO = DBPARAMIO_INPUT;
acDBBinding[i].cbMaxLen = sizeof(VARIANT);
acDBBinding[i].wType = DBTYPE_VARIANT;
acDBBinding[i].bPrecision = 11;
Re: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: rm822 Россия  
Дата: 29.06.16 22:16
Оценка:
B>Как избавится от ошибки и записать файл объемом больше 300 МБ?
У тебя скорее всего тупо 32битный процесс и нет куска памяти непрерывного достаточного размера
Вариант 1. Попробуй editbin имя твего экзешника /LARGEADDRESSAWARE, блобы все равно больше 2х гб не бывают
Вариант 2. Писать блоб по кускам, через @myblob.Write(chunk, offset, chunk_len)

declare @x varbinary(max) =0x00
set @x.WRITE ( 0x0102030405060708090a, 0 , 10 )
set @x.WRITE ( 0x0102030405060708090a, 10 , 10 )
..............

select @x
Re[2]: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: blonduser  
Дата: 30.06.16 07:51
Оценка:
Здравствуйте, rm822, Вы писали:

B>>Как избавится от ошибки и записать файл объемом больше 300 МБ?

R>У тебя скорее всего тупо 32битный процесс и нет куска памяти непрерывного достаточного размера
R>Вариант 1. Попробуй editbin имя твего экзешника /LARGEADDRESSAWARE, блобы все равно больше 2х гб не бывают
R>Вариант 2. Писать блоб по кускам, через @myblob.Write(chunk, offset, chunk_len)

R>
R>declare @x varbinary(max) =0x00
R>set @x.WRITE ( 0x0102030405060708090a, 0 , 10 )
R>set @x.WRITE ( 0x0102030405060708090a, 10 , 10 )
R>..............

R>select @x
R>


Дело в том что блоб передается в хранимую процедуру и уже ей обрабатывается.
У себя я его в память загружаю. Ошибка приходит от SQL сервера.
А вот SQL-сервер у меня 32-х битный, но при этом если выполнить эту же процедуру из под SSMS, то все загружается.

Попробую на 64-х разрядном сервере.
Re[3]: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: rm822 Россия  
Дата: 30.06.16 08:29
Оценка: 2 (1)
B>Дело в том что блоб передается в хранимую процедуру и уже ей обрабатывается.
Это понятно

B>У себя я его в память загружаю. Ошибка приходит от SQL сервера.

Я думаю что нет и ошибку тебе говорит провайдер, при попытках этот несчастный кусок в 300мб куда-нибудь скопировать.
Re[4]: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: BlackEric http://black-eric.lj.ru
Дата: 30.06.16 08:45
Оценка:
Здравствуйте, rm822, Вы писали:

B>>У себя я его в память загружаю. Ошибка приходит от SQL сервера.

R>Я думаю что нет и ошибку тебе говорит провайдер, при попытках этот несчастный кусок в 300мб куда-нибудь скопировать.

Так это можно трассировкой посмотреть, доходят данные до сервера или нет. Ну или логирование в процедуре поставить.
Хотя правильно писать через WriteBlob кусками
https://github.com/BlackEric001
Re[2]: SQL 2008 и ошибка 22018 при вставке большого BLOB-а.
От: blonduser  
Дата: 30.06.16 18:58
Оценка: 35 (1)
Здравствуйте, rm822, Вы писали:

B>>Как избавится от ошибки и записать файл объемом больше 300 МБ?

R>У тебя скорее всего тупо 32битный процесс и нет куска памяти непрерывного достаточного размера
R>Вариант 1. Попробуй editbin имя твего экзешника /LARGEADDRESSAWARE, блобы все равно больше 2х гб не бывают
R>Вариант 2. Писать блоб по кускам, через @myblob.Write(chunk, offset, chunk_len)

R>
R>declare @x varbinary(max) =0x00
R>set @x.WRITE ( 0x0102030405060708090a, 0 , 10 )
R>set @x.WRITE ( 0x0102030405060708090a, 10 , 10 )
R>..............

R>select @x
R>


Пересобрал как 64х битное приложение.
Все работает без ошибок.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.