首页 > 解决方案 > cx_Oracle.DatabaseError: ORA-00904: "DATETIME"."DATETIME": 标识符无效

问题描述

我正在尝试使用 Python 的 cx_Oracle 导出 Oracle 数据库。我连接到数据库,查询我需要的所有行,然后用它们构建一个 INSERT 语句。我正在使用与此类似的代码:

table_name = "AUDIT"
where_clause = "id > 10"
query = "SELECT * FROM " + table_name + " WHERE " + where_clause
curs = db_conn.cursor()
curs.execute(query)
res = curs.fetchall()
columns = []
for i in range(0, len(curs.description)):
    columns.append(curs.description[i][0])
column_names = ",".join(columns)
statement = "INSERT INTO %s (%s) VALUES %s" % (table_name, column_names, row)
print statement

类型是 NUMBER、VARCHAR2、DATE、NUMBER,我得到一个看起来不错的插入语句...除了日期字段:

INSERT INTO AUDIT_LOG (LOG_DBID,USER_NAME,EVENT_DATE,SEVERITY) VALUES ('AUDIT_LOG_SQ.nextval', 'user@do',datetime.datetime(2018, 4, 28, 1, 57, 42), '1')

当我尝试执行此操作时,无论是通过 sqlplus 还是相同的游标,我都会收到以下错误:

Error starting at line 1 in command:
INSERT INTO AUDIT_LOG (LOG_DBID,USER_NAME,EVENT_DATE,SEVERITY) VALUES ('AUDIT_LOG_SQ.nextval', 'SYSTEM@do',datetime.datetime(2018, 4, 28, 1, 57, 42), '1')
Error at Command Line:1 Column:95
Error report:
SQL Error: ORA-00904: "DATETIME"."DATETIME": invalid identifier
00904. 00000 -  "%s: invalid identifier"

如果没有 datetime 元素,查询就可以正常工作。 如何插入从游标获得的结果?

我检查了 SQL_Developer 导出以与我的比较,他们有不同的处理方式:

INSERT INTO AUDIT_LOG (LOG_DBID,USER_NAME,EVENT_DATE,SEVERITY) VALUES ('AUDIT_LOG_SQ.nextval', 'user@do',to_timestamp('25-APR-18','DD-MON-RR HH.MI.SSXFF AM'), '1')

我还没有真正找到复制的方法(没有将整个查询变成丑陋的字符串连接),而且我不确定我是否需要 - 一定有我遗漏的东西!

任何帮助将不胜感激,谢谢!

标签: sqloraclepython-2.7cx-oraclepython-datetime

解决方案


我不知道你在做什么,但是 - 至于 5 小时没有答案,让我说一两句话。

这是一个失败的声明:

INSERT INTO AUDIT_LOG (LOG_DBID,USER_NAME,EVENT_DATE,SEVERITY) VALUES 
('AUDIT_LOG_SQ.nextval', 'SYSTEM@do',datetime.datetime(2018, 4, 28, 1, 57, 42), '1')

你期望datetime.datetime成为什么?对我(以及大概是 Oracle)来说,看起来好像有datetime一个名为(第一个,在点前面)的用户,它有一个名为datetime(第二个,在点后面)的函数。很可能这两个都不是真的,是吗?

我建议您尝试使用 TO_DATE 函数,该函数将接受两个参数:日期(和时间)和适当的格式掩码,例如

to_date('2018-04-28 01:57:42', 'yyyy-mm-dd hh24:mi:ss')

你会用它而不是你的datetime构造。

但是,我担心——即使你这样做了——INSERT可能会因为你插入的第一个值而再次失败。

LOG_DBID看起来像IDNUMBER数据类型);是吗?INSERT你写的是试图在其中插入一个字符串 - 因为你把它括在单引号中:'audit_log_sq.nextval'. AUDIT_LOG_SQ是一个序列名称。所以,如果你想在该列中插入一个数值,你应该省略单引号。

最后,可能有效的语句(至少在 Oracle 本身中)如下所示:

INSERT INTO AUDIT_LOG (LOG_DBID,USER_NAME,EVENT_DATE,SEVERITY) VALUES 
(AUDIT_LOG_SQ.nextval, 
 'SYSTEM@do', 
  to_date('2018-04-28 01:57:42', 'yyyy-mm-dd hh24:mi:ss'), 
 '1')

我希望它是有道理的,即使在你的上下文中。


推荐阅读