序列生成的主键似乎不适用于 select 语句

Posted

技术标签:

【中文标题】序列生成的主键似乎不适用于 select 语句【英文标题】:sequence generated primary keys don't seem to work well with select statements 【发布时间】:2020-03-19 20:43:53 【问题描述】:

我正在尝试创建一个传输数据库。我已经在 Access 和 mysql 中完成了。现在我正在做 Oracle 和我完全不熟悉使用它。我遇到了序列生成字段的问题。或者至少我是这么认为的。你会在什么时候上船 你读了整本书。

这是我的 driverRecords 表的代码:

CREATE TABLE TRANSPORT_SCHEMA.driverRecords
(
    driverReg varchar2(15) PRIMARY KEY,
    driverIDNumber varchar2(10) UNIQUE,
    surname varchar2(15) NOT NULL,
    otherNames varchar2(30) NOT NULL,
    address varchar2(20),
    email varchar2(320) NOT NULL,
    DOB date NOT NULL,
    employmentDate date NOT NULL
);

这是drivingLicences 表的代码:

CREATE TABLE TRANSPORT_SCHEMA.drivingLicences
(
    licenceID varchar2(6) PRIMARY KEY,
    vehicleClass varchar2(15),
    issueDate date,
    expiryDate date,
    driverReg varchar2(15) UNIQUE,
    CONSTRAINT fk_driverReg FOREIGN KEY(driverReg) REFERENCES driverRecords(driverReg),
    CONSTRAINT Chk_vehicleClass CHECK(vehicleClass IN('A','B','C','D','E','F','G'))
);

所以我试图将记录插入到驾驶执照中。 drivingLicences 中的 driverReg 是 driverRecords 中 driverReg 的子键。这个想法 如果司机的记录不存在于 driverRecords 表中,那么司机不应该存在于drivingLicences 表中

这是我用来插入的代码;

insert into drivingLicences VALUES('123456', 'D', '12-12-2019','12-12-2020', 'DRV/1003/2020');

这是返回的错误:

ORA-02291: integrity constraint (TRANSPORT_SCHEMA.FK_DRIVERREG) violated - parent key not found

现在我完全明白错误是由违反完整性约束引起的......但问题是......我实际上有一个驱动程序 注册号DRV/1003/2020在我的记录中

我的司机注册号由这个序列生成并触发:

顺序:

CREATE SEQUENCE driverNumberSequence
    START WITH 1000
    INCREMENT BY 1
    NOCACHE
    NOCYCLE;

触发器:

CREATE OR REPLACE TRIGGER regNumberGenerator BEFORE 
INSERT ON driverRecords
FOR EACH ROW

    DECLARE
        prefix char(3) := 'DRV';
        driverNumber char(4);
        postfix char(4);
        generatedDriverNumber char(15);

    BEGIN
        SELECT TO_CHAR(SYSDATE, 'YYYY') INTO postfix FROM sys.dual;
        SELECT TO_CHAR(driverNumberSequence.nextval) INTO driverNumber FROM dual;
        generatedDriverNumber:= prefix || '/' || driverNumber || '/' || postfix;
        SELECT TO_CHAR(generatedDriverNumber) INTO :NEW.driverReg FROM dual;
        DBMS_OUTPUT.PUT_LINE('Driver Reg Number generated:' || generatedDriverNumber);
    END;

我尝试执行两个 select 语句来找出问题所在:

1)SELECT * FROM DRIVERRECORDS where DRIVERREG = 'DRV/1001/2020';

这个返回 0 行

2)SELECT * FROM DRIVERRECORDS where DRIVERREG LIKE 'DRV/1001/2020%';

这个实际上返回了一个结果

我不知道我做错了什么。但我认为这与我的 driverReg 信息的保存方式有关。任何帮助将不胜感激

如果有帮助,这里是我保存的所有司机注册号:

SELECT driverReg FROM driverRecords;

*DRV/1001/2020
DRV/1002/2020
DRV/1003/2020
DRV/1004/2020
DRV/1005/2020*

简而言之,我需要知道原因:

a) select 语句适用于LIKE '%' 而不适用于= ''

b) 即使我没有违反完整性约束,我也无法进行插入

【问题讨论】:

【参考方案1】:

generatedDriverNumber 在您的触发器中被定义为char(15) - 一个长度为 15 的 固定长度 字符字段。由于您用一个短得多的值填充它,它会将其填充到全长为 15。这解释了为什么在值的开头使用 like 查询有效,但使用 = 查询无效。

长话短说,将定义更改为varchar2,您应该没问题:

generatedDriverNumber varchar2(15);

【讨论】:

另外,无需在触发器中执行“select ... into”语句。只需直接分配变量的值: postfix := TO_CHAR(SYSDATE, 'YYYY'); driverNumber := TO_CHAR(driverNumberSequence.nextval); NEW.driverReg := 前缀 || '/' ||司机编号 || '/' ||后缀;

以上是关于序列生成的主键似乎不适用于 select 语句的主要内容,如果未能解决你的问题,请参考以下文章

MSSql - 选择语句不适用于所有列

Hibernate 注解序列生成主键执行完select seq_t_user.nextval后不执行insert等语句导致 执行save()或update()方法无效

MyBatis 这小子是怎样拿到 insert 时生成的主键的?

Oracle数据库中序列(SEQUENCE)的用法详解

Oracle 反向主键

SQL - 如果存在不适用于 Select 语句?