EXEC SQL LOB WRITE APPEND与轮询(WRITE FIRST、WRITE NEXT和WRITE LA

EXEC SQL LOB WRITE APPEND vs polling (WRITE FIRST, WRITE NEXT, WRITE LAST)

本文关键字:WRITE FIRST NEXT LA LOB SQL APPEND EXEC      更新时间:2023-10-16

第一次接触Oracle数据库中的LOB时,偶然发现了一些让我感到困惑的东西。

我必须使用Pro*CBLOB插入到要插入表的行的列中。文件上说我有两个可能的选择。

  1. 如果lob适合缓冲区,则使用EXEC SQL WRITEONE一次写入所有lob
  2. 如果缓冲区太小,则使用文档所称的轮询逐段写入lob,顺序由以下3个步骤组成:

    1. EXEC SQL WRITEFIRST
    2. EXEC SQL WRITENEXTn次
    3. EXEC SQL WRITELAST

然而,我发现我可以用EXEC SQL WRITEAPPENDn+2次简单地替换文档中描述的轮询方法,使循环更加简单、直观,并更容易处理错误处理。

因此,与其写这样的东西(取自文档):

if (filelen > MAXBUFLEN)
nbytes = MAXBUFLEN ;
else
nbytes = filelen ;
fread((void *)buffer, (size_t)nbytes, (size_t)1, fp) ;
remainder = filelen - nbytes ;
if (remainder == 0)
{
EXEC SQL LOB WRITE ONE :amt
FROM :buffer INTO :blob AT :offset ;
}
else
{
EXEC SQL LOB WRITE FIRST :amt
FROM :buffer INTO :blob AT :offset ;
last = FALSE ;
EXEC SQL WHENEVER SQLERROR DO break ;
do
{
if (remainder > MAXBUFLEN)
nbytes = MAXBUFLEN ;
else
{
nbytes = remainder ;
last = TRUE ;
}
if (fread((void *)buffer, (size_t)nbytes, (size_t)1, fp) != 1)
last = TRUE ;
if (last)
{  
EXEC SQL LOB WRITE LAST :amt
FROM :buffer INTO :blob  ;
}           
else
{
EXEC SQL LOB WRITE NEXT :amt
FROM :buffer INTO :blob;
}
remainder -= nbytes ;
}
while (!last && !feof(fp)) ;
}

人们可以这样写:

while ((nbytes = remainder < MAXBUFLEN ? remainder : MAXBUFLEN)) 
{
if (fread(buffer, nbytes, 1, fp) != 1) {
/* Handle error somehow */
break;
}
EXEC SQL LOB WRITE APPEND :nbytes 
FROM :buffer WITH LENGTH :nbytes INTO blob;
remainder -= nbytes;
}

我在没有注意到任何问题的情况下彻底测试了第二种方法,所以我想知道:

  1. 第二种方法是否有问题
  2. 如果可以像第二种方法那样进行,那么像文档所解释的那样,由3个步骤组成的轮询机制需要什么

如果使用LBS(LOB缓冲子系统)进行适当的缓冲,可能会有一些优势。Oracle解释-

缓冲具有这些优点,特别是对于对的特定区域执行许多小型读写操作的客户端LOB:

  1. LBS减少了到服务器的往返行程,因为您在缓冲区中对LOB进行多次读取/写入,然后写入服务器执行FLUSH指令时。

  2. 缓冲还可以减少服务器上LOB更新的总数。这样可以创建更好的LOB性能并节省磁盘空间。

滚动到链接中的LOB Buffering Subsystem部分以阅读更多信息。