[MySQL] sql field constraints

In MySQL, the data we need to store requires different constraints in specific scenarios. When the newly inserted data violates the constraint field of the field, MySQL will directly prohibit the insertion.

  • Data type is also a constraint, but the data type constraint is too simple;
  • For example, if what I need to store is a serial number, then there cannot be a negative number. In this case, unsigned must be used to constrain the integer;
  • If what I want to store is a date, and every field of this date must have it, then it needs to be NOT NULLconstrained by not being empty;
  • If what I want to store is a user ID, this value must be unique in the entire user system, and I can use it UNIQUEto constrain the uniqueness.

This article mainly introduces the following types of constraints, which are still ddl type statement operations in MySQL.

null/not null
default
comment
zerofill
primary key
auto_increment
unique key

By the way, in MySQL, the value of each column can be called or 字段; generally it is not called 键值.

And each row in the table is called一条记录

1. Empty attribute

1.1 Description

The empty attribute contains two values, NULL/NOT NULL, corresponding to empty and not empty respectively.

In the database, if we do not specify the value of a column when inserting a row, the database will set the value to NULL;

Pay attention here to distinguish between NULL and empty strings. Empty strings are not NULL!

But when actually using the data, assuming that this is integer data, we need to take it out and perform operations on it. At this time, the result obtained by NULL is not a number, and there is no way to perform operations. So many times, we will set the constraints of a field to NOT NULLand add a default value (such as 0 or empty string)

MariaDB [hello]> select null;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.000 sec)

MariaDB [hello]> select not null;
+----------+
| not null |
+----------+
|     NULL |
+----------+
1 row in set (0.001 sec)

It can be seen from the following that empty attributes cannot participate in operations, and the result will be NULL no matter how the operation is performed.

In Python, NULL directly corresponds to None. When you try to perform operations with None and int types, Python will report an error. The same is true in CPP.

MariaDB [hello]> select 1+null;
+--------+
| 1+null |
+--------+
|   NULL |
+--------+
1 row in set (0.001 sec)

1.2 Case

Suppose we have a table corresponding to classes and classrooms on a floor, which contains two fields: class number and classroom number.

  • If the class number is empty, then you don’t know which class is in this classroom.
  • If the classroom number is empty, then you don’t know where a certain class is held.

It can be seen from the actual scenario that neither of these two fields can be empty, so this needs to be taken into consideration when creating the table.

create table if not exists myclass(
	class_name varchar(30) not null,
    class_room varchar(30) not null
)default charset=utf8;

After creating the table, when we try to insert a NULL field, the following prompt will appear, indicating that a certain column cannot be empty.

MariaDB [hello]> insert into myclass values ('510',NULL);
ERROR 1048 (23000): Column 'class_room' cannot be null

The empty string can be inserted. This once again illustrates that what we think is not the same as NULL. The empty string is not NULL.

MariaDB [hello]> insert into myclass values ('510','');
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> select * from myclass;
+------------+------------+
| class_name | class_room |
+------------+------------+
| 510        |            |
+------------+------------+
1 row in set (0.000 sec)

2.Default value default

When we register for certain websites, if some information is not filled in, it will be set as default by the system.

For example, when you do not select your age, the system may display you as 0 years old; other users will know that you did not fill in your true age when they see the 0 years old displayed on your personal homepage. (When developing front-end, you can also regard 0 as not filled in and display it as "hidden age")

Another example is that there is a value for user points on our website. When a user registers, the points must be 0 (the operation of giving points to new users is not considered for the time being). At this time, the default value of the points column can be set to 0. You do not need to explicitly insert the data in this column when inserting;

In MySQL, after a default value is set for a column. If the data for this column is not specified when inserting, the default value will be used.

create table if not exists web_user(
    name varchar(30) not null default '默认用户名',
    age tinyint not null default 0,
    gender char(2) not null default '男' 
);

After creating this table, when we look at the table structure, we can see whether it is empty and the default related attributes.

MariaDB [hello]> desc web_user;
+--------+-------------+------+-----+-----------------+-------+
| Field  | Type        | Null | Key | Default         | Extra |
+--------+-------------+------+-----+-----------------+-------+
| name   | varchar(30) | NO   |     | 默认用户名      |       |
| age    | tinyint(4)  | NO   |     | 0               |       |
| gender | char(2)     | NO   |     | 男              |       |
+--------+-------------+------+-----+-----------------+-------+
3 rows in set (0.004 sec)

Since we have set initial values ​​for the three fields in this table, you can even insert data directly without specifying anything; as you can see below, all columns are set to the initial values ​​of the column.

MariaDB [hello]> insert into web_user values ();
Query OK, 1 row affected (0.001 sec)

MariaDB [hello]> select * from web_user;
+-----------------+-----+--------+
| name            | age | gender |
+-----------------+-----+--------+
| 默认用户名      |   0 | 男     |
+-----------------+-----+--------+
1 row in set (0.000 sec)

Default values ​​can help when we want not to set the value of a certain column.

Here is an error demonstration. We only set two values ​​​​in values. The purpose is to let the gender of the newly inserted user adopt the default value. But MySQL reported an error. The error message was that the number of values ​​was inconsistent with the number of columns.

MariaDB [hello]> insert into web_user values ('李华',16);
ERROR 1136 (21S01): Column count doesn't match value count at row 1

This is because when we inserted, we did not explicitly tell MySQL which columns these two values ​​​​are. Does Li Hua list name or gender? MySQL has no way to decide for itself! So simply refuse to insert.

Therefore, when we want a certain column to use the default value, we need to tell MySQL which columns of data the values ​​we are currently specifying are.

insert into web_user (name,age) values ('李华',16);

Only in this way can the insertion be successful

MariaDB [hello]> insert into web_user (name,age) values ('李华',16);
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> select * from web_user;
+-----------------+-----+--------+
| name            | age | gender |
+-----------------+-----+--------+
| 默认用户名      |   0 | 男     |
| 李华            |  16 | 男     |
+-----------------+-----+--------+
2 rows in set (0.001 sec)

Because the column names are displayed and specified here, the order does not necessarily need to follow the order of the column names in the table. For example, below we can also insert in reverse. But it is not recommended to do this. The order of column names when inserting should be consistent with the order of columns in the table!

MariaDB [hello]> insert into web_user (age,name) values (18,'小李');
Query OK, 1 row affected (0.001 sec)

MariaDB [hello]> select * from web_user;
+-----------------+-----+--------+
| name            | age | gender |
+-----------------+-----+--------+
| 默认用户名      |   0 | 男     |
| 李华            |  16 | 男     |
| 小李            |  18 | 男     |
+-----------------+-----+--------+
3 rows in set (0.001 sec)

If you want the age column to use the initial value, then insert it as follows;

MariaDB [hello]> insert into web_user (name,gender) values ('菲菲公主','女');
Query OK, 1 row affected (0.005 sec)

2.1 Default value and NULL

It should be noted that the default value and NOT NULLdo not have to be used together

  • When we set a default value, but it is not set NOT NULL, we can explicitly insert NULL
  • The default value can also be set to NULL
create table if not exists test_user(
    name varchar(30) not null default '默认用户名',
    age tinyint not null default 0,
    gender char(2) default null
);

Use the above SQL to create a table, and the database does not report an error, which means that our syntax is supported. Because gender does not need to be involved in the operation, we can think that when the gender column is empty, it is 未选择性别the option. However, this problem can also be solved by using an empty string as the default value. In comparison, using an empty string is better, because this ensures that the value of this field is always a string without the need for special handling of null.

image-20230804095037098

default nulland not nullcan't be used together, that's for sure!

3. Column description comment

It should be noted that comments are not supported in SQLite. Different databases will have slight differences in their support for SQL fields. Please refer to the database you are using. What is described in this article is based on MySQL and MariaDB.

The so-called column description is an explanatory message about what the column does, which is equivalent to a comment on the code. It has no meaning in itself;

The main function of column comments is to allow everyone who uses this database and this table to understand the role of this field. Additional comments can also be added to allow programmers to perform additional processing in the upload code of different modules.

For example, we change the user table that appeared in the second point to the following form, and add comments to each field.

create table if not exists web_user(
    name varchar(30) not null default '默认用户名' comment '用户名',
    age tinyint not null default 0 comment '用户年龄',
    gender char(2) not null default '男' comment '用户性别' 
);

After we use this SQL to create this table, if we want to query the comments of the fields, we can use the following command to view the commands used when creating the table (which includes the comments of the table)

SHOW CREATE TABLE web_user;

Displayed as follows

MariaDB [hello]> SHOW CREATE TABLE web_user;
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                               |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| web_user | CREATE TABLE `web_user` (
  `name` varchar(30) NOT NULL DEFAULT '默认用户名' COMMENT '用户名',
  `age` tinyint(4) NOT NULL DEFAULT 0 COMMENT '用户年龄',
  `gender` char(2) NOT NULL DEFAULT '男' COMMENT '用户性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8                  |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.000 sec)

You can also use the following command to display all columns and column properties, including comments

SHOW FULL COLUMNS FROM web_user;
MariaDB [hello]> SHOW FULL COLUMNS FROM web_user;
+--------+-------------+-----------------+------+-----+-----------------+-------+---------------------------------+--------------+
| Field  | Type        | Collation       | Null | Key | Default         | Extra | Privileges                      | Comment      |
+--------+-------------+-----------------+------+-----+-----------------+-------+---------------------------------+--------------+
| name   | varchar(30) | utf8_general_ci | NO   |     | 默认用户名      |       | select,insert,update,references | 用户名       |
| age    | tinyint(4)  | NULL            | NO   |     | 0               |       | select,insert,update,references | 用户年龄     |
| gender | char(2)     | utf8_general_ci | NO   |     | 男              |       | select,insert,update,references | 用户性别     |
+--------+-------------+-----------------+------+-----+-----------------+-------+---------------------------------+--------------+
3 rows in set (0.002 sec)

It should be noted that the results displayed by the desc command do not include column comments.

MariaDB [hello]> desc web_user;
+--------+-------------+------+-----+-----------------+-------+
| Field  | Type        | Null | Key | Default         | Extra |
+--------+-------------+------+-----+-----------------+-------+
| name   | varchar(30) | NO   |     | 默认用户名      |       |
| age    | tinyint(4)  | NO   |     | 0               |       |
| gender | char(2)     | NO   |     | 男              |       |
+--------+-------------+------+-----+-----------------+-------+
3 rows in set (0.001 sec)

image-20230804101749987

4.zerofill

4.1 Test results

First, create a table using the following command

create table if not exists test_int(
	a int not null,
	b int unsigned not null
);

After the creation is completed, we look at the statements used to create this table, and we will find that there is an extra bracket after int, followed by a number.

We know that in char and varchar, the brackets are used to limit the character length of the string, so what are the brackets used in shaping?

MariaDB [hello]> show create table test_int;
+----------+------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                           |
+----------+------------------------------------------------------------------------------------------------------------------------+
| test_int | CREATE TABLE `test_int` (
  `a` int(11) NOT NULL,
  `b` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+----------+------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)

First insert a piece of data into this table and query to display it.

MariaDB [hello]> insert into test_int values (3,1);
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> select * from test_int;
+---+---+
| a | b |
+---+---+
| 3 | 1 |
+---+---+
1 row in set (0.000 sec)

If we modify the attributes of column a to the following field type

alter table test_int change a a int(5) unsigned zerofill;

Check the command to create the table again. The result is as follows. Column a has been modified to the attribute of the letter.

MariaDB [hello]> alter table test_int change a a int(5) unsigned zerofill;
Query OK, 1 row affected (0.005 sec)               
Records: 1  Duplicates: 0  Warnings: 0

MariaDB [hello]> show create table test_int;
+----------+---------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                |
+----------+---------------------------------------------------------------------------------------------------------------------------------------------+
| test_int | CREATE TABLE `test_int` (
  `a` int(5) unsigned zerofill DEFAULT NULL,
  `b` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+----------+---------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.000 sec)

So what does the number in the brackets do with zerofill?

Query this table again and you will find that the data just inserted has changed to 3 in column a 00003!

MariaDB [hello]> select * from test_int;
+-------+---+
| a     | b |
+-------+---+
| 00003 | 1 |
+-------+---+
1 row in set (0.000 sec)

4.2 padding with 0

At this time, the role of this attribute is very clear. It is used to pad the number with 0s; and 5 is the specified length of padding 0s, not the length of the number; when the number of digits is less than 5, it will trigger pad 0;

It can be seen that even if it appears in the table structure int(5), we can still insert numbers longer than 5 digits into this table.

MariaDB [hello]> insert into test_int values (12345678,1);
Query OK, 1 row affected (0.005 sec)

So this bracket is not used to limit the length of int, but when a number is less than 5 digits, 0 will be added to the front of the number.

MariaDB [hello]> insert into test_int values (18,3);
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> select * from test_int;
+----------+---+
| a        | b |
+----------+---+
|    00003 | 1 |
| 12345678 | 1 |
|    00018 | 3 |
+----------+---+
3 rows in set (0.001 sec)

If you int(5) zerofillchange it to a longer value, the length of the leading 0 will change.

alter table test_int change a a int(7) unsigned zerofill;
MariaDB [hello]> alter table test_int change a a int(7) unsigned zerofill;
Query OK, 0 rows affected (0.007 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [hello]> select * from test_int;
+----------+---+
| a        | b |
+----------+---+
|  0000003 | 1 |
| 12345678 | 1 |
|  0000018 | 3 |
+----------+---+
3 rows in set (0.001 sec)

It should be noted that int(n)the attribute of zerofillwill only trigger the operation of adding 0 before it is used together with . This can explain why the number in the initially created table int(11)is not padded with zeros;

The prepended 0 here is just an optimization displayed internally in MySQL . In fact, the number itself is still stored; for example, if we query 3 in the above table, we can directly find it out.

MariaDB [hello]> select * from test_int where a = 3;
+---------+---+
| a       | b |
+---------+---+
| 0000003 | 1 |
+---------+---+
1 row in set (0.001 sec)

For example, the numbers I want to store are all 5 digits, and if the leading 0s are set, the formatted output results seen when querying the entire table will look much more comfortable than the results without leading 0s.

4.3 Why is int 11 and unsigned 10?

When querying the default create table i statement earlier, you will find that the MySQL system defaults to 11 bits for int and 10 bits for unsigned int.

image-20230804104708752

This is because the length of 10 bits can already identify all values ​​in the int range, and signed integers have one more bit, which is used to display the positive and negative signs.

5.primary key

The primary key is used to constrain the data in the field. It cannot be repeated or empty . A table has only one primary key (or no one), and an integer is generally used as the primary key.

The primary key is used to determine the uniqueness of each record in the table. It informs the user that if they want to insert data into this table, they must ensure that the primary key values ​​do not conflict.

5.1 Design types of primary keys

Take a user system as an example

  • We can set the username as the primary key. When the user selects an existing username, reject the username and inform the user;
  • We can use another unrelated number as the primary key. For example, QQ uses the QQ number to identify the uniqueness of the user. It does not require that the user's user name cannot be the same (most chat software now uses this method, such as QQ and KOOK, although WeChat does not have a unique identifier like QQ, there must be a primary key as a unique identifier in the background),
  • We can combine multiple columns into a composite primary key

5.2 Deleting and adding primary keys

When creating a table, you can specify the primary key in two ways:

-- 方法1,在字段后指明
create table test_pri_1(
	id int unsigned not null primary key,
    name varchar(30) not null
);
-- 方法2,在表的最后指明
create table test_pri_2(
	id int unsigned not null,
    name varchar(30) not null,
    primary key(id)
);

Both can be executed successfully.

In addition, the primary key itself cannot be empty, so we don’t need to write it when defining the primary key column.not null

MariaDB [hello]> create table test_pri_1(
    -> id int unsigned not null primary key,
    ->     name varchar(30) not null
    -> );
Query OK, 0 rows affected (0.017 sec)

MariaDB [hello]> create table test_pri_2(
    -> id int unsigned not null,
    ->     name varchar(30) not null,
    ->     primary key(id)
    -> );
Query OK, 0 rows affected (0.019 sec)

And the table structure is the same. You can see PRI at the Key of the id column, which is Primarythe abbreviation of , which means that the id column is the primary key.

MariaDB [hello]> desc test_pri_1;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(30)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.001 sec)

MariaDB [hello]> desc test_pri_2;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(30)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.001 sec)

If it is an existing table, we can also add primary keys to it or delete primary keys.

alter table 表名 drop primary key;
-- 用于删除主键列的主键属性,因为主键列只能有一个
-- 注意,这个语句不会删除该列
alter table 表名 add primary key(id);
-- 给id列加上主键属性(但是ID列里面不能有重复值)

Test it and you can see that the PRI attribute of the id column is gone.

MariaDB [hello]> alter table test_pri_1 drop primary key;
Query OK, 0 rows affected (0.010 sec)              
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [hello]> desc test_pri_1;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   |     | NULL    |       |
| name  | varchar(30)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.002 sec)

When we insert data into the table, if we want to insert the same record into the primary key column, MySQL will refuse the insertion.

MariaDB [hello]> insert into test_pri_2  values (1,'李华');
Query OK, 1 row affected (0.006 sec)

MariaDB [hello]> insert into test_pri_2  values (1,'李明');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

5.3 Composite primary key

A table has only one primary key, but the primary key can have more than one column ;

Take the activity statistics robot I wrote myself as an example. The robot is in different servers and will receive different server IDs and operations from different users. In order to record the activity of different users on different servers, in the user statistics table , you need both server ID and user ID; at this time, a user will join two servers , and both servers use my robot. When fed back to the table, a user ID appears twice, but the corresponding server IDs are different;

In this case, it is definitely not possible to set the user ID or server ID as the primary key alone. We can set the user ID and server ID to match the primary key;

After setting up the composite primary key, we can have the same server ID and the same user ID. But it can only be a user of a certain server , and there cannot be two records with the same server ID and user ID . This is what composite primary keys are for!

create table user(
	guild_id int unsigned comment '服务器ID',
	user_id int unsigned not null comment '用户ID',
	score tinyint unsigned not null default 0 comment '用户积分',
	primary key(guild_id, user_id) -- guild_id + user_id 为复合主键
);

If you look at the table structure at this time, you will find that the two key values ​​​​of server id and user id have attributes in Key PRI, that is, they are both primary keys;

Moreover, even if ours guild_idis not specified not null, its NULLattribute is still NO. Because the primary key is not allowed to be NULL!

MariaDB [hello]> create table user(
    -> guild_id int unsigned comment '服务器ID',
    -> user_id int unsigned not null comment '用户ID',
    -> score tinyint unsigned not null default 0 comment '用户积分',
    -> primary key(guild_id, user_id) -- guild_id + user_id 为复合主键
    -> );
Query OK, 0 rows affected (0.011 sec)

MariaDB [hello]> desc user;
+----------+---------------------+------+-----+---------+-------+
| Field    | Type                | Null | Key | Default | Extra |
+----------+---------------------+------+-----+---------+-------+
| guild_id | int(10) unsigned    | NO   | PRI | NULL    |       |
| user_id  | int(10) unsigned    | NO   | PRI | NULL    |       |
| score    | tinyint(3) unsigned | NO   |     | 0       |       |
+----------+---------------------+------+-----+---------+-------+
3 rows in set (0.003 sec)

When we insert, the server id and user id can be repeated in their respective columns.

MariaDB [hello]> insert into user values (1,1,0);
Query OK, 1 row affected (0.008 sec)

MariaDB [hello]> insert into user values (1,2,0);
Query OK, 1 row affected (0.008 sec)

MariaDB [hello]> insert into user values (2,1,0);
Query OK, 1 row affected (0.001 sec)

But if you want to insert another such record on the basis of the existing record with server ID 1 and user ID 1 , an error will be reported and the insertion will be refused.

MariaDB [hello]> select * from user;
+----------+---------+-------+
| guild_id | user_id | score |
+----------+---------+-------+
|        1 |       1 |     0 |
|        1 |       2 |     0 |
|        2 |       1 |     0 |
+----------+---------+-------+
3 rows in set (0.000 sec)

MariaDB [hello]> insert into user values (1,1,10);
ERROR 1062 (23000): Duplicate entry '1-1' for key 'PRIMARY'

6.Auto_increment

Auto-increment, as the name suggests, means that MySQL will automatically add data to this column for us. For example, for a serial number, adding a new record will increase the serial number by one; auto-increment attributes can only be added to shaping!

The auto-incremented column must be the primary key!

6.1 Use

The way to use auto-increment is to add this constraint after creating the key value of the table

create table test_pri_3(
	id int unsigned auto_increment,
    name varchar(30) not null,
    primary key(id)
);

Looking at the table structure, you can see that the id column is the primary key, is not empty, and has an auto-increment attribute.

MariaDB [hello]> desc test_pri_3;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.003 sec)

Since the auto-increment column must be the primary key, we cannot use it separately from the primary key;

If this column is not set as the primary key when setting the auto-increment, an error will be reported when creating the table.

MariaDB [hello]> create table test_pri_4(
    -> id int unsigned auto_increment,
    ->     name varchar(30) not null
    -> );
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

After setting the auto-increment, we can also explicitly specify the value of the column; we can also directly insert data from other columns without specifying it. MySQL will automatically help us +1 the current record.

MariaDB [hello]> insert into test_pri_3 values (1,'李华');
Query OK, 1 row affected (0.007 sec)

MariaDB [hello]> select * from test_pri_3;
+----+--------+
| id | name   |
+----+--------+
|  1 | 李华   |
+----+--------+
1 row in set (0.001 sec)

MariaDB [hello]> insert into test_pri_3 (name) values ('小明');
Query OK, 1 row affected (0.001 sec)

MariaDB [hello]> select * from test_pri_3;
+----+--------+
| id | name   |
+----+--------+
|  1 | 李华   |
|  2 | 小明   |
+----+--------+
2 rows in set (0.000 sec)

Insert a few more pieces of data and you can see that the ID column has been successfully incremented.

MariaDB [hello]> insert into test_pri_3 (name) values ('小明3');
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> insert into test_pri_3 (name) values ('小明5');
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> select * from test_pri_3;
+----+---------+
| id | name    |
+----+---------+
|  1 | 李华    |
|  2 | 小明    |
|  3 | 小明3   |
|  4 | 小明5   |
+----+---------+
4 rows in set (0.000 sec)

6.2 How does auto-increment determine the current serial number position?

Does the self-increasing length start from the largest number? Or are there other processing procedures?

First try to actively insert a key value of 1000 into the table, and then insert two rows of records without specifying the id.

MariaDB [hello]> insert into test_pri_3 values (1000,'test');
Query OK, 1 row affected (0.006 sec)

MariaDB [hello]> insert into test_pri_3 (name) values ('test1');
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> insert into test_pri_3 (name) values ('test2');
Query OK, 1 row affected (0.001 sec)

If you query the list, you will find that the records after 1000 are all added starting from 1000.

MariaDB [hello]> select * from test_pri_3;
+------+---------+
| id   | name    |
+------+---------+
|    1 | 李华    |
|    2 | 小明    |
|    3 | 小明3   |
|    4 | 小明5   |
| 1000 | test    |
| 1001 | test1   |
| 1002 | test2   |
+------+---------+
7 rows in set (0.000 sec)

Could it be that it is automatically incremented based on the largest ID? Let's try again.

First delete the record with the largest ID and then insert new data.

MariaDB [hello]> delete from test_pri_3 where id = 1002;
Query OK, 1 row affected (0.007 sec)

MariaDB [hello]> insert into test_pri_3 (name) values ('test3');
Query OK, 1 row affected (0.006 sec)

Query again and you will find that the auto-incremented ID is 1003. It can be seen that the maximum value of an id recorded internally is automatically incremented according to an additional internal record, instead of judging the maximum value of the id column in the table!

MariaDB [hello]> select * from test_pri_3;
+------+---------+
| id   | name    |
+------+---------+
|    1 | 李华    |
|    2 | 小明    |
|    3 | 小明3   |
|    4 | 小明5   |
| 1000 | test    |
| 1001 | test1   |
| 1003 | test3   |
+------+---------+
7 rows in set (0.001 sec)

So where is this extra record?

show create table test_pri_3;

Use the above command to view the sql statement that creates the table. You will find that immediately after the table, there is an auto-increment field.AUTO_INCREMENT=1004

MariaDB [hello]> show create table test_pri_3;
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                              |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_pri_3 | CREATE TABLE `test_pri_3` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1004 DEFAULT CHARSET=utf8 |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.000 sec)

This is the definition of the current value of the auto-increment field in MySQL. What is stored here is the auto-increment value of the next inserted record and its id. Each time a new record is inserted, the auto-increment value here will be converted into the value that the next record should be;

For example, if we want the ID of a system to increase from 10001, then we can directly insert a record with an ID of 10000 into the table after creating the table. For other records created after this, the ID will increase from 10001!

image-20230804133951367

6.3 Index

Speaking of which, let me mention the concept of indexes in MySQL.

Index : In a relational database, an index is a separate, physical storage structure that sorts the values ​​of one or more columns in a database table. It is a collection of one or more column values ​​in a table and a corresponding list of logical pointers to data pages in the table that physically identify these values .

The index is equivalent to the table of contents of a book . You can quickly find the required content based on the page numbers in the table of contents. Indexes provide pointers to data values ​​stored in specified columns of a table, and then sort these pointers according to a sort order that you specify. The database uses an index to find a specific value and then points forward to find the row containing that value.

This allows SQL statements corresponding to the table to execute faster and allows quick access to specific information in the database table.

Indexing is essentially a routine that trades space for time. In the current multi-concurrency business, execution speed is far more important than memory and disk usage!

7. unique key unique

The constraint of the unique key on the field is that the data in this column cannot be the same.

It looks similar to the primary key, but in fact it is a unique constraint independent of the primary key. The difference from the primary key is that the unique key can be NULL

You know, only one primary key can be set in a table. Composite primary keys sometimes do not meet our needs. So MySQL provides additional unique key constraints in addition to the primary key, allowing us to set uniqueness for other columns.

As for why? It's like a disclaimer: The data in my column is set to be unique, so it is impossible to accept two identical records (for example, two people in the user table have the same mobile phone number, which is not allowed). If it appears in your business If an error occurs when inserting is refused, then you should look at the BUG in the business processing code instead of blaming MySQL for not maintaining uniqueness or refusing to insert records.

7.1 Individually unique keys

Suppose I have a platform that uses a QQ number as the user's primary key similar to QQ; but for real-name authentication, we require that one ID card can only register one account. At this time, we cannot use a composite primary key to solve this problem, because the composite primary key allows one of the columns to be repeated ; and what we need is that the user account number and user ID number cannot be repeated!

At the same time, in the user's contact information, the phone numbers and WeChat IDs of the two users should not be the same. If you want to add the key value of the phone number, you can also set it unique!

At this time, the user number can be used as the primary key, and the user ID number can be set uniqueas the unique key;

create table test_unique_1(
	no int unsigned not null primary key,
	name varchar(30) not null,
    id_card varchar(30) not null unique 
);

View the table structure, the unique key column, the key constraint is UNI, which is uniquethe abbreviation of

MariaDB [hello]> desc test_unique_1;
+---------+------------------+------+-----+---------+-------+
| Field   | Type             | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+-------+
| no      | int(10) unsigned | NO   | PRI | NULL    |       |
| name    | varchar(30)      | NO   |     | NULL    |       |
| id_card | varchar(30)      | NO   | UNI | NULL    |       |
+---------+------------------+------+-----+---------+-------+
3 rows in set (0.001 sec)

id_cardWhen we insert the same record into the primary key column or column in this table , MySQL will reject the insertion.

MariaDB [hello]> insert into test_unique_1 values (1,'李华',123456);
Query OK, 1 row affected (0.006 sec)

MariaDB [hello]> insert into test_unique_1 values (1,'李华',1234567);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

MariaDB [hello]> insert into test_unique_1 values (3,'小明',123456);
ERROR 1062 (23000): Duplicate entry '123456' for key 'id_card'

7.2 Composite unique keys

A unique key can also set multiple columns, and the effect is the same as a composite primary key; it will not be explained here.

create table user(
	user_no int unsigned primary key auto_increment comment '用户编号 主键',
	guild_id int unsigned comment '服务器ID',
	user_id int unsigned not null comment '用户ID',
	score tinyint unsigned not null default 0 comment '用户积分',
	unique(guild_id, user_id) -- guild_id + user_id 为复合唯一键
);

The constraints on the pairs in the table guild_id和user_idbecome MUL, as shown in the figure below;

It can be observed that guild_idbecause there is no setting not null, the NULL column is YES, which means that this column can be NULL (the unique key can be NULL, but the primary key cannot)

MUL means that multiple rows are currently allowed to have the same value in this column, but guild_id和user_idtwo rows that are the same are not allowed to exist.

MariaDB [hello]> desc user;
+----------+---------------------+------+-----+---------+----------------+
| Field    | Type                | Null | Key | Default | Extra          |
+----------+---------------------+------+-----+---------+----------------+
| user_no  | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| guild_id | int(10) unsigned    | YES  | MUL | NULL    |                |
| user_id  | int(10) unsigned    | NO   |     | NULL    |                |
| score    | tinyint(3) unsigned | NO   |     | 0       |                |
+----------+---------------------+------+-----+---------+----------------+
4 rows in set (0.001 sec)

As shown below, the last insertion is the same as the first insertion guild_id和user_id, so an insertion rejection error occurs.

MariaDB [hello]> insert into user values (1,1,1,20);
Query OK, 1 row affected (0.006 sec)

MariaDB [hello]> insert into user values (2,1,2,21);
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> insert into user values (3,2,3,22);
Query OK, 1 row affected (0.006 sec)

MariaDB [hello]> insert into user values (4,1,1,23);
ERROR 1062 (23000): Duplicate entry '1-1' for key 'guild_id'

7.3 What are MUL, PRI and UNI in MySQL?

From the Mysql 5.7 official website documentation:

  • If the key is a PRI, the column is the primary key or one of the columns in a multi-column primary key;
  • If the key is UNI, this column is the first column of the unique index (unique indexes allow multiple null values, but you can determine whether the column allows nulls by checking the NULL field);
  • If the key is MUL, the column is the first column in a non-unique index, where multiple occurrences of a given value in the column are allowed;

8.Foreign keys

8.1 Description

Foreign keys are used to define the relationship between certain fields in two tables and to constrain records;

The basic syntax is as follows, used when creating tables. The table where the foreign key is set is the slave table!

foreign key (字段名) references 主表()

For example, in the figure below, the class number of each student in the student table corresponds to the class ID in the class table. At this time, we can set the ID of the class table as a foreign key in the student table class_id;

Although we can insert the data in the class table directly into the student table, this is not reasonable. If we have a lot of fields for a class or a student, it is very inconvenient to combine these two tables. Because there are many students in the same class, after merging the tables, it is equivalent to students in the same class, and the information in their class columns is all equal , which results in meaningless resource occupation (redundancy).

In contrast, after splitting the tables, it is a better choice to use foreign keys to bind the two fields !

image-20230804161621345

In the situation above, myclass is the master table and stu is a slave table;

-- 主表 班级
create table myclass (
	id int primary key comment '班级号',
	name varchar(30) not null comment '班级名'
);
-- 从表 学生
create table stu (
	id int primary key,
	name varchar(30) not null comment '学生名',
	class_id int,
	foreign key (class_id) references myclass(id) -- 设置从表外键约束
);

8.2 Testing

After creating the table, let's first take a look at the attributes of the student table i. You can see that the class_idkey of the table is a MUL, which is the same as when setting the composite unique key earlier.

MariaDB [hello]> desc stu;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int(11)     | NO   | PRI | NULL    |       |
| name     | varchar(30) | NO   |     | NULL    |       |
| class_id | int(11)     | YES  | MUL | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.001 sec)

When we try to insert data into the student table, an error will be reported

MariaDB [hello]> insert into stu values (1,'李华',2);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`hello`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass` (`id`))

This is because in the record you set, the student's class number 2 does not exist in the class table at all. How can a class that doesn't exist have students? So it naturally rejects your insertion.

Therefore, if we want to insert a student, we need to ensure that the class where the student's record is located exists in the class table! In this way, N-to-1 binding of students and classes is achieved.

MariaDB [hello]> insert into myclass values (1,'少华班');
Query OK, 1 row affected (0.002 sec)

MariaDB [hello]> insert into stu values (1,'李华',1);
Query OK, 1 row affected (0.005 sec)

MariaDB [hello]> select * from myclass;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 少华班    |
+----+-----------+
1 row in set (0.001 sec)

MariaDB [hello]> select * from stu;
+----+--------+----------+
| id | name   | class_id |
+----+--------+----------+
|  1 | 李华   |        1 |
+----+--------+----------+
1 row in set (0.000 sec)

Here I have inserted a few more data

MariaDB [hello]> select * from stu;
+----+-----------+----------+
| id | name      | class_id |
+----+-----------+----------+
|  1 | 李华      |        1 |
|  2 | 小明      |        1 |
|  3 | 小流      |        1 |
|  4 | 小流2     |        2 |
|  5 | 猪猪侠    |        2 |
|  6 | 苗条俊    |        2 |
+----+-----------+----------+
6 rows in set (0.000 sec)

MariaDB [hello]> select * from myclass;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 少华班    |
|  2 | 你好班    |
+----+-----------+
2 rows in set (0.000 sec)

There is another question at this time: If there are students in this class, can we delete this class?

Thinking about it, it is definitely not possible: since there is no such class, you cannot insert the corresponding student. Then when there are students in this class, you should not delete the class. The two are mutually logical; the same is true in MySQL. When a class has corresponding students, deletion is not allowed.

MariaDB [hello]> delete from myclass where id = 1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`hello`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass` (`id`))

Only when there are no more students in this class can it be deleted from the class table!

MariaDB [hello]> delete from stu where class_id = 2;
Query OK, 3 rows affected (0.005 sec)

MariaDB [hello]> delete from myclass where id = 2;
Query OK, 1 row affected (0.006 sec)

MariaDB [hello]> 

Updating the class ID is also not allowed because there are students bound to this class in the student table. MySQL cannot help us directly update the class numbers of all students.

MariaDB [hello]> update  myclass set id = 3 where name = '你好班'; 
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`hello`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass` (`id`))

8.3 Foreign key constraints

In the above situation, we can completely establish two independent tables without foreign key relationships and maintain the relationship between the two at the code layer.

But in this way, the operations of these two tables are still independent . MySQL does not know that there is a connection between the two tables; at this time, you can insert students into classes that do not exist and delete classes that still have students. If you drop it, it will eventually become a mess ;

  • Self-maintenance: the information in the two tables is related
  • Plus foreign keys: MySQL constraints

The combination of the two is the complete foreign key!

That's why we need to define foreign key constraints between these two tables in MySQL, and let MySQL help us maintain the data relationship in the two tables.

Note: Although MySQL will restrict our operations at this time, the actual business process still needs to be handled by the programmer in the code. For example, do not insert students whose classes do not exist into MySQL (MySQL will only reject the insertion and cannot help you correct the class)

The end

These are the basic constraint operations. There are others that will be used and will be added in the future!

Guess you like

Origin blog.csdn.net/muxuen/article/details/132158703