MS SQL到Oracle链接服务器。列

时间:2017-10-30 16:29:09

标签: sql sql-server oracle linked-server

我需要将数据从MS SQL(AWS EC2)表复制到Oracle(AWS RDS)实例。在几次失败的方法之后,我决定在SQL中创建一个链接服务器到Ora数据库并在触发事件上插入新数据。到目前为止,非常好。

现在我试图从[相同] SQL表中将数据插入到单个Oracle表中,但是收到以下错误

“用于链接服务器的”OLE DB提供程序“OraOLEDB.Oracle”“desora12”为“CREATE_DATE”列提供了无效的元数据。不支持数据类型。“

我已尝试从插入语句中取出CREATE_DATE,但收到相同的错误。我还尝试在select语句中转换和转换CreateDate。同样的错误。

Oracle中的CREATE_DATE列类型是TIMESTAMP(6)。 SQL中相应的CreateDate列类型是可为空的DateTime

表格中有31列,这里是插入的删节版本。

INSERT INTO [desora12]..[DATAENTRY].[TBL_API_ITEM_TYPEID1_LBL_TEST]
       ([SITE_ID]
       ,[USER_ID]
       ,[CREATE_DATE]
       ,[TRANSFER_DATE]
       ,[TRANSFER_STATUS])
SELECT TOP 1 SiteID,
         UserID,
         CreateDate,
         TransferDate,
         TransferStatus
    FROM API.ItemDataTypeID1Label
      WHERE TransferDate is null
      AND TransferStatus is null
      AND ReturnStatus=200

任何帮助?

1 个答案:

答案 0 :(得分:1)

我总是“拉”来传输数据,而不是像你正在做的那样“推”。 Pulls确保您在刷新开发或测试数据库时不会损害生产数据库。就日期而言,我在Oracle和SQL Server之间的日期类型上苦苦挣扎。我最终将我的Oracle日期转换为文本(请记住我正在拉动)并允许SQL Server自动将文本转换为日期。您可以在我对下面的bindvar的调用中看到这一点,我将Oracle日期转换为字符串。

如果您要从Oracle中学习,请查看DBMS_HS_PASSTHROUGH。它比通过数据库链接选择快许多倍。我一次获取200万条记录,我的运行时间从4个半小时到5分钟不等。

   PROCEDURE bindvar (
        p_cursor   IN INTEGER
      , p_pos      IN INTEGER
      , p_value    IN VARCHAR2
    )
    AS
        l_routine   CONSTANT oracleobj_t := 'bindvar';
    BEGIN
        DBMS_HS_PASSTHROUGH.bind_variable@intervaldata.world (p_cursor, p_pos, p_value);
    EXCEPTION
        WHEN OTHERS
        THEN
            make_log_error_entry (
                p_routine => l_routine
              , p_message => cealogging.activity_log_maintenance_pkg.labels (
                                'p_cursor'
                              , p_cursor
                              , 'p_pos'
                              , p_pos
                              , 'p_value'
                              , p_value
                            )
            );
            RAISE;
    END;

 -- ***********************************************************************
    --  Fetch Interval Data
    --  Purpose:
    --    Retrieve interval data from SQL*Server
    --  Arguments:
    --    p_earliestintervaldate - earliest interval date from which data will be fetched
    --    p_latestintervaldate   - latest   interval date from which data will be fetched
    --    p_earliestlogtime      - earliest log date for which data will be fetched
    --    p_latestlogtime        - latest   log date for which data will be fetched
    --    p_maxrecords   - maximum records to fetch from SQL Server
      -- ***********************************************************************
    FUNCTION fetch_intervaldata (
        p_earliestintervaldate   IN DATE
      , p_latestintervaldate     IN DATE
      , p_earliestlogdate        IN DATE
      , p_latestlogdate          IN DATE
      , p_meterno                IN VARCHAR2 DEFAULT NULL
      , p_maxrecords             IN INTEGER DEFAULT NULL
    )
        RETURN PLS_INTEGER
    AS
        l_routine   CONSTANT oracleobj_t := 'fetch_intervaldata';
        l_format    CONSTANT oracleobj_t := 'YYYYMMDD HH24:MI:SS';

        l_cnt                PLS_INTEGER;
        l_cursor             INTEGER;
        l_earliestlogdate    DATE := p_earliestlogdate;
        l_numrows            INTEGER;
        l_row                intervaldata_load%ROWTYPE;
        l_ret                PLS_INTEGER := 0;
        l_sql                VARCHAR2 (200)
            := ';select  * from  cea.fetchCisIntervalData(  ?, ?, ?, ?, ?) where interval_read is not null';
        l_latestlogtimearg   DATE;
    BEGIN

        close_databaselink (p_link => 'INTERVALDATA.WORLD');

        EXECUTE IMMEDIATE 'truncate table intervaldata_load';

        -- set l_cnt = 1 to allow the first pass to run
        -- thereafter it is the number or records returned by the pass that will
        -- be tested for continuation
        l_cnt   := 1;

        WHILE  l_earliestlogdate <= p_latestlogdate
          AND l_cnt > 0
          AND (p_maxrecords IS NULL
            OR l_ret < p_maxrecords)
        LOOP
            make_log_entry (
                p_routine => l_routine
              , p_message => 'processing starting for ' || TO_CHAR (l_earliestlogdate, c_intervaldateformat)
            );

            l_cursor            := DBMS_HS_PASSTHROUGH.open_cursor@intervaldata.world;
            DBMS_HS_PASSTHROUGH.parse@intervaldata.world (l_cursor, l_sql);
            bindvar (p_cursor => l_cursor, p_pos => 1, p_value => TO_CHAR (l_earliestlogdate, l_format));
            bindvar (
                p_cursor => l_cursor
              , p_pos    => 2
              , p_value  => TO_CHAR (l_earliestlogdate + INTERVAL '6' HOUR - INTERVAL '1' SECOND, l_format)
            );
            bindvar (p_cursor => l_cursor, p_pos => 3, p_value => TO_CHAR (p_earliestintervaldate, l_format));
            bindvar (p_cursor => l_cursor, p_pos => 4, p_value => TO_CHAR (p_latestintervaldate, l_format));
            bindvar (p_cursor => l_cursor, p_pos => 5, p_value => p_meterno);
            l_cnt               := 0;

            LOOP
                l_numrows   := DBMS_HS_PASSTHROUGH.fetch_row@intervaldata.world (l_cursor);
                EXIT WHEN l_numrows = 0
                       OR (p_maxrecords IS NOT NULL
                       AND l_ret >= p_maxrecords);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 1, l_row.meterno);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 2, l_row.interval_start);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 3, l_row.endpointid);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 4, l_row.logtime);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 5, l_row.interval_read);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 6, l_row.buy_back);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 7, l_row.phase_a);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 8, l_row.phase_b);
                DBMS_HS_PASSTHROUGH.get_value@intervaldata (l_cursor, 9, l_row.phase_b);
                EXIT WHEN l_row.logtime > p_latestlogdate;

                INSERT INTO intervaldata_load
                VALUES l_row;

                l_cnt       := l_cnt + 1;
                l_ret       := l_ret + 1;

            END LOOP;

            DBMS_HS_PASSTHROUGH.close_cursor@intervaldata.world (l_cursor);

            make_log_entry (
                p_routine => l_routine
              , p_message =>    LPAD (l_cnt, 10)
                             || ' records retrieved for '
                             || TO_CHAR (l_earliestlogdate, c_intervaldateformat)
                             || ' to '
                             || TO_CHAR (l_earliestlogdate + INTERVAL '6' HOUR, c_intervaldateformat)
            );

            l_earliestlogdate   := l_earliestlogdate + INTERVAL '6' HOUR;
        END LOOP;

        RETURN l_ret;
    EXCEPTION
        WHEN OTHERS
        THEN
            make_log_error_entry (
                p_routine => l_routine
              , p_message => 'processing ' || TO_CHAR (l_earliestlogdate, l_format)
            );
            DBMS_HS_PASSTHROUGH.close_cursor@intervaldata.world (l_cursor);
            RAISE;
    END fetch_intervaldata;