在SQL中创建唯一的字符串/数字

时间:2017-04-16 01:49:54

标签: mysql sql

我有一个表格someTable,其中包含bin类型的列VARCHAR(4)。每当我插入此表时,bin应该是字符和数字的唯一组合。在这个意义上的独特意义并没有出现在另一行的表格中。

bin采用AA00的形式,其中A是字符A-F,0是数字0-9。

假设我向该表插入一次:它应该出现bin值,之前不会出现。假设该表为空,则第一个bin可能为AA11。在第二次插入时,它应该是AA12,然后是AA13等等。

AA00, AA01, ... AA09, AA10, AA11, ... AA99, AB00, AB01, ... AF99, BA00, BA01, ... FF99

这个表只能包含3,600个可能的行并不重要。如何创建此代码,专门查找bin中尚未存在的someTable?它可以按照我所描述的顺序或随机bin,只要它不会出现两次。

CREATE TABLE someTable (
    bin VARCHAR(4),
    someText VARCHAR(32),
    PRIMARY KEY(bin)
);

INSERT INTO someTable
    VALUES('?', 'a');
INSERT INTO someTable
    VALUES('?', 'b');
INSERT INTO someTable
    VALUES('?', 'c');
INSERT INTO someTable
    VALUES('?', 'd');

或者,我可以使用以下程序代替:

CREATE PROCEDURE insert_someTable(tsomeText VARCHAR(32))
    BEGIN
    DECLARE var (VARCHAR(4) DEFAULT (
        -- some code to find unique bin
    );
    INSERT INTO someTable
        VALUES(var, tsomeText);
    END

可能的结果是:

+------+----------+
|  bin | someText |
+------+----------+
| AB31 |    a     |
| FC10 |    b     |
| BB22 |    c     |
| AF92 |    d     |
+------+----------+

1 个答案:

答案 0 :(得分:1)

正如戈登所说,你必须使用一个触发器,因为它太复杂了,不能作为默认的简单公式。应该相当简单,您只需获取最后一个值(按降序排序,限制1)并递增它。由于字母字符的原因,编写增量器会有些复杂。在应用程序语言中会更容易,但是你会遇到表锁定问题以及两个用户创建相同值的可能性。

更好的方法是使用普通的自动增量主键并将其转换为二进制值。将bin值视为两个基数为6的字符,后跟两个基数为10的值。然后你获取MySQL生成的id,它保证是唯一的并转换为你的特殊号码系统。计算bin并将其存储在bin列中。

计算垃圾箱:

  1. 第一步是获得十进制数的较低100值(mod 100) - 它给出最后两位数字。转换为带前导零的varchar。
  2. 从id中减去该值,然后除以100得到前两位的值。
  3. 获取mod 6值以确定第3个(从右侧)数字。按索引转换为A-F.
  4. 从ID的左边减去这个,然后除以6得到第4个(从右边)数字。按索引转换为A-F.
  5. 将三个结果合并在一起,形成bin的值。
  6. 您可能需要编辑以下内容以匹配您的表名和列名,但它应该是您所要求的。一个可能的改进是取消任何超过3600限制的插入。如果插入第3600条记录,它将复制以前的bin值。此外,它不会插入AA00(id = 1 =' AA01'),因此它并不完美。最后,您可以在bin上放置一个唯一索引,这样可以防止重复。

    DELIMITER $$
    
    CREATE TRIGGER `fix_bin` 
    BEFORE INSERT ON `so_temp`
    FOR EACH ROW
    BEGIN
        DECLARE next_id INT;
        SET next_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='so_temp');
        SET @id = next_id;
        SET @Part1 = MOD(@id,100);
        SET @Temp1 = FLOOR((@id - @Part1) / 100);
        SET @Part2 = MOD(@Temp1,6);
        SET @Temp2 = FLOOR((@Temp1 - @Part2) / 6);
        SET @Part3 = MOD(@Temp2,6);
    
        SET @DIGIT12 = RIGHT(CONCAT("00",@Part1),2);
        SET @DIGIT3 = SUBSTR("ABCDEF",@Part2 + 1,1);
        SET @DIGIT4 = SUBSTR("ABCDEF",@Part3 + 1,1);
        SET NEW.`bin` = CONCAT(@DIGIT4,@DIGIT3,@DIGIT12);
    END;
    $$
    
    DELIMITER ;