Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.66 MB
Время: 0.095 c
6-1259847112
Bellf
2009-12-03 16:31
2013.03.22
Отправка данных на Сервер Соап


15-1353514078
Printer7
2012-11-21 20:07
2013.03.22
Печать как низкое разрешение


15-1342379221
Просто ФАН
2012-07-15 23:07
2013.03.22
Работа с файлами


15-1352665803
Юрий
2012-11-12 00:30
2013.03.22
С днем рождения ! 12 ноября 2012 понедельник


2-1345262775
0?0
2012-08-18 08:06
2013.03.22
Не ожидать завершения процедуры.