【问题标题】:How to create ID number without duplication如何创建不重复的身份证号码
【发布时间】:2023-04-03 03:00:01
【问题描述】:

我有一个名为 Student 的表,其中包含以下列:

First name 
Last name
Class ID
Class 

我想为学生创建一个 ID,我尝试使用 Row_number Over Partiton,但我似乎没有得到想要的东西,但更多的是自行重置,这是我想要得到的结果。

First Last   Class    ClasID  ID (outcome looking for)
------------------------------------
John  Brown  Math     M21     ID01
John  Brown  English  E31     ID01
Tom   Bank   Math     M21     ID02
John  Brown  Gym      G41     ID01
Tim   Brown  English  E31     ID03

【问题讨论】:

  • 首先不应该将该表称为Student。应该有三个表:Student(每个学生一行,每个学生的个人数据,包括一个student_id),Class(每个班级一行,每个班级的特征,包括一个class_id) ,还有一张像你说明的那样的表格,可能称为Student_Class,仅列出(student_id, class_id) 的对,以显示每个学生注册的课程。所以,问题:这是你想出的吗?这是你班上的作业吗?
  • 如果是作业,我会告诉老师这不是一个好的数据模型,不应该鼓励我们学习糟糕的数据模型。如果这是您想出的,您可能需要重新考虑您的方法。

标签: sql oracle window-functions


【解决方案1】:

使用dense_rank():

select t.*, dense_rank() over(order by last, first) as id
from student

这会将相同的id 分配给名字和姓氏相同的行。

如果你真的想要像IDnn 这样的格式(在我看来这没有多大意义),那么你可以格式化和连接:

select t.*, 
    'ID' || to_char(dense_rank() over(order by last, first), '09') as id
from student

如果有超过 99 个不同的学生,这将无法生成正确的字符串。

【讨论】:

    【解决方案2】:

    @GMB 提供的 dense_rank 解决方案会生成一个“id”作为给定结果集的一部分,而不是作为给定学生的固有标识符。将 ID 永久分配给实体(学生、员工、班级等)的经典方法是创建一个 SEQUENCE,然后创建一个 on_insert TRIGGER 以使用序列的 next_value 填充 ID 列。

    SQL> CREATE TABLE STUDENTS
      2  (
      3    STUDENT_ID NUMBER NOT NULL
      4  , FIRST_NAME VARCHAR2(20)
      5  , LAST_NAME VARCHAR2(20)
      6  , CONSTRAINT STUDENTS_PK PRIMARY KEY
      7    (
      8      STUDENT_ID
      9    )
     10    ENABLE
     11  );
    
    Table created.
    
    Elapsed: 00:00:00.05
    SQL> --
    SQL> CREATE SEQUENCE id_seq
      2   START WITH     1
      3   INCREMENT BY   1
      4  ;
    
    Sequence created.
    
    Elapsed: 00:00:00.01
    SQL> CREATE OR REPLACE TRIGGER STUDENTS_TRIG
      2  BEFORE INSERT ON students
      3  FOR EACH ROW
      4  BEGIN
      5    :new.student_ID := ID_SEQ.NEXTVAL;
      6  END;
      7  /
    
    Trigger created.
    
    Elapsed: 00:00:00.02
    
    SQL> show errors
    No errors.
    SQL> --
    SQL> insert into students (first_name,
      2                        last_name)
      3              values ('Ed',
      4                      'Stevens'
      5                     )
      6  ;
    
    1 row created.
    
    Elapsed: 00:00:00.18
    SQL> commit;
    
    Commit complete.
    
    Elapsed: 00:00:00.01
    SQL> select * from students;
    
    STUDENT_ID FIRST_NAME           LAST_NAME
    ---------- -------------------- --------------------
             1 Ed                   Stevens
    
    1 row selected.
    
    Elapsed: 00:00:00.07
    SQL> --
    SQL> drop trigger students_trig;
    
    Trigger dropped.
    
    Elapsed: 00:00:00.02
    SQL> drop table students purge;
    
    Table dropped.
    
    Elapsed: 00:00:00.05
    SQL> drop sequence id_seq;
    
    Sequence dropped.
    
    Elapsed: 00:00:00.01
    

    从版本 12 开始,您不必创建序列或触发器,只需将 ID 列声明为“身份”列。我把它留给学生研究这个概念的练习。

    【讨论】:

      猜你喜欢
      • 2020-07-11
      • 1970-01-01
      • 2019-03-11
      • 2019-09-16
      • 2016-04-21
      • 1970-01-01
      • 2020-01-28
      • 1970-01-01
      • 2019-10-10
      相关资源
      最近更新 更多