【问题标题】:newline charter \n gives "java.sql.SQLException: ORA-00911: invalid character\n" Oracle 11g换行符 \n 给出“java.sql.SQLException: ORA-00911: invalid character\n” Oracle 11g
【发布时间】:2014-01-03 15:26:20
【问题描述】:

我有 Oracle DB 11g 企业版,我想通过从文件中读取 sql 脚本来创建表。通过 java 代码,我正在从文件中读取以下 sql 脚本并将其存储在 String sqlBlock 中:

CREATE SEQUENCE VerHist_SeqNum
   START WITH 1 
   INCREMENT BY 1;
CREATE TABLE VerHist
(
  SequenceNumber NUMBER(10,0)  NOT NULL,
  SQLFileName VARCHAR2(100)  NOT NULL,
  STATUS VARCHAR2(10)  NOT NULL,
  AppliedDate DATE  NOT NULL,
  DateCreated DATE 
   DEFAULT (SYSDATE),
  DateUpdated DATE 
   DEFAULT (SYSDATE),
  CONSTRAINT PK_VerHist PRIMARY KEY( SequenceNumber ),
  CONSTRAINT UC_VerHist_SQLFileNa UNIQUE( SQLFileName )
);
CREATE OR REPLACE TRIGGER VerHist_SeqNum_TRG
   BEFORE INSERT 
   ON VerHist
   FOR EACH ROW
   BEGIN
      SELECT VerHist_SeqNum.NEXTVAL INTO :NEW.SequenceNumber
        FROM DUAL;
   END;

当我执行这个查询时,它给出了

java.sql.SQLException: ORA-00911: 无效字符\n 在 oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) 在 oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) 在 oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) 在 oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:743) 在 oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:207) 在 oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:946) 在 oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1168) 在 oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1687) 在 oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1653)

以下是我执行 sql 块的代码:

Statement stmt = conn.createStatement();
String sqlBlock = //"this contains the content of the file (it contains \n charters)";
stmt.execute(sqlBlock);

这里的换行章程是否无效,如果是,否则如何使它工作?

请注意,当我复制粘贴此文件的内容并通过 Oracle SQL Developer 运行脚本时,它运行良好。

【问题讨论】:

  • 为什么你有\n个字符?删除它们...
  • 尝试使用转义字符表示 \\n 代替 \n
  • 我尝试用单个空格替换\n,也尝试用\\n 代替\n,但仍然收到相同的错误消息。
  • 那么请贴出那个sql-block的原始代码

标签: java sql oracle jdbc oracle11g


【解决方案1】:

当您将文件的包含内容复制粘贴到浏览器时。浏览器会将 \n 视为新行。 而代码 /n 只是字符。 尝试用单个空格替换 \n 然后运行它会工作

【讨论】:

  • 我尝试用单个空格替换 \n,但仍然收到相同的错误消息。
  • @John 您能否添加解释您如何阅读文件的代码
【解决方案2】:

sqlBlock = sqlBlock.replaceAll("\n"," ");

从查询中删除 \n。如果要在sql developer中格式化查询,可以选择查询并按Ctrl+F7

【讨论】:

  • 你能粘贴整个语句而不是String sqlBlock = //"this contains the content of the file (it contains \n charters)";
【解决方案3】:

我认为\n 引用是一个红鲱鱼,并且是如何记录错误的人工制品。您正尝试在一个execute 中运行两条SQL 语句,用分号分隔。这是不允许的。分号是 SQL*Plus 中的语句分隔符,而不是 SQL,即使使用单个语句也会生成 ORA-00911。而execute 必须是单个语句。

如果您正在执行 DML,您可以将语句包装在 PL/SQL 块中并执行它,但由于这是 DDL,除非您使用动态 SQL,否则您无法执行此操作,这将过于复杂和混乱对于你正在尝试做的事情。

您需要将每个语句放在一个单独的文件中(create sequence 上没有尾随分号;您仍然需要在create trigger 上使用它,因为它正在结束触发器的 PL/SQL 块,而不是充当一个语句分隔符 - 令人困惑,我知道),并分别阅读和执行它们。然后每个execute 都有一个声明,会更快乐。


顺便说一句,您不需要在 11g 中将序列值选择到变量中; you can now do it like this:

CREATE OR REPLACE TRIGGER VerHist_SeqNum_TRG
BEFORE INSERT 
ON VerHist
FOR EACH ROW
BEGIN
  :NEW.SequenceNumber := VerHist_SeqNum.NEXTVAL;
END;

【讨论】:

  • 感谢 Alex,您的解决方案有效 +1。请原谅我缺乏对 Oracle 和 SQL 的一般知识,您能否让我知道根据您对 11g 中变量的最后建议,我的 sql 语句将如何变化。
  • 这里的分号是:NEW.SequenceNumber := VerHist_SeqNum.NEXTVAL;optional吗?我可以删除它吗?问这个是因为我已经更改了我的 java 代码以认为 SQL 语句以分号结尾。
  • @John - 不,它不是可选的,END 之后的那个也不是可选的。 BEGIN/END 是一个 PL/SQL 块,它本身可以包含多个分号分隔的语句,并且该块必须以分号结束。在那个不是语句分隔符的上下文中。这……令人困惑。对于驱动程序,从CREATEEND; 的所有内容都是一个声明。省略create sequence 文件中的分号可能会更好,而不是尝试让Java 弄清楚何时删除它。文件中的代码仍将在 SQL Developer 中运行。
  • 哦,所以如果我想将所有 SQL 语句保存在一个文件中,那么如果不是分号,可以用什么作为这些 SQL 语句的分隔符?
  • 所以您可以将一个文件加载到 Java 中,然后将其拆分为语句?我会使用/,它仍然可以在 SQL Developer (or SQL*Plus) 中使用。将文件解析为语句可能会在某些时候让您头疼,例如如果文件中有 cmets (/* ... */)。我认为,如果在 Java 中进行更多工作,单独的文件会更易于管理。
猜你喜欢
  • 2023-03-20
  • 2020-11-10
  • 1970-01-01
  • 2014-06-20
  • 2017-06-10
  • 1970-01-01
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多