【问题标题】:Oracle SQL automatically create VARCHAR incremented PKOracle SQL 自动创建 VARCHAR 递增 PK
【发布时间】:2020-04-03 13:02:56
【问题描述】:

我正在尝试编写一个 Oracle SQL 表,以便每当插入一行时(通过 Oracle APEX 表单),PK 都会自动填充一个自动递增的 varchar 类型。例如。 TNT00000001, TNT00000002, TNT00000003...

 create table sample (
Tnt_ID CHAR(8) NOT NULL,
wtv NUMBER(3)
);

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

CREATE OR REPLACE TRIGGER sample_on_insert
  BEFORE INSERT ON sample
  FOR EACH ROW
BEGIN
  SELECT CONCAT('TNT', LPAD(Tnt_ID_Auto.nextval, 5, '0'))
  INTO :new.Tnt_ID
  FROM dual;
END;

当我尝试运行时:

INSERT INTO SAMPLE (wtv) VALUES (1);

我得到了错误

PLS-00103:遇到符号“INSERT”

【问题讨论】:

  • LPAD(Tnt_ID_Auto.nextval, 5, '0') 不会为您提供TNT00000001 btw 所需的零个数
  • 敢说你也可以将触发器简化为:new.Tnt_ID := CONCAT('TNT', LPAD(Tnt_ID_Auto.nextval, 8, '0'));
  • 脚本中的 INSERT 上方是什么?
  • 我不确定你的意思。插入语句之前的代码是从创建表到结束的东西
  • 基本上the same as this - 缺少一个斜线。

标签: sql oracle


【解决方案1】:

这是 IDENTITYVIRTUAL 列的一个很好的用例。因此,不需要额外的 SEQUENCETRIGGER

演示:

CREATE TABLE sample (
    serial_no NUMBER GENERATED ALWAYS AS IDENTITY,
    tnt_id GENERATED ALWAYS AS (CONCAT('TNT', LPAD(serial_no, 5, '0'))) VIRTUAL,
    wtv    NUMBER(3)
);

insert into sample (wtv) values(100);
insert into sample (wtv) values(200);
insert into sample (wtv) values(300);

结果:

select * from sample;

 SERIAL_NO TNT_ID                         WTV
---------- ----------------------- ----------
         1 TNT00001                       100
         2 TNT00002                       200
         3 TNT00003                       300

它是如何工作的:

  1. NUMBER GENERATED ALWAYS AS IDENTITY:这会自动为您创建所需的序列,从 1 开始,默认以 1 递增。
  2. GENERATED ALWAYS AS VIRTUAL:这将创建一个虚拟列,其值是使用其他列值自动计算的。在此演示中,它使用标识列。
  3. LPAD:这将确保在增加列值时填充零,但也会确保在增加数字时不会增加字符串的长度。
  4. CONCAT:这会将TNT 连接到上述值。

【讨论】:

    【解决方案2】:

    如果您想知道您的查询出了什么问题,它缺少/

    create table sample (
    Tnt_ID CHAR(8) NOT NULL,
    wtv NUMBER(3)
    );
    
    CREATE SEQUENCE Tnt_ID_Auto 
     MINVALUE 1  START WITH 1 INCREMENT BY 1  CACHE 10;
    
    CREATE OR REPLACE TRIGGER sample_on_insert
      BEFORE INSERT ON sample
      FOR EACH ROW
    BEGIN
      SELECT CONCAT('TNT', LPAD(Tnt_ID_Auto.nextval, 5, '0'))
      INTO :new.Tnt_ID
      FROM dual;
    END;
    / -- this needs here
    
    INSERT INTO SAMPLE (wtv) VALUES (1);
    

    PL/SQL 代码必须以/ 结尾,然后才能开始它下面的另一个代码。

    【讨论】:

    • 我试过了,但没用。我有这样的错误:PLS-00103:遇到符号“/”
    • @Alioz - 它必须是它自己的斜线,一些客户端(SQL Developer 将抛出 PLS-00103;SQL*Plus 认为语句尚未结束......)所以删除评论“--这里需要”,如果你逐字包含的话。
    • 除非万不得已,否则避免使用触发器。
    猜你喜欢
    • 2020-07-22
    • 2012-01-13
    • 2014-05-25
    • 2013-12-01
    • 2015-11-03
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    相关资源
    最近更新 更多