简体   繁体   中英

MySQL - How do I declare a primary key using a column constraint?

您好,我正在使用MySQL,并且已经在SQL中使用表约束声明了原子主键,这是不好的做法吗?

When you say "column constraint", you mean this?

CREATE TABLE `clients` (
  `id` int(11) NOT NULL auto_increment PRIMARY KEY,
  `created` datetime NOT NULL,
  `email` varchar(150) NOT NULL,
  `notes` text NOT NULL
);

There is nothing inherently bad with either of them (it's just a syntactic difference).

The "in column" syntax above is slightly shorter so you'd want to use it when you don't care for naming your constraint and PK spans only one field.

Conversely, if your want to name the primary key or it is composite, you'd use the "table-level" syntax.

Here is an example of the named PK spanning two columns:

CREATE TABLE `clients` (
  ...
  CONSTRAINT `my_primary_key` PRIMARY KEY (`id1`, `id2`)
);

What you have is best practice. Having all constraints after the columns.

Easier to read (at least for me): all constraints (and indexes) are grouped together in the table's definition.

Consistency: a compound primary key cannot be declared as a column constraint, so this way you have all primary key constraints declared at the same place, in all your table definitions.

Less error prone: Foreign Key constraints have to be defined this way. If you try to define them as column constraints, they are (silently) ignored in MySQL!


I'm not sure what "atomic" is supposed to mean in this case, I guess it means that the key is not compound (composite) but only one column.

They are just both the same, when you do this column constraint :

create table xx(
    id int primary key,
    txt text not null   
);

When your database admin tool make a script out of it, this is how it looks like:

CREATE TABLE xx
(
  id integer NOT NULL,
  txt text NOT NULL,
  CONSTRAINT xx_pkey PRIMARY KEY (id )
)

The advantage of making primary key a table constraint , is you can get to name your primary key in a more descriptive manner.

And the another advantage of your first approach(table constraint), should you decided to make a composite primary key, it's possible to make that happen:

create table yy
(
   country_id int not null,
   city_id int not null,
   population int,
   constraint xx_primary_key primary key(country_id, city_id)
);

You cannot do this with column constraint :

create table yy
(
   country_id int not null primary key,
   city_id int not null primary key,
   population int not null
);

Either way, your friends are not accurate on column constraint , there is no such thing as column constraint (sic) (they might meant column-level primary key), the information of primary-key-ness of column(s) are not saved on column level(even you are using single column primary key)

It's just a syntactic convenience to put the PRIMARY KEY on column level, but they are not saved there, your RDBMS will still put that information on table-level

While not exactly an answer to primary key, here's an example of column-level and table-level stuff as handcrafted by developer:

Sql Server:

create table zz
(
id int not null primary key,
lastname varchar(50) not null check(len(lastname) >= 2),
x numeric(18,4) not null,
y numeric(18,4) not null,
constraint ck_balance check(x - y >= 0)
);

You can see on Sql Server admin tool if it keeps your column-level-intended stuff really resides in the column:

CREATE TABLE [dbo].[zz](
    [id] [int] NOT NULL,
    [lastname] [varchar](50) NOT NULL,
    [x] [numeric](18, 4) NOT NULL,
    [y] [numeric](18, 4) NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[zz]  WITH CHECK ADD CHECK  ((len([lastname])>=(2)))
GO

ALTER TABLE [dbo].[zz]  WITH CHECK ADD  CONSTRAINT [ck_balance] CHECK  ((([x]-[y])>=(0)))
GO

ALTER TABLE [dbo].[zz] CHECK CONSTRAINT [ck_balance]
GO

Only column-level check constraint (Lastname field) gets a column-level treatment. Other things like primary key(even it's a single field) and constraint checking if two numbers are balance are on table-level.

I don't see how your database will benefit on placing the column constraint (primary key) on column level, primary key information gets saved on table-level anyhow

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM