sqlserver datetime to oracle timestamp Probleme

Also arbeite ich an einem Projekt, um data von einem SQL server db zu einem oracle db zu verschieben und die data geben mir eine harte time. Um databewegung zu machen, habe ich ein Python-Skript, das data aus dem SQL server db zieht und dann eine Insert-Abfrage ausführt.

Das Problem ist, dass die data aussehen wie dies ist 2016-06-01 05:45:06.003 aber wenn ich die Fraktions-Sekunden fallen, wird es den Primärschlüssel verletzen, da es viele datasätze bei 2016-06-01 05:45:06 aber gibt nur einer bei 2016-06-01 05:45:06.003 so muss es Millisekunden darin haben.

Ich sollte erwähnen, dass datatyp für die Spalte im oracle TIMESTAMP ist

Wenn ich gerade die Aufzeichnungen ziehe und meine Einfügung ausführe, die nur ein Grundeinsatz ist mit den Werten wie diese VALUES(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15)

Das macht mir Termine, die so aussehen 01-JUN-16 07.05.41.000000000 AM . Das wäre gut, aber für jeden einzelnen Rekord sind die Bruchteile Sekunden 000000, also habe ich die Genauigkeit verloren und das macht mich gegen den Primärschlüssel.

Ich dachte, das Update wäre, um explizit über das Format, so dass ich die Insert-statement Werte Klausel, um wie diese VALUES(TO_TIMESTAMP(:1, 'YYYY-MM-DD HH24:MI:SS,FF9'), :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15) . Dies ist noch schlimmer, da es alle data in jeder Zeile um 16-JUN-20 12.00.00.000000000 AM Ich habe auch versucht YYYY-MM-DD HH24:MI:SS,FF9 aber das ergibt die gleichen Ergebnisse.

Ich bin mir sicher, dass etwas Dummes, dass ich fehlt aber für das Leben von mir Ich weiß nicht, was es ist.

Da gefragt, Der datatyp der Spalte auf der SQL server-Tabelle ist DateTime und auf dem Oracle-server habe ich es derzeit auf TimeStamp(3) aber ich kann den datatyp auf der TimeStamp(3) ändern.

Ich benutze cx_oracle zu verbinden und führen Sie den deployment. Ich kann bestätigen, dass, bevor die Einfügung ausgeführt wird, die data Millisekunden haben.

Die Pythonschlange:

 def RunQuery(): srccrsr.execute(query) return srccrsr.fetchall() def RunQuery(): srccrsr.execute(query) return srccrsr.fetchall() def BuildBindList(recordsToWrite): closingRecords = [] for rec in recordsToWrite: closingRecords.append((rec[0], rec[1], rec[2], rec[3], rec[4], rec[5], rec[6], rec[7], rec[8], rec[9], rec[10], rec[11], rec[12], rec[13], rec[14])) return closingRecords def write_to_table(recordsToWrite): SQL = """INSERT INTO TRACE (DATETIME, ID, TZ, DOMAINID, EVENTNAME, REASONCODE, TARGETID, STATE, KEY, PERIPHERALKEY, RECOVERYKEY, DIRECTION, ROUTERDAY, ROUTERCKEY, ROUTERNUMBER) VALUES(TO_TIMESTAMP(TO_CHAR(:1), 'yyyy-mm-dd hh24:mi:ss.ff3'), :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15)""" try: trgtcrsr.prepare(SQL) except cx_Oracle.DatabaseError, exception: print ('Failed to prepare cursor') print Exception(exception) exit (1) try: trgtcrsr.executemany(None, recordsToWrite) except cx_Oracle.DatabaseError, exception: print ('Failed to insert rows') print Exception(exception) exit (1) trgtcnn.commit() trgtcnn.close() source_connection.close() def main(): recordstowrite = BuildBindList(RunQuery()) write_to_table(recordstowrite) if __name__ == "__main__": main() 

Dieser Oracle-Artikel warnt davor:

Fraktionale Sekunden eines dates / time-Wertes, der als Bindungsvariable übergeben wird, wird abgeschnitten, es sei denn, die setinputsizes () -Methode wird zwischen prepare () und execute ()

Das Beispiel des Artikels zeigt, dass zum memoryn von Millisekunden die Eingabegröße für den Parameter tval angegeben werden muss:

 ts = datetime.datetime.now() cursor.prepare("INSERT INTO python_tstamps VALUES(:t_val)") cursor.setinputsizes(t_val=cx_Oracle.TIMESTAMP) cursor.execute(None, {'t_val':ts}) db.commit() 

Es ist möglich, dass das, was Sie erleben, etwas mit Ihren nls Formateinstellungen zu tun ist. Allerdings sehe ich kein Problem mit der Verwendung von to_timestamp :

 with sample_data as (select '2016-06-01 05:45:06.003' col1 from dual union all select '2016-06-01 12:55:06.638' col1 from dual union all select '2016-06-02 11:53:24.827' col1 from dual) select col1, to_timestamp(col1, 'yyyy-mm-dd hh24:mi:ss.ff3') col1_ts, to_char(to_timestamp(col1, 'yyyy-mm-dd hh24:mi:ss.ff3'), 'yyyy-mm-dd hh24:mi:ss.ff3') col1_ts_str from sample_data; COL1 COL1_TS COL1_TS_STR ----------------------- -------------------------------------------------- ----------------------------- 2016-06-01 05:45:06.003 01/06/2016 05:45:06.003000000 2016-06-01 05:45:06.003 2016-06-01 12:55:06.638 01/06/2016 12:55:06.638000000 2016-06-01 12:55:06.638 2016-06-02 11:53:24.827 02/06/2016 11:53:24.827000000 2016-06-02 11:53:24.827 

(die Spalte col1_ts ist der timestempel, der von oracle gespeichert wird, der als String im Standardformat zurückgegeben wird (was bei verschiedenen Clients unterschiedlich sein kann, je nachdem, ob sie mit ihren nls-Formaten umgangen haben) und der col1_ts_str ist der timestempel als zurückgegeben eine characterfolge im spezifischen Format, die ich angefordert habe).

Sie sollten sicherstellen, dass die data korrekt eingegeben wurden, indem Sie ein to_char auf Ihrer timestempelspalte eingeben, zB

 select to_char(your_timestamp_column, '<format>') ts_col from your_table;