使用 seq 和触发器在 oracle 中自动增量 - 无效的 sql 语句

Autoincrement in oracle with seq and trigger - invalid sql statement

我是 oracle 的新手,来自 MySQL,我正在尝试使用序列和触发器让自动增量在 Oracle 中工作,以便每次我这样做时它都会将我的字段递增 1插入。

CREATE SEQUENCE proposals_seq MINVALUE 1 
START WITH 1 INCREMENT BY 1 CACHE 10;

CREATE OR REPLACE TRIGGER proposals_before_insert
BEFORE INSERT
   ON proposals
   FOR EACH ROW
BEGIN
    SELECT proposals_seq.nextval INTO :new.proposal_id FROM dual;
END;

但是当我 运行 脚本时,出现错误:

Error code 900, SQL state 42000: ORA-00900: invalid SQL statement

如果我去掉“;”在 select 语句之后,我没有得到任何错误,直到我尝试将数据插入 table,然后我得到这个错误:

INSERT INTO proposals (target_audience, line_of_business, activity_description, cost, comments, objectives_and_results) 
    VALUES ('test', 'test', 'test', 15, 'test', 'test');

Error code 4098, SQL state 42000: ORA-04098: trigger 'PROPOSALS_BEFORE_INSERT' is invalid and failed re-validation

我正在使用这个版本的 Oracle: Oracle 数据库 11g 企业版 11.2.0.1.0 版 - 64 位生产

我找到的所有关于它的文章,似乎都是这样做的,并且在这里也有答案:How to create id with AUTO_INCREMENT on Oracle?

会不会是我的Oracle版本问题?我还有另一种方法可以自动增加吗?或者我必须用 sql 中的序列手动递增吗?

我的 table 看起来像这样:

CREATE TABLE proposals (
    proposal_id INT NOT NULL,
    target_audience VARCHAR2(50) NOT NULL,
    line_of_business VARCHAR2(50),
    activity_description VARCHAR2(250) NOT NULL,
    cost DECIMAL(19, 4) NOT NULL,
    comments VARCHAR2(250),
    objectives_and_results VARCHAR2(250),
    PRIMARY KEY (proposal_id)
);

这是我使用的适合您 table 的代码。它适用于任何 Oracle 版本,但不利用 12 中的新功能将序列设置为自动递增 id

CREATE OR REPLACE TRIGGER your_schema.proposal_Id_TRG BEFORE INSERT ON your_schema.proposal
FOR EACH ROW
BEGIN
  if inserting and :new.Proposal_Id is NULL then
  SELECT your_schema.proposal_Id_SEQ.nextval into :new.Proposal_Id FROM DUAL;
  end if;

END;
/

用法是

INSERT INTO proposals (proposal_id,target_audience, line_of_business, activity_description, cost, comments, objectives_and_results) 
    VALUES (null,'test', 'test', 'test', 15, 'test', 'test');

请注意,我们故意将 null 插入主键以启动触发器。

我怀疑问题是您的客户端工具读取每个分号作为命令的结尾,导致 PL/SQL 代码(需要分号作为语句终止符)错误地传输到服务器。

删除分号后,语句会正确发送到服务器,但最终会得到一个无效对象,因为 PL/SQL 不正确。

我在 SQL Fiddle 上重复了你的问题。然后我将语句终止符更改为 / 而不是 ; 并将代码更改为使用斜杠来执行每个语句,并且它没有错误地工作:

CREATE TABLE proposals (
    proposal_id INT NOT NULL,
    target_audience VARCHAR2(50) NOT NULL,
    line_of_business VARCHAR2(50),
    activity_description VARCHAR2(250) NOT NULL,
    cost NUMBER(19, 4),
    comments VARCHAR2(250),
    objectives_and_results VARCHAR2(250),
    PRIMARY KEY (proposal_id)
)
/

CREATE SEQUENCE proposals_seq MINVALUE 1 
START WITH 1 INCREMENT BY 1 CACHE 10
/

CREATE OR REPLACE TRIGGER proposals_before_insert
BEFORE INSERT ON proposals FOR EACH ROW
BEGIN
    select proposals_seq.nextval into :new.proposal_id from dual;
END;
/

我在 Oracle 中为 table 创建了 SEQUENCE 和触发器。

我的实体:

@Entity
@Table(name = "TBL_AUTHENTICATE")
public class UserSession implements Serializable {
    @Id
    @Column(name = "SESSIONID", nullable = false, length = 12)
    private Long sessionId;

    @Column(name = "USER_ID", nullable = false, length = 10)
    private int user_id;

    @Column(name = "TIME_TO_LIVE", nullable = false)
    private Date time_to_live;

:-D
我尝试在此 table 中插入数据并使用我生成的值设置 sessionId ,最后我明白了这个问题。那是我的错。

然后我从 table 中删除序列和触发器。
我的问题解决了。