MYSQL 表创建,其中列具有默认值(表达式)

发布于 2024-10-20 23:58:34 字数 401 浏览 1 评论 0原文

我有一个表 Employee(id,name,dept_name)。我希望 id 为字母数字 [dddddaaaaa],前 5 位数字将自动递增 id,其余 4 个字符将是员工姓名的前 4 个字符。

例如,对于第一个员工 name=John Todd ,Id 的自动递增部分将为 00001。因此 Id 将为00001JOHN

是否可以为列 Id=(concat(autoincrement,substring(name,4)) 设置默认表达式。

我还在想是否可以在插入 Employee 和触发器后创建触发器 MySql 不允许从触发的触发器更新同一个表。

将更新Employee.Id,但

I have a Table Employee(id,name,dept_name).I want the id will alphanumeric [dddddaaaaa] with first 5 digit will be auto increment id and rest 4 char will be the first 4 char of employee name.

For example , for the first employee name=John Todd ,the auto incremented part of the Id will be 00001. And so the Id will be 00001JOHN.

Is it possible to set a default expression to the column Id=(concat(autoincrement,substring(name,4)).

I was also thinking if I Can create a trigger on after insert Employee and the trigger will update the Employee.Id. But MySql does not allow to update the same table from trigger for which trigger got fired.

Please Help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

优雅的叶子 2024-10-27 23:58:34

像这样的模式怎么样?

CREATE TABLE employee
(
employeeid INT PRIMARY KEY AUTO_INCREMENT,
firstname varchar(255)
);

CREATE INDEX part_of_firstname ON employee (firstname(4));

这将允许您使用自然主键相当快速地执行查找,同时为您提供人工主键并且不强制非规范化。

EXPLAIN SELECT * FROM EMPLOYEE WHERE EMPLOYEEID = 1 AND FIRSTNAME LIKE 'john%';

+----+-------------+----------+-------+---------------------------+---------+---------+-------+------+-------+
| id | select_type | table    | type  | possible_keys             | key     | key_len | ref   | rows | Extra |
+----+-------------+----------+-------+---------------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | employee | const | PRIMARY,part_of_firstname | PRIMARY | 4       | const |    1 |       |
+----+-------------+----------+-------+---------------------------+---------+---------+-------+------+-------+

当然,由于主键的 0001 部分足够唯一来识别用户,因此您根本不需要查询名称。

如果您坚持预先计算,这应该可以进行

CREATE TABLE employee
(
employeeid INT PRIMARY KEY AUTO_INCREMENT,
specialid VARCHAR(255),
firstname VARCHAR(255)
);

CREATE INDEX employee_specialid ON employee (firstname(4));

DELIMITER ;;
CREATE TRIGGER employeeid_trigger BEFORE insert ON employee
FOR EACH ROW
BEGIN
SET new.specialid = CONCAT(LPAD((SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'employee'), 4, '0'), SUBSTRING(new.firstname, 1, 4));
END
;;
DELIMITER ;

测试:

mysql> insert into employee (firstname) values ('johnathan');
Query OK, 1 row affected (0.04 sec)

mysql> insert into employee (firstname) values ('johnathan');
Query OK, 1 row affected (0.02 sec)

mysql> insert into employee (firstname) values ('johnathan');
Query OK, 1 row affected (0.02 sec)

mysql> select * from employee;
+------------+-----------+-----------+
| employeeid | specialid | firstname |
+------------+-----------+-----------+
|          1 | 0001john  | johnathan |
|          2 | 0002john  | johnathan |
|          3 | 0003john  | johnathan |
+------------+-----------+-----------+
3 rows in set (0.00 sec)

这是一种黑客攻击,并且 information_schema 在某些权限不受您控制的数据库上将不可用。

What about a schema like

CREATE TABLE employee
(
employeeid INT PRIMARY KEY AUTO_INCREMENT,
firstname varchar(255)
);

CREATE INDEX part_of_firstname ON employee (firstname(4));

That'll let you perform lookups fairly quickly using your natural primary key, while giving you an artificial primary key and not forcing to denormalize.

EXPLAIN SELECT * FROM EMPLOYEE WHERE EMPLOYEEID = 1 AND FIRSTNAME LIKE 'john%';

+----+-------------+----------+-------+---------------------------+---------+---------+-------+------+-------+
| id | select_type | table    | type  | possible_keys             | key     | key_len | ref   | rows | Extra |
+----+-------------+----------+-------+---------------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | employee | const | PRIMARY,part_of_firstname | PRIMARY | 4       | const |    1 |       |
+----+-------------+----------+-------+---------------------------+---------+---------+-------+------+-------+

Of course since the 0001 part of the primary key is unique enough to identify the user you need not query the name at all.

If you insist on precalculating this should work

CREATE TABLE employee
(
employeeid INT PRIMARY KEY AUTO_INCREMENT,
specialid VARCHAR(255),
firstname VARCHAR(255)
);

CREATE INDEX employee_specialid ON employee (firstname(4));

DELIMITER ;;
CREATE TRIGGER employeeid_trigger BEFORE insert ON employee
FOR EACH ROW
BEGIN
SET new.specialid = CONCAT(LPAD((SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'employee'), 4, '0'), SUBSTRING(new.firstname, 1, 4));
END
;;
DELIMITER ;

Testing it:

mysql> insert into employee (firstname) values ('johnathan');
Query OK, 1 row affected (0.04 sec)

mysql> insert into employee (firstname) values ('johnathan');
Query OK, 1 row affected (0.02 sec)

mysql> insert into employee (firstname) values ('johnathan');
Query OK, 1 row affected (0.02 sec)

mysql> select * from employee;
+------------+-----------+-----------+
| employeeid | specialid | firstname |
+------------+-----------+-----------+
|          1 | 0001john  | johnathan |
|          2 | 0002john  | johnathan |
|          3 | 0003john  | johnathan |
+------------+-----------+-----------+
3 rows in set (0.00 sec)

This is kind of a hack, and information_schema won't be available on some DBs where permissions aren't under your control.

谁许谁一生繁华 2024-10-27 23:58:34

您可以尝试在 select 语句中连接它,而不是存储自动增量列和 id 列,

SELECT CONCAT(id, substring(name,4) FROM tbl_employee

这样您就不需要触发器

You could try concatenating it in your select statement instead of storing an auto increment column and an id column,

SELECT CONCAT(id, substring(name,4) FROM tbl_employee

That way you wouldn't need triggers

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文