【问题标题】:How to format SQL Server DateTimeOffset and move to Oracle using OracleBulkCopy如何使用 OracleBulkCopy 格式化 SQL Server DateTimeOffset 并移至 Oracle
【发布时间】:2015-10-15 16:01:43
【问题描述】:

我正在尝试使用 OracleBulkCopy 移动 SQL Server DateTimeOffset 或 Oracle。

对于 DateTimeOffset(1),目标数据类型是 Timestamp(1) With Time Zone。

如果我在 SQL Server 上选择 DateTimeOffset(1) 列,我会收到以下信息:

2007-05-08 12:35:29.1 +12:15

当我尝试将其移至 Oracle 时,我收到:

ORA-01843:月份无效

这是有道理的,我相信这个月需要首先,但如果我运行 INSERT 到 MyOracleTable values('2007-05-08 12:35:29.1 +12:15') 我可以插入就好了。

我尝试在 SQL Server 端将 datetimeoffset 转换为各种格式。我收到各种错误,其中之一是:

ORA-01855:上午/上午或下午/下午需要

NLS_TIMESTAMP_TZ_FORMAT 参数为:

YYYY-MM-DD HH24:MI:SSXFF TZR

感谢您的帮助!

【问题讨论】:

    标签: sql-server oracle datetimeoffset timestamp-with-timezone


    【解决方案1】:

    我的想法是为 SqlDataReader 创建一个包装器并在里面进行转换:

    using (SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=test;Integrated Security=True;"))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand("Select * from table_2", conn))
        {
            using (SqlDataReader sqlReader = cmd.ExecuteReader())
            {
                using (ReaderWrapper reader = new ReaderWrapper(sqlReader))
                {
                    using (OracleBulkCopy bulkCopy = new OracleBulkCopy("data source=oracle;user id=user;password=secret", OracleBulkCopyOptions.Default))
                    {
                        bulkCopy.DestinationTableName = "tb_date";
                        bulkCopy.WriteToServer(reader);
                    }
                }
            }
        }
    }
    

    包装器本身体积庞大,但非常简单:

        internal sealed class ReaderWrapper : IDataReader
    {
        #region Fields
    
        private bool _disposed;
    
        private IDataReader _reader;
    
        #endregion
    
        #region Constructors
    
        /// <summary>
        /// Initializes a new instance of the <see cref="ReaderWrapper"/> class.
        /// </summary>
        /// <param name="reader">The wrapped reader.</param>
        public ReaderWrapper(IDataReader reader)
        {
            this._reader = reader;
        }
    
        #endregion
    
        #region Properties
    
        /// <summary>
        /// Gets the number of columns in the current row.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// When not positioned in a valid recordset, 0; otherwise, the number of columns in the current record. The default is -1.
        /// </returns>
        public int FieldCount
        {
            get { return this._reader.FieldCount; }
        }
    
        #endregion
    
        #region Indexers
    
        /// <summary>
        /// Gets the column located at the specified index.
        /// </summary>
        /// <param name="i">The zero-based index of the column to get.</param>
        /// <returns>The column located at the specified index.</returns>
        /// <exception cref="System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="FieldCount"/>.</exception>
        public object this[int i]
        {
            get { return this.GetValue(i); }
        }
    
        /// <summary>
        /// Gets the column with the specified name.
        /// </summary>
        /// <param name="name">The name of the column to find.</param>
        /// <returns>The column with the specified name.</returns>
        /// <exception cref="System.IndexOutOfRangeException">No column with the specified name was found.</exception>
        public object this[string name]
        {
            get { return this._reader[name]; }
        }
    
        #endregion
    
        #region Methods
    
        /// <summary>
        /// Advances the <see cref="T:System.Data.IDataReader"/> to the next record.
        /// </summary>
        /// <returns>
        /// <see langword="true"/> if there are more rows; otherwise, <see langword="false"/>.
        /// </returns>
        public bool Read()
        {
            return this._reader.Read();
        }
    
        /// <summary>
        /// Return the value of the specified field.
        /// </summary>
        /// <param name="i">The index of the field to find.</param>
        /// <returns>
        /// The <see cref="T:System.Object"/> which will contain the field value upon return.
        /// </returns>
        /// <exception cref="T:System.IndexOutOfRangeException">
        /// The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>.
        /// </exception>
        public object GetValue(int i)
        {
            object sqlValue = this._reader[i];
            DateTimeOffset? dateValue = sqlValue as DateTimeOffset?;
            if (dateValue == null)
            {
                return sqlValue;
            }
    
            // Ensure that DateTimeOffset can be converted to Oracle
            OracleTimeStampTZ oracleDate = new OracleTimeStampTZ(dateValue.Value.UtcDateTime, dateValue.Value.Offset.ToString());
            return oracleDate;
        }
    
        /// <summary>
        /// Gets the <see cref="T:System.Type" /> information corresponding to the type of <see cref="T:System.Object" /> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)" />.
        /// </summary>
        /// <param name="i">The index of the field to find.</param>
        /// <returns>
        /// The <see cref="T:System.Type" /> information corresponding to the type of <see cref="T:System.Object" /> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)" />.
        /// </returns>
        /// <exception cref="NotSupportedException"></exception>
        Type IDataRecord.GetFieldType(int i)
        {
            return this._reader.GetFieldType(i);
        }
    
        public int GetOrdinal(string name)
        {
            return this._reader.GetOrdinal(name);
        }
    
        public bool IsDBNull(int i)
        {
            return this.IsDBNull(i);
        }
    
        /// <summary>
        /// Closes the <see cref="T:System.Data.IDataReader"/> Object.
        /// </summary>
        public void Close()
        {
            this._reader.Dispose();
        }
    
        /// <summary>
        /// Performs application-defined tasks associated with freeing, 
        /// releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (!this._disposed)
            {
                this._reader.Dispose();
                this._disposed = true;
            }
        }
    
        #endregion
    
        #region Not Implemented
    
        bool IDataReader.IsClosed
        {
            get { throw new NotSupportedException(); }
        }
    
        void IDataReader.Close()
        {
            throw new NotSupportedException();
        }
    
        int IDataReader.Depth
        {
            get { throw new NotSupportedException(); }
        }
    
        DataTable IDataReader.GetSchemaTable()
        {
            throw new NotSupportedException();
        }
    
        bool IDataReader.NextResult()
        {
            throw new NotSupportedException();
        }
    
        int IDataReader.RecordsAffected
        {
            get { throw new NotSupportedException(); }
        }
    
        bool IDataRecord.GetBoolean(int i)
        {
            throw new NotSupportedException();
        }
    
        byte IDataRecord.GetByte(int i)
        {
            throw new NotSupportedException();
        }
    
        long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
        {
            throw new NotSupportedException();
        }
    
        char IDataRecord.GetChar(int i)
        {
            throw new NotSupportedException();
        }
    
        long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
        {
            throw new NotSupportedException();
        }
    
        IDataReader IDataRecord.GetData(int i)
        {
            throw new NotSupportedException();
        }
    
        string IDataRecord.GetDataTypeName(int i)
        {
            throw new NotSupportedException();
        }
    
        DateTime IDataRecord.GetDateTime(int i)
        {
            throw new NotSupportedException();
        }
    
        decimal IDataRecord.GetDecimal(int i)
        {
            throw new NotSupportedException();
        }
    
        double IDataRecord.GetDouble(int i)
        {
            throw new NotSupportedException();
        }
    
        float IDataRecord.GetFloat(int i)
        {
            throw new NotSupportedException();
        }
    
        Guid IDataRecord.GetGuid(int i)
        {
            throw new NotSupportedException();
        }
    
        short IDataRecord.GetInt16(int i)
        {
            throw new NotSupportedException();
        }
    
        int IDataRecord.GetInt32(int i)
        {
            throw new NotSupportedException();
        }
    
        long IDataRecord.GetInt64(int i)
        {
            throw new NotSupportedException();
        }
    
        string IDataRecord.GetName(int i)
        {
            throw new NotSupportedException();
        }
    
        string IDataRecord.GetString(int i)
        {
            throw new NotSupportedException();
        }
    
        int IDataRecord.GetValues(object[] values)
        {
            throw new NotSupportedException();
        }
    
        #endregion
    

    实际转换在这里完成:

    public object GetValue(int i)
    {
        object sqlValue = this._reader[i];
        DateTimeOffset? dateValue = sqlValue as DateTimeOffset?;
        if (dateValue == null)
        {
            return sqlValue;
        }
    
        // Ensure that DateTimeOffset can be converted to Oracle
        OracleTimeStampTZ oracleDate = new OracleTimeStampTZ(dateValue.Value.UtcDateTime, dateValue.Value.Offset.ToString());
        return oracleDate;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多