【发布时间】:2016-10-21 21:04:42
【问题描述】:
所以我正在做一个将数据从 sql server db 移动到 oracle db 的项目,日期让我很难过。为了进行数据移动,我有一个 python 脚本,它从 sql server db 中提取数据,然后运行插入查询。
问题是日期看起来像这样2016-06-01 05:45:06.003,但如果我去掉小数秒,它将违反主键,因为2016-06-01 05:45:06 有很多记录,但2016-06-01 05:45:06.003 只有一个记录,所以它必须有毫秒在里面。
我应该提到oracle中列的数据类型是TIMESTAMP
如果我只是提取记录并运行我的插入,这只是一个基本插入,其值类似于 VALUES(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15)
这样做会让我的约会看起来像这样01-JUN-16 07.05.41.000000000 AM。这很好,但对于每条记录,小数秒都是 000000,所以我失去了准确性,这让我违反了主键。
我认为解决方法是明确说明格式,因此我将插入语句值子句修改为 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)。这更糟糕,因为它将每行中的所有日期更改为16-JUN-20 12.00.00.000000000 AM 我也尝试了YYYY-MM-DD HH24:MI:SS,FF9,但这会产生相同的结果。
我确信这是我想念的愚蠢的东西,但对于我的生活,我不知道它是什么。
既然被问到,sql server 表上列的数据类型是DateTime,而在 oracle 服务器上,我目前将其设置为TimeStamp(3),但我可以在 oracle 端更改数据类型。
我正在使用 cx_oracle 连接并运行插入。我可以确认在插入运行之前数据确实有毫秒。
蟒蛇:
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()
【问题讨论】:
-
从基础开始——你检查过Python脚本检索到的数据有毫秒级的数据吗? Python 脚本是将值存储为字符串值还是时间戳?
-
这与 SQL Server 或 Oracle 几乎没有关系,尽管像这样使用时间戳作为主键不是一个好主意。在任何情况下,日期都没有格式,它们是二进制值。如果您不将它们转换为文本并使用参数化查询,则可以将值从一个数据库按原样传递到另一个数据库。你用的是什么库?
-
我完全清楚这不是一个好主意。但是,我是一个低级的合作社,他们不想改变它。不过,该键确实有其他列。
-
@user5999614 发布代码!没有它,您就是在要求人们猜测!如果源数据有毫秒,而目标字段接受毫秒,则问题出在脚本中
-
来自这个Oracle article
Fractional seconds of a date/time value passed as a bind variable will be truncated unless the setinputsizes() method is used between prepare() and execute()。
标签: python sql-server oracle cx-oracle