【问题标题】:cx_Oracle.DatabaseError: ORA-00904: "DATETIME"."DATETIME": invalid identifiercx_Oracle.DatabaseError: ORA-00904: "DATETIME"."DATETIME": 标识符无效
【发布时间】:2019-03-19 01:26:04
【问题描述】:

我正在尝试使用 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')

我还没有真正找到复制的方法(没有将整个查询变成丑陋的字符串连接),我不确定我是否需要 - 一定有什么我错过了!

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

【问题讨论】:

    标签: sql oracle python-2.7 cx-oracle python-datetime


    【解决方案1】:

    我不知道你在做什么,但是 - 至于 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')
    

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

    【讨论】:

    • @a.pet 和上面的一样,确保使用绑定变量,这对于性能和安全原因至关重要。请参阅github.com/oracle/python-cx_Oracle/blob/master/samples/… 等示例您可以将绑定变量与to_date 一起使用,例如to_date(:bv, 'yyyy-mm-dd') 等。
    • @Littlefoot 非常感谢您注意到 .nextval 问题!太糟糕了,我现在才看到它(我最终在家里解决了它,但还没有更新问题),但简而言之 - 问题是表示为字符串的序列和为空的 值 - python 将它们写下来为无(显然),然后插入失败,因为 SQL 不知道什么是无。我最终也用 to_timestamp 替换了所有 datetime.datetime(我不得不使用正则表达式,因为它当时在一个字符串中我可以改变它),它现在工作正常。谢谢!
    【解决方案2】:

    SQL 错误:ORA-00904:“DATETIME”。“DATETIME”:标识符无效

    您收到此错误是因为 datetime.datetime 不是有效的 Oracle 语法。您大概知道这一点,因为您知道 Oracle SQL Developer 如何格式化时间戳。但是您不想复制显式的to_timestamp() 逻辑。

    我不清楚您从哪里获取 EVENT_DATE 的值,但鉴于这是一个审计功能,您可能需要的是 sysdate,这是一个 Oracle 内置函数,它为我们提供当前日期和时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      • 2022-01-22
      • 2011-08-27
      • 2011-04-21
      • 2019-06-29
      • 2013-10-20
      • 2017-12-29
      相关资源
      最近更新 更多