在 DB2 for Linux, UNIX and Windows 中使用管道加载数据

转自 http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-1002db2pipes/index.html

动机

在 UNIX 和 Linux 环境中,您可以使用 mkfifo 命令来创建管道。然后,您可以通过 DB2 LOAD 命令来使用管道。但是,Windows 操作系统不允许您使用类似于 mkfifo 的外部命令来创建指定管道。在 Windows 中,您需要通过 Windows API 来创建指定管道,并且该管道的作用域仅限于创建它时所处的会话。此外,使用 Java 创建的指定管道不能与 Windows shell 交互,因此不能由 DB2 LOAD 命令使用。

本文 下载 部分提供了 pipeload.zip 文件的下载链接,其中的示例代码可帮助您解决此问题。使用该示例代码,您可以创建供 DB2 LOAD 命令使用的 Windows 管道。为此,您将创建一些 Java Native Interface (JNI) 包装器,它们可通过 C 程序调用 Windows API 以创建和使用指定管道。然后,您可以使用 Java 程序将数据发送给 Windows 管道。

示例代码概述

从较高的层面来说,示例代码使用 Java 驱动程序(TestPipe.java 或 TestUnixPipe.java)将数据发送给指定管道。然后,db2load.sql 通过单独命令 shell 中的管道来使用数据。IBM Data Movement Tool 演示了这一概念(请参阅 参考资料 部分,其中链接的一篇 developerWorks 文章介绍了 IBM Data Movement Tool)。

pipeload.zip 下载 文件中各主要文件的描述如下:

  • Pipe.c — 使用 Windows APIs 创建、使用和关闭 Windows 指定管道的 C 代码。
  • Pipes.java — 为 Pipe.c 中使用的所有 Windows 本地方法声明包装器的 Java Native Interface (JNI)。
  • TestPipe.java — 创建、使用和关闭 Windows 指定管道的 JNI 调用。
  • TestUnixPipe.java — 包含对 mkfifo 命令的指纹调用,用于创建、使用和抛弃 UNIX 中的指定管道
  • db2load.sql — 包含使用管道的 DB2 LOAD 命令。

Windows 中的指定管道

在 Windows 中创建的指定管道并不如在 UNIX 和 Linux 中创建的管道那样持久,并且您采用与特殊文件相似的方式来创建它们。Windows 指定管道的访问更像是文件,但管道在 Windows Explorer 中并不可见。Windows 管道将加载到一种特殊的文件系统。您可以使用 Windows SDK 功能(如 CreateFileReadFileWriteFileCloseHandle)来打开、读取、写入和关闭管道。

UNIX 和 Linux 中的指定管道

在 UNIX 或 Linux 中,您可以使用 mkfifomknod 命令来创建指定管道。两个独立的进程可以访问创建的管道。mkfifo 命令将创建一个 First In First Out (FIFO) 文件。然后,您可以使用此 FIFO 文件将信息从一个应用程序移到另一个应用程序,而不需要将数据存储在中间文件中。因此,您可以节省原本用于存储临时文件的空间。如果为类型指定了 p 选项,则 mknod 命令还将创建一个指定管道。

以下命令示例将通过两个步骤创建一个指定管道,并在 Unix 或 Linux 环境中载入数据。

步骤 1 — 将创建一个指定管道,并将未压缩的数据发送给管道:

$ mkfifo db2pipe
$ gunzip tabledata.gz > db2pipe	

步骤 2 — 使用管道将未压缩的数据载入到 DB2:

$ db2 connect to sample
$ db2 "LOAD FROM db2pipe OF DEL INSERT INTO mytable"
$ db2 terminate					

使用 JNI 访问 Windows 本机方法

Pipes.java 程序中的代码将声明指回通过 Pipe.c 程序实现的 Windows 本地 API 调用的 Java 方法。您可以通过 javah 程序运行 Pipes.java 来创建头文件,其中的 C 程序规范将匹配 C 方法的签名。

注意,提供 JNI 的完整描述不在本文范围之内。


清单 1. Pipes.java 文件中的 JNI 方法声明
	
public class Pipes
{
   static
   {
      System.loadLibrary("Pipe");
   }

   public static final native int CreateNamedPipe(String pipeName,
      int ppenMode, int pipeMode, int maxInstances,
   int outBufferSize, int inBufferSize, int defaultTimeOut,
      int securityAttributes);

   public static final native boolean ConnectNamedPipe(int namedPipeHandle, 
      int overlapped);
   public static final native int GetLastError();
   public static final native boolean CloseHandle(int bbject);
   public static final native byte[] ReadFile(int file, int numberOfBytesToRead);
   public static final native int WriteFile(int file, byte[] buffer, 
      int numberOfBytesToWrite);
   public static final native boolean FlushFileBuffers(int file);
   public static final native boolean DisconnectNamedPipe(int namedPipeHandle);
   public static final native int CreateFile(String fileName,
      int desiredAccess, int shareMode, int securityAttributes,
      int creationDisposition, int flagsAndAttributes,
      int templateFile);

   public static final native boolean WaitNamedPipe(String namedPipeName, int timeOut);
   public static final native String FormatMessage(int errorCode);
   public static final native void Print(String message);

创建 JNI 头文件

使用以下代码为 Pipes.java 编译和创建 JNI 头文件:

javac ibm/Pipes.java
javah -jni ibm.Pipes

将 ibm_Pipes.h 文件从示例代码复制到 C 程序文件夹中。

封装 Windows 方法的 C 代码

清单 2 中的示例 C 代码来自下载示例中的 Pipe.c 文件。该代码创建的 C 函数将与您在上一步骤中使用 javah 程序创建的头文件中的声明相匹配。


清单 2. JNI 示例代码清单
				
#include  
#include 
#include 
#include "ibm_Pipes.h"

#define  DEBUG 0

JNIEXPORT jint JNICALL Java_ibm_Pipes_CreateNamedPipe
(
    JNIEnv *env, 
    jclass className, 
    jstring sPipeName, 
    jint dwOpenMode, 
    jint dwPipeMode, 
    jint nMaxInstances, 
    jint nOutBufferSize, 
    jint nInBufferSize, 
    jint nDefaultTimeOut, 
    jint lpSecurityAttributes
 )
{
   HANDLE pipeHandler;
   LPCSTR pipeName;
   pipeName = (*env)->GetStringUTFChars(env, sPipeName, NULL);
   if (pipeName == NULL)
      return -1;

   if (DEBUG)
   {
      printf("Native: Pipe Name %s\n", pipeName);
      printf("Native: dwOpenMode %d\n", dwOpenMode);
      printf("Native: dwPipeMode %d\n", dwPipeMode);
      printf("Native: nMaxInstances %d\n", nMaxInstances);
      printf("Native: nOutBufferSize %d\n", nOutBufferSize);
      printf("Native: nInBufferSize %d\n", nInBufferSize);
      printf("Native: nDefaultTimeOut %d\n", nDefaultTimeOut);
   }

   pipeHandler = CreateNamedPipe((LPCSTR)pipeName, dwOpenMode, 
                     dwPipeMode, nMaxInstances, nOutBufferSize, 
                     nInBufferSize, nDefaultTimeOut, 
                   (LPSECURITY_ATTRIBUTES) lpSecurityAttributes);  

   (*env)->ReleaseStringUTFChars(env, sPipeName, pipeName);
   return (jint) pipeHandler;
}

JNIEXPORT jboolean JNICALL Java_ibm_Pipes_ConnectNamedPipe
(
    JNIEnv *env, 
    jclass className, 
    jint hNamedPipe, 
    jint lpOverlapped
 )
{
   BOOL fConnected;
   HANDLE pipeHandler = (HANDLE) hNamedPipe;
   fConnected = ConnectNamedPipe(pipeHandler, 
                           (LPOVERLAPPED) lpOverlapped);
   return fConnected;
}

JNIEXPORT jint JNICALL Java_ibm_Pipes_GetLastError 
(
    JNIEnv *env, 
    jclass className
 )
{
   DWORD errorNumber = GetLastError();
   return (jint) errorNumber;
}

JNIEXPORT jboolean JNICALL Java_ibm_Pipes_CloseHandle
(
    JNIEnv *env, 
    jclass className, 
    jint hNamedPipe
 )
{
   BOOL result;
    HANDLE pipeHandler = (HANDLE) hNamedPipe;
   result = CloseHandle(pipeHandler);
   return result;
}

JNIEXPORT jbyteArray JNICALL Java_ibm_Pipes_ReadFile
(
    JNIEnv *env, 
    jclass className, 
    jint hNamedPipe, 
    jint nNumberOfBytesToRead
 )
{
   int bytesRead = 0;
   BOOL result;
    HANDLE pipeHandler = (HANDLE) hNamedPipe;
   LPVOID buffer;
   jbyteArray lpBuffer;

   buffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT, nNumberOfBytesToRead);

   if (DEBUG)
   {
      printf("Native: Before ReadFile pipeHandler %d 
         nNumberOfBytesToRead %d\n", pipeHandler, nNumberOfBytesToRead);
   }
   result = ReadFile(pipeHandler, (LPVOID) buffer, 
                     (DWORD) nNumberOfBytesToRead, 
                     &bytesRead, (LPOVERLAPPED) 0);
   if (result)
   {
      lpBuffer = (*env)->NewByteArray(env, (jsize) bytesRead);    
      (*env)->SetByteArrayRegion(env, lpBuffer, 0, 
                             (jsize) bytesRead, (jbyte *) buffer);
   } else
      bytesRead = 0;

   LocalFree(buffer);

   if (DEBUG)
   {
      printf("Native: After ReadFile BytesRead %d\n", bytesRead);
   }
   return lpBuffer;
}

JNIEXPORT jint JNICALL Java_ibm_Pipes_WriteFile
(
    JNIEnv *env, 
    jclass className, 
    jint hNamedPipe, 
    jbyteArray lpBuffer, 
    jint nNumberOfBytesToWrite
 )
{
   int bytesWritten = 0;
   BOOL result;
    HANDLE pipeHandler = (HANDLE) hNamedPipe;
   LPVOID buffer;

   buffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT, nNumberOfBytesToWrite);

   (*env)->GetByteArrayRegion(env, lpBuffer, 0, 
                    nNumberOfBytesToWrite, buffer);
   result = WriteFile(pipeHandler, buffer, 
                      (DWORD) nNumberOfBytesToWrite, 
                      (LPDWORD) &bytesWritten, (LPOVERLAPPED) 0);
   LocalFree(buffer);

   if (DEBUG)
   {
      printf("Native: After WriteFile BytesReadWritten %d\n", 
             bytesWritten);
   }

   if (!result)
   {
      if (GetLastError() != ERROR_IO_PENDING)
         result = 0;
      else
         result = 1;
   }
   if (!result)
   {
      bytesWritten = -1;
   }
   return bytesWritten;
}

JNIEXPORT jboolean JNICALL Java_ibm_Pipes_FlushFileBuffers
(
    JNIEnv *env, 
    jclass className, 
    jint hNamedPipe
 )
{
   BOOL result;
    HANDLE pipeHandler = (HANDLE) hNamedPipe;
   result = FlushFileBuffers(pipeHandler); 
   return result;
}

JNIEXPORT jboolean JNICALL Java_ibm_Pipes_DisconnectNamedPipe
(
    JNIEnv *env, 
    jclass className, 
    jint hNamedPipe
 )
{
   BOOL result;
    HANDLE pipeHandler = (HANDLE) hNamedPipe;
   result = DisconnectNamedPipe(pipeHandler);
   return result;
}

JNIEXPORT jint JNICALL Java_ibm_Pipes_CreateFile
(
    JNIEnv *env, 
    jclass className, 
    jstring lpFileName, 
    jint dwDesiredAccess, 
    jint dwShareMode, 
    jint lpSecurityAttributes, 
    jint dwCreationDisposition, 
    jint dwFlagsAndAttributes, 
    jint hTemplateFile
 )
{
    HANDLE pipeHandler;
   const jbyte *fileName;
   fileName = (*env)->GetStringUTFChars(env, lpFileName, NULL);
   if (fileName == NULL)
      return -1;
   pipeHandler = CreateFile((LPCSTR) fileName, 
                            (DWORD) dwDesiredAccess, (DWORD) dwShareMode, 
      (LPSECURITY_ATTRIBUTES) lpSecurityAttributes, 
                            (DWORD) dwCreationDisposition, 
                            (DWORD) dwFlagsAndAttributes, 
                            (HANDLE) hTemplateFile);
   return (jint) pipeHandler;
}

JNIEXPORT jboolean JNICALL Java_ibm_Pipes_WaitNamedPipe
(
    JNIEnv *env, 
    jclass className, 
    jstring lpNamedPipeName, 
    jint nTimeOut
 )
{
   BOOL result;
   const jbyte *pipeName;
   pipeName = (*env)->GetStringUTFChars(env, lpNamedPipeName, NULL);
   if (pipeName == NULL)
      return 0;
   result = WaitNamedPipe((LPCSTR) pipeName, (DWORD) nTimeOut);
   return result;
}

JNIEXPORT jstring JNICALL Java_ibm_Pipes_FormatMessage
(
   JNIEnv *env, 
   jclass className, 
   jint errorCode
)
{
   LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
   DWORD dw = (DWORD) errorCode;

   FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

   lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
                    LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("Failed with error %d: %s"), dw, lpMsgBuf); 
   return (jstring) (*env)->NewStringUTF(env, lpDisplayBuf);
}

JNIEXPORT void JNICALL Java_ibm_Pipes_Print(JNIEnv *env, 
                                            jclass className, 
                                            jstring lpMsgBuf)
{  
   const jbyte *str;
   str = (*env)->GetStringUTFChars(env, lpMsgBuf, NULL);
   if (str == NULL)
      return;
   printf("Native: %s\n", str);
   (*env)->ReleaseStringUTFChars(env, lpMsgBuf, str);
   return;
}

在 Windows 中编译 C 程序

要编译和创建动态链接库 (DLL),您需要使用 Windows cl.exe 编译器。如果还没有 cl.exe,请下载 Microsoft Visual Studio Express Edition 获取它。有关如何使用 Visual Studio 来编译 C 程序的详细步骤并不在本文的讨论范围之内。但是,您可以在命令行中使用 cl.exe 来创建 DLL,如下所示:

cl -I"C:\Program Files\IBM\Java50\include" -I"C:\Program Files\IBM\Java50\include\win32" 
       -LD Pipe.c -FePipe.dll		    

使用 cl.exe 创建 DLL 时,记住将 ibm_Pipes.h 文件复制到当前目录,并将到 Java include 目录的引用替换为系统上该目录的实际位置。

使用 Windows 管道的示例 Java 程序

使用清单 3 中的代码在 Windows 上创建一个指定管道(使用在 Pipes.h 头文件中声明并在 Pipe.c 代码中实现的本机方法。)


清单 3. 使用 Windows 管道的示例 TestPipe.java 程序

		    
package ibm;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class TestPipe
{
   static final int ERROR_PIPE_CONNECTED = 535;
   static final int ERROR_BROKEN_PIPE = 109;
   private int namedPipeHandle;
   private String pipeName, srcFile;
   private int pipeBuffer = 131072, fileBuffer = 8192;
   
   public TestPipe(String pipeName, String srcFile)
   {
      this.pipeName = pipeName;
      this.srcFile = srcFile;    
   }
   
   private void log(String message)
   {
      System.out.println(message);     
   }  

   private boolean createPipe()
   {
      boolean k = false;
      namedPipeHandle = Pipes.CreateNamedPipe(pipeName, 
                0x00000003, 0x00000000, 2, pipeBuffer, 
                pipeBuffer, 0xffffffff, 0);
      if (namedPipeHandle == -1)
      {
         log("CreateNamedPipe failed for " + pipeName + 
               " for error " + " Message " + 
                    Pipes.FormatMessage(Pipes.GetLastError()));
         k = false;
      } else
      {
         log("Named Pipe " + pipeName + 
              " created successfully Handle=" + namedPipeHandle);
         k = true;
      }
      return ok;
   }
   
   private boolean connectToPipe()
   {
      log("Waiting for a client to connect to pipe " + pipeName);
      boolean connected = Pipes.ConnectNamedPipe(namedPipeHandle, 0);
      if (!connected)
      {
         int lastError = Pipes.GetLastError();
         if (lastError == ERROR_PIPE_CONNECTED)
            connected = true;
      }
      if (connected)
      {
         log("Connected to the pipe " + pipeName);
      } else
      {
         log("Falied to connect to the pipe " + pipeName);
      }
      return connected;
   }

   public void runPipe()
   {
      if (createPipe())
      {
         if (!connectToPipe())
         {
            log("Connect ConnectNamedPipe failed : " + 
                  Pipes.FormatMessage(Pipes.GetLastError()));
            return;
         } else
         {
            log("Client connected.");
         }
         
         try
         {
            File f1 = new File(this.srcFile);
            InputStream in = new FileInputStream(f1);
            log("Sending data to the pipe");
            byte[] buf = new byte[fileBuffer];
            int len, bytesWritten;
            while ((len = in.read(buf)) > 0)
            {
              bytesWritten = Pipes.WriteFile(namedPipeHandle, buf, len);
              log("Sent " + len + "/" + bytesWritten + 
                               " bytes to the pipe");
              if (bytesWritten == -1)
              {
                 int errorNumber = Pipes.GetLastError();
                 log("Error Writing to pipe " + 
                            Pipes.FormatMessage(errorNumber));
              }                  
            }
            in.close();
            Pipes.FlushFileBuffers(namedPipeHandle);
            Pipes.CloseHandle(namedPipeHandle);
            Pipes.DisconnectNamedPipe(namedPipeHandle);
            log("Writing to the pipe completed.");
         } catch (Exception e)
         {
            e.printStackTrace();
         }
      }     
   }
   
   public static void main(String[] args) throws IOException, 
               InterruptedException 
   {
      String pipeName = "\\\\.\\pipe\\mynamedpipe";
      String fileName = "C:\\db2tabledata.txt";;
      TestPipe testPipe = new TestPipe(pipeName, fileName);
      testPipe.runPipe();
   }
}

使用 UNIX 管道的示例 Java 程序

在 UNIX 中,您不需要通过 Java 代码来调用 C 程序和创建指定管道。这是因为 UNIX 可以直接使用 mkfifomknod 命令来创建指定管道。清单 4 中的代码展示了在 UNIX 中使用指定管道的示例。


清单 4. 使用指定 UNIX 管道的示例 TestUnixPipe.java 程序
				
package ibm;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class TestUnixPipe
{
   FileChannel fc;
   int multiTables[] = new int[1];
   String filesep = System.getProperty("file.separator");
   String fileName, OUTPUT_DIR = ".", pipeName;
   int pipeBuffer = 131072, fileBuffer = 8192;
   
   public TestUnixPipe(String fileName, String output)
   {
      this.fileName = fileName;
      this.OUTPUT_DIR = output;
      multiTables[0] = 0;
   }
   
   private void log(String message)
   {
      System.out.println(message);     
   }
   
   public void runPipe()
   {
      int bytesReturn;
      pipeName = OUTPUT_DIR + "data" + filesep + pipeName + ".pipe";
      File pipeFile = new File(pipeName);
      pipeFile.deleteOnExit();
      if (!pipeFile.exists())
      {
         try
         {
            Runtime.getRuntime().exec("mkfifo " + 
                pipeFile.getAbsolutePath());
         } catch (Exception e)
         {
            e.printStackTrace();
         }
      }
      FileOutputStream fos = null;
      try
      {
         if (multiTables[0] == 0)
         {
            fos = new FileOutputStream(pipeFile);
            fc = fos.getChannel();                       
         } else
         {
            fc = fc;
         }
      } catch (Exception e)
      {
         e.printStackTrace();
      }
      try
      {
         File f1 = new File(this.fileName);
         InputStream in = new FileInputStream(f1);
         log("Sending data to the pipe");
         byte[] buf = new byte[fileBuffer];
          int len;
          while ((len = in.read(buf)) > 0)
          {
            bytesReturn = fc.write(ByteBuffer.wrap(buf));            
            log("Sent " + len + "/" + bytesReturn + 
                    " bytes to the pipe");
            if (bytesReturn == -1)
            {
               log("Error Writing to pipe " + pipeName);
            }                  
          }
          in.close();
         log("Writing to the pipe completed.");
      } catch (Exception e)
      {
         e.printStackTrace();
      }
   }
   
   public static void main(String[] args) throws IOException, 
             InterruptedException 
   {
      String utput = ".";
      String fileName = "/home/db2inst1/db2tabledata.txt";;
      TestUnixPipe testPipe = new TestUnixPipe(fileName, output);
      testPipe.runPipe();
   }
}

运行 TestPipe.java 程序以使用 Windows 管道

使用以下命令编译和运行示例 TestPipe.java 程序(清单 3)。

				
javac TestPipe.java
java -Djava.library.path=".." ibm.TestPipe

在上述示例中,您将 java.library.path 系统属性传递给 JVM,用于指示 Pipe.dll 的位置,以便于 JVM 通过 Pipe.dll 调用 Windows 本地方法。在本例中,Pipe.dll 位于比当前目录高一级的目录中。

运行 TestPipe 时,它将创建一个指定管道 \\.\pipe\mynamedpipe,并连接到该管道。随后,它将等待另一个程序(在本例中为 DB2 LOAD 命令)连接到它,然后再开始向管道写入数据。 当 DB2 LOAD 连接到管道之后,Java 程序会开始将 db2tabledata.txt 文件的内容发送给管道以及使用该数据的 DB2 LOAD


图 1. 在 Windows 命令提示中运行 Java 示例代码
pipeloadshell.jpg

使用管道的 DB2 Load 脚本

如上一节所述,在 TestPipe 程序连接到管道之后,它会等待另一个程序连接到它。要建立这个连接,请运行示例 db2load.sql DB2 脚本(清单 5)。这将创建一个表,并开始调用 LOAD 载入 mynamedpipe。


清单 5. 创建表并启动 LOAD 的示例 DB2 脚本

CONNECT TO SAMPLE;

CREATE TABLE PIPE_TABLE
(
"ID" NUMBER(10)  NOT NULL ,
"NAME" VARCHAR2(35)  ,
"LOC_ID" NUMBER(4)  
)
;
 
LOAD  FROM 
"\\.\pipe\mynamedpipe"
OF DEL 
MODIFIED BY CODEPAGE=1208  COLDEL~ ANYORDER  
   USEDEFAULTS CHARDEL"" DELPRIORITYCHAR  NOROWWARNINGS 
METHOD P (1,2,3)
MESSAGES "db2tabledata.txt"
REPLACE INTO PIPE_TABLE
(
"ID",
"NAME",
"LOC_ID"
)
 NONRECOVERABLE 
INDEXING MODE AUTOSELECT
;

TERMINATE;					

要调用 db2load.sql 脚本,请打开一个 DB2 命令行处理器 (CLP) 窗口并运行以下命令:

    
db2 -tf db2load.sql					
				

图 2 表示 db2load.sql 脚本和 TestPipe.java 程序之间的同步处理。注意,当 DB2 LOAD 命令连接到 Windows 指定管道之后,Java 程序会开始将数据写入到管道。同时,DB2 LOAD 将使用该数据并将其加载到 DB2 中。


图 2. 运行 db2load.sql 的 DB2 CLP 窗口以及运行 TestPipe.java(运行 TestPipe)的 Windows 命令提示
db2loadshellpipe.jpg

运行 TestUnixPipe.java 程序以使用 UNIX 管道

您可以在 UNIX 系统中运行 TestUnixPipe.java 程序,并且将看到与上述 Windows 环境相同的行为。当然,不同之处在于,您将使用 UNIX 功能直接创建管道。

通过 IBM Data Movement Tool 来使用管道

当您需要通过 Java 或 C/C++ 程序来处理数据时,而主要目标是避免使用中间文件时,可以定制并使用本文中的示例代码。但是,如果您的动机仅仅是使用管道将源数据库中的数据加载到 DB2,则可以使用 IBM Data Movement Tool 并指定 Use Pipe 选项,如图 3 所示。

借助 IBM Data Movement Tool,您首先从源数据库中提取表并创建表定义,然后使用管道选项载入数据。加载操作与卸载操作将同时执行。您可以同时加载和卸载一个或多个表。有关该工具及其使用方法的详细信息,请参阅 参考资料 部分中的 IBM Data Movement 文章。


图 3. IBM Data Movement Tool 的屏幕快照
idmt.jpg

结束语

DB2 LOAD 是一个极为强大的实用工具,可允许您充分利用服务器硬件来加载数据。但是,在大型数据库环境中,存入中间数据的空间便成了一个问题。您可以使用管道功能来解决此问题。在各平台中使用管道的方法大致相同,就像使用普通文件一样,只是在 Windows 环境中需要额外创建管道,并且 Java 程序必须使用 JNI 来访问 Windows API。本文的详细说明以及示例包括在下载文件中,从而降低了文章的复杂度,并且可帮助您更加轻松地完成此类任务。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15082138/viewspace-662065/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/15082138/viewspace-662065/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值