Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
ВнизADO + Ora = пропихнуть в хранимку blob более 32 кбайт Найти похожие ветки
← →
Es (2012-08-16 16:02) [0]Имеется хранимка на сервере Oracle, один из входящих параметров blob:
...
i_FILE_BODY in blob,
...
Имеем TAdoConnection и TADOStoredProc, натравленный на хранимку.
Тип параметра указан как ftBlob. Грузится как[AddParam].LoadFromStream(..., ftBlob)
При execute получаем ошибку:ORA-01460: затребовано нереализованное или неразумное преобразование
http://www.onlinedisk.ru/get_image.php?id=928134
Что за фигня с ADO? Что он такого делает, что потом ругается ОРАКЛ со СВОЕЙ стороны?
Эксперименты показали, что если сформировать большой блоб на стороне сервера (мегабайт на 15) и запихнуть его в хранимку - то все здорово и беспроблемно. Но если с дельфового клиенту через ADO указанным выше способом - то облом.
Провайдер используется родной: OraOLEDB.Oracle.1 (так как в MS"ном вообще blob не поддерживается).
Клиент Win 7, ора 11g на nix.
Кто-нибудь сталкивался еще с таким бредом?
← →
AV © (2012-08-16 16:16) [1]ага,
переделал через query
oqTmp.sql.text := "Update SUBSCRIBER set PIC=EMPTY_BLOB() Where ID_SUBSCRIBER = :ID_SUBSCRIBER RETURNING PIC INTO :PIC";
oqTmp.ParamByName("PIC").ParamType := ptInput;
oqTmp.ParamByName("PIC").DataType := ftOraBlob;
oqTmp.ParamByName("PIC").AsBLOBLocator.LoadFromFile(dlgOpenPic.FileName);
oqTmp.ParamByName("ID_SUBSCRIBER").asinteger := FSubscriber;
oqTmp.ExecSQL;
← →
QAZ (2012-08-16 16:41) [2]а зачем человеки вообще пихают в базы всякие блобы с картинками ?
почему их не хранить файлами а в базе хранить адрес?
← →
DVM © (2012-08-16 16:43) [3]
> QAZ (16.08.12 16:41) [2]
> а зачем человеки вообще пихают в базы всякие блобы с картинками
> ?
> почему их не хранить файлами а в базе хранить адрес?
удобно потому что
← →
AV © (2012-08-16 16:43) [4]
> QAZ (16.08.12 16:41) [2]
Все в одном, ничего не потеряется
или потеряется все :)
← →
имя (2012-08-16 16:46) [5]Удалено модератором
← →
QAZ (2012-08-16 16:47) [6]а резервировать и тд?
← →
DVM © (2012-08-16 16:47) [7]
> AV © (16.08.12 16:43) [4]
Да кроме этого причин хранить бинарные данные в базе масса, а вот причин не хранить и хранить в файлах я не знаю ни одной.
← →
DVM © (2012-08-16 16:50) [8]Удалено модератором
← →
QAZ (2012-08-16 16:51) [9]
> DVM © (16.08.12 16:47) [7]
ну наверно в базе нужно хранить то что можно искать,сортировать, это ведь основная идея существования баз данных?
а картинку то зачем мучить?
← →
Es (2012-08-16 16:55) [10]Так никто в проблема не разбирался? Что за нафиг делает ADO с блобом при передачи, что у Оры крышу рвет?
← →
DVM © (2012-08-16 16:55) [11]
> QAZ
Из прочих плюсов
1. Разграничение прав на уровне базы.
2. Гораздо легче открыть 1 порт для подключения к базе через интернет, чем городить доступ к файловому серверу и еще как то связывать пути на нем с записями в базе.
3. При хранении файлов отдельно от базы надо заботиться о том, чтобы ссылки всегда были верными и что делать при удалении файла?
Вообще на ibase.ru была статья для опасающихся хранить файлы в базе от создателей Firebird.
← →
QAZ (2012-08-16 16:56) [12]Удалено модератором
← →
AV © (2012-08-16 16:57) [13]
> Что за нафиг делает ADO с блобом при передачи, что у Оры
> крышу рвет?
Есть подозрение, что как -то не так размер передается
Но не разбирался до конца, тупо стал грузить запросом
← →
Sergey Masloff (2012-08-16 16:59) [14]QAZ (16.08.12 16:51) [9]
>ну наверно в базе нужно хранить то что можно искать,сортировать, это >ведь основная идея существования баз данных?
>а картинку то зачем мучить?
Не надо свое видение обобщать. Я лично из своего опыта согласен с DVM (с) и не вижу ни одной причины хнанить связанные данные в разных местах.
DVM © (16.08.12 16:50) [8]
>База же ограничена лишь размером максимального файла в фс.
И даже этим не ограничена.
← →
Sergey Masloff (2012-08-16 17:02) [15]QAZ (16.08.12 16:56) [12]
>нену как сорганизуеш,сдается мне что отображение картинки не самое >важное,и можно потерпеть загрузку при запросе
>даи всякие фрагментации баз за щет ненужной инфы тоже не убыстрят >процесс
Извини но ЯХДР от этого потока сознания ;-)
- что такое "потерять загрузку при запросе"
- про фрагментацию баз вообще достаточно смешно.
← →
DVM © (2012-08-16 17:03) [16]
> QAZ (16.08.12 16:56) [12]
> даи всякие фрагментации баз за щет ненужной инфы тоже не
> убыстрят процесс
Информация в файле базы записывается постранично, при удалении страницы помечаются как свободные, файл базы на диске как правило не уменьшается никогда сам пос себе, может только расти. Т.е фактически запись в базу - это просто запись в файл на диск в свободные страницы. Это по скорости примерно тоже самое что прямо писать в файл. Чуть-чуть медленнее, но самым медленным звеном тут всегда будет диск и сеть, а не сервер баз данных и какие то дополнительные обработки.
← →
QAZ (2012-08-16 17:07) [17]Удалено модератором
← →
DVM © (2012-08-16 17:12) [18]
> QAZ (16.08.12 17:07) [17]
> нуи нахрена нужен файл где половина размера есть неиспользуемое
> место после удалений записей ?
Плата за удобство.
Есть правда один вариант, который я допускаю, но особенно хорошим его все же не считаю. Во многих СУБД можно сделать так (в Firebird например за счет написания своих расширений - udf), чтобы при загрузке файла на сервер баз данных он сохранялся не в базе а рядом с ней в файловой системе. И читался из файловой системы при попытке чтения из базы. Т.е к файлам в файловой системе доступ будет иметь только сервер субд, но прямого доступа извне к ним нет. Но у этого способа есть куча недостатков и они перевешивают единственное "достоинство" - файлы не лежат в базе.
← →
QAZ (2012-08-16 17:14) [19]
> Но у этого способа есть куча недостатков
какие
← →
DVM © (2012-08-16 17:15) [20]
> QAZ (16.08.12 17:07) [17]
> нуи нахрена нужен файл где половина размера есть неиспользуемое
> место после удалений записей ?
Это решаемо кстати на NTFS. Там есть понятие разреженные файлы - файлы которые имеют размер больше чем реально на диске занимают.
← →
AV © (2012-08-16 17:17) [21]имхо, все равно, наверное почти все субд, "форматируют" отведенное им место под себя и пишут данные блоками. Предпочтительно, кратными ФС.
Так что не особо "дырки" будут мешать
← →
QAZ (2012-08-16 17:17) [22]
> DVM © (16.08.12 17:15) [20]
врятли, ведь запись при удалении не зануляется
← →
DVM © (2012-08-16 17:20) [23]
> QAZ (16.08.12 17:17) [22]
> врятли, ведь запись при удалении не зануляется
Ее не надо занулять, достаточно сказать системе, что место от сих до сих (смещение в файле) не используется. Драйвер сам разберется что кому и куда. Я не знаю, использует ли эту возможность хоть одна из существующих субд.
← →
QAZ (2012-08-16 17:24) [24]Удалено модератором
← →
QAZ (2012-08-16 17:26) [25]чувствую что надо изобрести свою СУБД для ленивых батонокидателей дабы спасти,а потом поработить мир
← →
DVM © (2012-08-16 17:26) [26]
> QAZ (16.08.12 17:24) [24]
> далан, и какой функцией?
DeviceIoControl
← →
DVM © (2012-08-16 17:27) [27]
> QAZ
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Модуль : uNTFSFileStream.pas
// * Назначение : Класс файлового потока, реализующий доп. возможности NTFS
// * Copyright : 2012 © Дмитрий Муратов (dvmuratov@yandex.ru)
// * Версия : 1.0
// * Дата : 06.02.2012
// ****************************************************************************
//
////////////////////////////////////////////////////////////////////////////////
unit uNTFSFileStream;
interface
{$I DEFINES.INC}
{$IFNDEF MSWINDOWS}
These streams are only usable in Windows!!!
{$ENDIF}
{$WARN SYMBOL_PLATFORM OFF}
uses
{$IFDEF DELPHIXE2_UP}
Winapi.Windows, System.SysUtils, System.Classes;
{$ELSE}
Windows, SysUtils, Classes;
{$ENDIF}
type
TNTFSFileStreamOption = (fsoCompressed, fsoSparse, fsoTemporary, fsoEncrypted,
fsoWriteThrough, fsoNoBuffering, fsoRandomAccess, fsoSequentialScan,
fsoDeleteOnClose);
TNTFSFileStreamOptions = set of TNTFSFileStreamOption;
TNTFSFileStream = class(THandleStream)
strict private
FFileName: string;
FMode: Word;
FOptions: TNTFSFileStreamOptions;
procedure SetCompression(const AHandle: THandle; const AEnabled: Boolean);
procedure SetSparse(const AHandle: THandle);
function CreateFile(const AFilename: string; const AMode: Word;
const AOptions: TNTFSFileStreamOptions = []): THandle;
function GetCompressed: Boolean;
procedure SetCompressed(const AValue: Boolean);
public
constructor Create(const AFilename: string; const AMode: Word = fmCreate;
const AOptions: TNTFSFileStreamOptions = []);
destructor Destroy; override;
procedure ZeroData(const AFileOffset: Int64 = 0; const ALength: Int64 = 0);
procedure ZeroDataForTwoOffsets(const AFirstOffset, ALastOffset: Int64);
procedure ZeroToCurrPosition;
property Compressed: Boolean read GetCompressed write SetCompressed;
procedure Recompress;
procedure Decompress;
procedure Compress;
property FileName: string read FFileName;
property Mode: Word read FMode;
property Options: TNTFSFileStreamOptions read FOptions;
end;
← →
DVM © (2012-08-16 17:28) [28]
implementation
resourcestring
rsCanNotEncryptFiles = "Can not encrypt files on a non-NT platform";
rsFileIsNotSparse = "File "%s" is not sparse";
type
TEncryptFile = function(lpFilename: PChar): BOOL; stdcall;
type
TFileZeroDataInformation = record
FileOffset: Int64;
BeyondFinalZero: Int64;
end;
PFileZeroDataInformation = ^TFileZeroDataInformation;
var
EncryptFile: TEncryptFile;
const
FILE_ATTRIBUTE_SPARSE_FILE = $80;
FSCTL_GET_COMPRESSION = $9003C;
FSCTL_SET_COMPRESSION = $9C040;
FSCTL_SET_ZERO_DATA = $980C8;
FSCTL_SET_SPARSE = $900C4;
COMPRESSION_FORMAT_NONE = 0;
COMPRESSION_FORMAT_DEFAULT = 1;
{ TNTFSFileStream }
procedure TNTFSFileStream.Compress;
begin
Compressed := True;
end;
//------------------------------------------------------------------------------
constructor TNTFSFileStream.Create(const AFilename: string;
const AMode: Word = fmCreate; const AOptions: TNTFSFileStreamOptions = []);
begin
FFileName := AFilename;
FMode := AMode;
FOptions := AOptions;
inherited Create(CreateFile(FFilename, FMode, FOptions));
end;
//------------------------------------------------------------------------------
function TNTFSFileStream.CreateFile(const AFilename: string;
const AMode: Word; const AOptions: TNTFSFileStreamOptions): THandle;
var
DesiredAccess: Cardinal;
ShareMode: Cardinal;
CreationDisposition: Cardinal;
FlagsAndAttributes: Cardinal;
Option: TNTFSFileStreamOption;
begin
DesiredAccess := 0;
ShareMode := 0;
if (AMode and fmCreate) = fmCreate then
begin
if FileExists(AFilename) then
if not DeleteFile(AFilename) then
RaiseLastOSError;
DesiredAccess := GENERIC_READ or GENERIC_WRITE;
ShareMode := 0;
CreationDisposition := CREATE_ALWAYS;
FlagsAndAttributes := FILE_ATTRIBUTE_NORMAL;
for Option := Low(TNTFSFileStreamOption) to High(TNTFSFileStreamOption) do
if Option in AOptions then
case Option of
fsoTemporary: FlagsAndAttributes := FlagsAndAttributes or FILE_ATTRIBUTE_TEMPORARY;
fsoWriteThrough: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_WRITE_THROUGH;
fsoNoBuffering: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_NO_BUFFERING;
fsoRandomAccess: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_RANDOM_ACCESS;
fsoSequentialScan: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_SEQUENTIAL_SCAN;
fsoDeleteOnClose: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_DELETE_ON_CLOSE;
end;
end
else
begin
FlagsAndAttributes := FILE_ATTRIBUTE_NORMAL;
case AMode and 3 of
fmOpenRead: DesiredAccess := GENERIC_READ;
fmOpenWrite: DesiredAccess := GENERIC_WRITE;
fmOpenReadWrite: DesiredAccess := GENERIC_READ or GENERIC_WRITE;
fmOpenReadWrite or fmOpenWrite: DesiredAccess := GENERIC_READ or GENERIC_WRITE;
end;
case AMode and $F0 of
fmShareCompat, fmShareExclusive: DesiredAccess := DesiredAccess or 0;
fmShareDenyWrite: DesiredAccess := DesiredAccess or FILE_SHARE_READ;
fmShareDenyRead: DesiredAccess := DesiredAccess or FILE_SHARE_WRITE;
fmShareDenyNone: DesiredAccess := DesiredAccess or (FILE_SHARE_READ or FILE_SHARE_WRITE);
end;
CreationDisposition := OPEN_EXISTING;
end;
{$IFDEF DELPHIXE2_UP}
Result := Winapi.Windows.CreateFile(PChar(Filename), DesiredAccess,
ShareMode, nil, CreationDisposition, FlagsAndAttributes, 0);
{$ELSE}
Result := Windows.CreateFile(PChar(AFilename), DesiredAccess, ShareMode,
nil, CreationDisposition, FlagsAndAttributes, 0);
{$ENDIF}
if Result = INVALID_HANDLE_VALUE then
RaiseLastOSError;
try
if (AMode and fmCreate) = fmCreate then
begin
if fsoEncrypted in AOptions then
begin
CloseHandle(Result);
if not Assigned(EncryptFile) then
raise Exception.Create(rsCanNotEncryptFiles);
if not EncryptFile(PChar(AFilename)) then
RaiseLastOSError;
Result := CreateFile(AFilename, fmOpenReadWrite or fmShareExclusive, AOptions);
end
else
SetCompression(Result, fsoCompressed in AOptions);
end;
if fsoSparse in AOptions then
SetSparse(Result);
except
CloseHandle(Result);
raise;
end;
end;
← →
DVM © (2012-08-16 17:28) [29]
//------------------------------------------------------------------------------
procedure TNTFSFileStream.Decompress;
begin
Compressed := False;
end;
//------------------------------------------------------------------------------
destructor TNTFSFileStream.Destroy;
begin
if Handle <> 0 then
CloseHandle(Handle);
inherited;
end;
//------------------------------------------------------------------------------
function TNTFSFileStream.GetCompressed: Boolean;
var
CompressionAlgorithm: Word;
Dummy: Cardinal;
begin
if not DeviceIoControl(Handle, FSCTL_GET_COMPRESSION, nil, 0,
@CompressionAlgorithm, SizeOf(CompressionAlgorithm), Dummy, nil) then
RaiseLastOSError;
Result := (CompressionAlgorithm <> COMPRESSION_FORMAT_NONE);
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.Recompress;
begin
if Compressed then
begin
Decompress;
Compress;
end;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.SetCompressed(const AValue: Boolean);
begin
if AValue <> GetCompressed then
SetCompression(Handle, AValue);
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.SetCompression(const AHandle: THandle;
const AEnabled: Boolean);
var
Dummy : Cardinal;
CompressionAlgorithm : Word;
const
CompressionAlgorithms : array[Boolean] of Word = (
COMPRESSION_FORMAT_NONE,
COMPRESSION_FORMAT_DEFAULT
);
begin
CompressionAlgorithm := CompressionAlgorithms[AEnabled];
if not DeviceIoControl(AHandle, FSCTL_SET_COMPRESSION, @CompressionAlgorithm,
SizeOf(CompressionAlgorithm), nil, 0, Dummy, nil) then
RaiseLastOSError;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.SetSparse(const AHandle: THandle);
var
Dummy : Cardinal;
begin
if not DeviceIoControl(AHandle, FSCTL_SET_SPARSE, nil, 0, nil, 0, Dummy, nil) then
RaiseLastOSError;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.ZeroData(const AFileOffset, ALength: Int64);
begin
ZeroDataForTwoOffsets(AFileOffset, AFileOffset + ALength);
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.ZeroDataForTwoOffsets(const AFirstOffset, ALastOffset: Int64);
var
FileZeroDataInformation: TFileZeroDataInformation;
BytesReturned: Cardinal;
begin
if not (fsoSparse in FOptions) then
raise Exception.CreateFmt(rsFileIsNotSparse, [FFileName]);
FileZeroDataInformation.FileOffset := AFirstOffset;
FileZeroDataInformation.BeyondFinalZero := ALastOffset;
if not DeviceIoControl(Handle, FSCTL_SET_ZERO_DATA, @FileZeroDataInformation,
SizeOf(FileZeroDataInformation), nil, 0, BytesReturned, nil) then
RaiseLastOSError;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.ZeroToCurrPosition;
begin
ZeroDataForTwoOffsets(0, Position);
end;
//------------------------------------------------------------------------------
var
ADVAPI32Handle : THandle;
initialization
EncryptFile := nil;
ADVAPI32Handle := LoadLibrary("advapi32.dll");
if ADVAPI32Handle <> 0 then
{$IFDEF UNICODE}
EncryptFile := GetProcAddress(ADVAPI32Handle, "EncryptFileW");
{$ELSE}
EncryptFile := GetProcAddress(ADVAPI32Handle, "EncryptFileA");
{$ENDIF}
finalization
FreeLibrary(ADVAPI32Handle);
EncryptFile := nil;
end.
← →
имя (2012-08-16 17:32) [30]Удалено модератором
← →
имя (2012-08-16 17:35) [31]Удалено модератором
← →
DVM © (2012-08-16 17:36) [32]
> QAZ (16.08.12 17:32) [30]
> одно дело сказать что файл спарседный, а другое дело указать
> место
Смещения можно указать в разреженном файле всегда и какие угодно. Все что между ними будет исключено из файла и места занимать не будет на диске. В чем проблема то?
← →
QAZ (2012-08-16 17:42) [33]
> В чем проблема то?
да все норм,показалось
← →
Es (2012-08-16 19:18) [34]
> согласен с DVM (с) и не вижу ни одной причины хнанить связанные
> данные в разных местах.
Серег, ну вообще в контексте WEB есть одна причина и имя ей - HTTP-протокол, ибо он запрос-ответ ориентированный. Браузер грузит страницу - а там HTTP-ссылки на 20 изображений. Он генерирует еще 20 запросов на получение этих 20 картинок. Самое наглядное, когда используется распространенный вариант front в виде nginx для быстрой отдачи статики, а за ним back в виде apache для обработки динамики.
1) обработка статики:
Клиент / Браузер -> GET/ -> Nginx -> Файловая система, считывание файла и отдача
2) обработка динамики
Клиент / Браузер -> GET/ -> Nginx -> Apache -> PHP -> Database -> blablabla...
В случае хранения картинок в БД первый вариант обработки исключен, а это ооочень сильно снижает быстродействие и не позволяет пользоваться уже считай стандартизированными решениями. Ибо nginx безумно быстро умеет отдавать статический файл с диска, не нагружая Apache инициализацией подключения. Специфика, но очень распространенная, отсюда большая привычка многих начинающих с программирования под веб хранить файлы на диске, а не в БД.
Что в "классическом" программировании вызывает непонимание, тем более это плохо реализуется, по крайней мере при двухзвенной структуре.
← →
MsGuns © (2012-08-17 11:39) [35]Аргументы против файл-серверов:
1) Реляционность. Во многих нормальных КС в базе хранятся не только данные, но и масса непосрественно софта: шаблоны, отчеты, визуальные элементы интерфейса (формы, фрэймы, диалоги, стили и т.д.). Если все это вынести в файлы, получится туча разнокалиберных файлов со сложной системой привязки к собственно логическим объектам модели БД. В самой же базе все связи прекрасно представлены средствами сервера (бизнес-логика).
2) Целостность. Если часть данных модели раположена вне самой БД, то на порядки возрастает сложность ПО по поддержке целостности данных. "Вшивать" в триггеры обращение к внешним файлам - это что-то, да и не всякий скл-сервер позволяет. И что делать с транзакционностью ?
Про бэкапы и ресторы вообще умолчу.
3) Масштабируемость. При резком повышении интенсивности работы (в т.ч. на запись) в файл-серверном варианте обеспечены длительные ожидания и даже зависания, управлять которыми фактически нет возможности. При серверном решении такие возможности имеются, и весьма в ассортименте.
4) Конфеденциальность. Тут все ясно без слов.
Хватит ?
← →
Es (2012-08-17 12:05) [36]Удалено модератором
← →
QAZ (2012-08-17 13:13) [37]а мне кажеца или на серверах где крутятся сотни сайтов и форумов с милиардами файлов, кучей запросов и прочей белеберды, все както работает, с масштабируемостью, конфиденциальностью, бэкапами и тд ?
← →
AV © (2012-08-17 13:20) [38]
> QAZ (17.08.12 13:13) [37]
Разумно..
Но есть подозрение, что это все опять виртуально
Сайт - файл. Внутри твои картинки, скрипты, др. А снаружи это один файл.
У нас так сайт сделан. На одном из серверов виртуалка стоит, бэкап сайта - бэкап файла виртуалки :)
← →
Sergey Masloff (2012-08-17 13:21) [39]QAZ (17.08.12 13:13) [37]
Кажется
← →
QAZ (2012-08-17 13:27) [40]
> AV © (17.08.12 13:20) [38]
кая разница что это снаружи один файл когда внутри тот же милион, да и виртуализация не прибавляет скорости
← →
AV © (2012-08-17 13:41) [41]
> QAZ (17.08.12 13:27) [40]
ну как, тебе дали место, видится нормально, ваяй что хочешь. Миллион файлов, так миллион. Значит, ССЗБ.
Администрация выделила тебе ресурс, как места, так времени процессора, памяти, др.
А чтобы ты ничего не свалил, что бы переезды там всякие были быстрые/успешные, или если тебя ломанули - все восстановимо простым f5 в тотале (это я утрирую сейчас)
А хочешь быстро - покупай свой сервак, договоры заключай( или что там провайдеры еще делают)
← →
QAZ (2012-08-17 13:46) [42]
> или что там провайдеры еще делают
продают белый IP за стописят руб. месяц
> AV © (17.08.12 13:41) [41]
так не, тут народ говорит что дескать база данных из дохрена файлов это ужасное зло обреченное на скорую погибель
а интернет почемуто до сих пор жив, и всякие фейсбуки где база явно не из трех файлов состоит процветает
← →
Es (2012-08-17 13:46) [43]Sergey Masloff, а ты то ничего не расскажешь про хранимки в контексте ADO + Oracle или вы окончательно съехали на шарп и про дельфю забыли? )
← →
Sergey Masloff (2012-08-17 14:14) [44]
> Es (17.08.12 13:46) [43]
ADO никогда не использовали. Про ODAC и DOA могу рассказать много чего если понадобится кому ;-)
Ну еще про BDE вот там много чего было подводного но кого это сейчас волнует ;-)
← →
Es (2012-08-20 11:35) [45]Ну что, господа.
Не может же быть такого, чтобы мы не разобрались как вызывать хранимку с BLOB"ом большого размера. Тем более Oracle точно не против. Он почему-то против ADO...
← →
DVM © (2012-08-20 12:00) [46]
> Es (20.08.12 11:35) [45]
> Тем более Oracle точно не против.
А в документации везде сказано что в хранимую процедуру Oracle нельзя передать BLOB больше 32к
← →
Sergey Masloff (2012-08-20 12:11) [47]
> А в документации везде сказано что в хранимую процедуру
> Oracle нельзя передать BLOB больше 32к
Да ну на ;-) Это микрософтовский провайдер может быть ограничивает - говорят он поверх OCI7 лежит
← →
Sergey Masloff (2012-08-20 12:18) [48]
> Не может же быть такого, чтобы мы не разобрались как вызывать
> хранимку с BLOB"ом большого размера. Тем более Oracle точно
> не против. Он почему-то против ADO...
Есть такое мнение что ты не задаешь значение SPPrmsLOB. Поэтому провайдер не биндит его как BLOB а то через чего он его биндит в PL/SQL не может иметь длинну более 32К
Мне не на чем попробовать
← →
Sergey Masloff (2012-08-20 12:21) [49]стырено на просторах инета
with ADOCommand1 do try
CommandObject.Set_ActiveConnection(ADOConnection1.ConnectionObject);
Properties["SPPrmsLob"].Value := true;
.....
Parameters.ParamByName("bDATA").LoadFromStream(...,ftBlob);
Execute;
finally
ADOCommand1.Properties["SPPrmsLob"].Value := false;
end;
ОНО?
← →
DVM © (2012-08-20 12:22) [50]
> Sergey Masloff (20.08.12 12:11) [47]
> Это микрософтовский провайдер может быть ограничивает
Я с Oracle практически не работал, может быть, но просто полез в гугл и нашел множество таких замечаний в разных мануалах, например в JDBC:
http://docs.oracle.com/cd/B19306_01/java.102/b14355/oralob.htm
Passing BLOB and CLOB Locators
Given a standard JDBC prepared statement or callable statement, you can use standard setter methods to pass LOB locators. These methods are defined as follows:
public void setBlob(int index, Blob value);
public void setClob(int index, Clob value);
Note:
If you pass a BLOB to a PL/SQL procedure, then the BLOB must be no bigger than 32K - 7. If you pass a BLOB that exceeds this limit, then you will receive a SQLException.
http://docs.oracle.com/cd/E11882_01/java.112/e16548/oralob.htm
← →
DVM © (2012-08-20 12:23) [51]
> Sergey Masloff (20.08.12 12:21) [49]
Тут важно, чтобы именно в хранимую процедуру передавалось
← →
Es (2012-08-20 12:47) [52]DVM, нет. По крайней мере на 11g проверено. Мы генерировали BLOB-поток на стороне оры, порядка 16 мбайт (то что у нас в тесте с клиента через ADO не прошло по размеру). Отлично такой BLOB уходит как параметр в хранимку, а хранимка его потом записала в поле таблицы.
Так что ора не против.
← →
DVM © (2012-08-20 13:33) [53]
> Es (20.08.12 12:47) [52]
> По крайней мере на 11g проверено.
А у тебя какая версия Oracle? Там как раз написано, что в 11 нет ограничения, а в 10 вроде как есть.
← →
Es (2012-08-20 13:42) [54]мне кажется ты ошибаешься... от сервера это не зависит. наверное, там речь идет про клиентскую сторону. Возможно, это зависит от клиентской версии.
← →
Es (2012-08-20 13:54) [55]да, на десятом оракле всё точно также хорошо работает, блоб в 20 мегабайт в хранимку улетает хорошо.
← →
Es (2012-08-20 14:06) [56]
> ОНО?
ну я не очень понял причем здесь ADOCommand... Ведь Insert / Update и так работает хорошо с большими блобами в несколько мегабайт.
Затык идет с передачей именно в хранимки. С хранимкой работаю через TADOStoredProc, если там устанавливать свойство "SPPrmsLob", так у меня вообще вылетает AV...
http://www.onlinedisk.ru/get_image.php?id=930217
← →
Sergey Masloff (2012-08-20 14:14) [57]
> Затык идет с передачей именно в хранимки. С хранимкой работаю
> через TADOStoredProc, если там устанавливать свойство "SPPrmsLob",
> так у меня вообще вылетает AV...
там типп cmdStoredProc и вызывается именно хранимка - в том месте откуда я код драл ;-)
Приведи свой пример кода где там AV?
вот этоCommandObject.Set_ActiveConnection
делал ДО установки свойства?
← →
Sergey Masloff (2012-08-20 14:15) [58]
> Тут важно, чтобы именно в хранимую процедуру передавалось
Это именно для хранимой процедуры.
У автора ж в query работает а в sp нет. Это значит что там биндится через какой-то тип который имеет разный допустимый размер в SQL и PL/SQL
То есть его "нелигитимное" преобразование становится таким только в случае с использованием системы типов PL/SQL
Если задать этот параметр то биндинг будет гарантировано проходить с использованием типа BLOB который одинаковый в SQL и PL/SQL энджайнах
Пока предположение такое дальше будем смотреть
← →
Sergey Masloff (2012-08-20 14:17) [59]Про размеры - и в 8 (вроде бы) и в 9 и далее вставлял блобы через хранимые размерами гораздо больше жалких десятка мегабайт ;-)
Так как не использовал ADO даже не знал что с ними проблемы могут быть
;-)
← →
Es (2012-08-20 14:20) [60]А-а-а, Серёг, я неправильно понял твой выдранный код ))
Я ставил у ADOStoredProc.Properties, а оказывается еще есть ADOStoredProc.Parameters.Properties.
Всё заработало на ура, спасибо )
Страницы: 1 2 вся ветка
Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
Память: 0.64 MB
Время: 0.063 c