如何用最少SQL语句将自动递增customer_id按指定格式写入first_name列?
解决方案
方法1:用数据库触发器(推荐,全自动)
不管你是用Oracle 12c+的IDENTITY列实现自增,还是用传统的序列+触发器,都可以通过行级触发器在插入时自动生成first_name,全程只需要1条插入语句,完全不用手动处理ID和更新。
如果你用的是12c+的IDENTITY列
先建表:
CREATE TABLE customers ( customer_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, first_name VARCHAR2(50) );
然后创建触发器:
CREATE OR REPLACE TRIGGER trg_customer_firstname BEFORE INSERT ON customers FOR EACH ROW BEGIN :NEW.first_name := 'NAME-' || :NEW.customer_id; END; /
之后插入数据只需要执行:
INSERT INTO customers DEFAULT VALUES;
触发器会自动把first_name设为NAME-加上刚生成的customer_id,完全不用额外操作。
如果你用的是11g及更早(序列+触发器实现自增)
先建序列:
CREATE SEQUENCE seq_customer_id START WITH 1 INCREMENT BY 1;
再建表:
CREATE TABLE customers ( customer_id NUMBER PRIMARY KEY, first_name VARCHAR2(50) );
可以把ID自增和first_name生成合并到一个触发器里:
CREATE OR REPLACE TRIGGER trg_customer_insert BEFORE INSERT ON customers FOR EACH ROW BEGIN SELECT seq_customer_id.NEXTVAL INTO :NEW.customer_id FROM DUAL; :NEW.first_name := 'NAME-' || :NEW.customer_id; END; /
插入时同样只需要一条语句:
INSERT INTO customers DEFAULT VALUES;
方法2:单条INSERT语句直接用序列值(不用触发器)
要是不想用触发器,也可以在插入时直接调用序列,一次完成两个列的赋值:
INSERT INTO customers (customer_id, first_name) VALUES (seq_customer_id.NEXTVAL, 'NAME-' || seq_customer_id.CURRVAL);
这里先用NEXTVAL拿到下一个序列值给customer_id,再用CURRVAL取当前序列值拼接成first_name,保证两者完全一致,全程一条语句搞定。
为啥比你原来的方案好
你之前的三步操作(插入→查ID→更新)不仅麻烦,在高并发场景下还可能出问题——比如你插入后还没更新,另一个会话又插了新数据,搞不好会更错ID。上面的两种方法都是原子性操作,不会有并发问题,而且语句量最少。
内容的提问来源于stack exchange,提问作者Johnyzhub
相关产品推荐
相关产品推荐

