こんにちは、私は MySQL を使用しており、SQL でテーブル制約を使用してアトミック主キーを宣言しています。これは悪い習慣ですか?
4 に答える
「列制約」とは、これのことですか?
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
);
どちらも本質的に悪いものではありません (構文上の違いにすぎません)。
上記の「in column」構文は少し短いので、制約に名前を付ける必要がなく、PK が 1 つのフィールドのみにまたがる場合に使用します。
逆に、主キーに名前を付けたい場合、またはそれが複合キーである場合は、「テーブルレベル」構文を使用します。
2 つの列にまたがる名前付き PK の例を次に示します。
CREATE TABLE `clients` (
...
CONSTRAINT `my_primary_key` PRIMARY KEY (`id1`, `id2`)
);
あなたが持っているのはベストプラクティスです。列の後にすべての制約があります。
読みやすい (少なくとも私にとっては): すべての制約 (およびインデックス) は、テーブルの定義でグループ化されます。
一貫性: 複合主キーを列制約として宣言することはできないため、このようにして、すべてのテーブル定義の同じ場所ですべての主キー制約を宣言できます。
エラーが発生しにくい: 外部キー制約はこのように定義する必要があります。それらを列の制約として定義しようとすると、MySQL では (黙って) 無視されます!
この場合、「アトミック」が何を意味するのかわかりません。キーが複合 (複合) ではなく、1 つの列のみであることを意味していると思います。
この列の制約を行うと、どちらも同じです。
create table xx(
id int primary key,
txt text not null
);
データベース管理ツールでスクリプトを作成すると、次のようになります。
CREATE TABLE xx
(
id integer NOT NULL,
txt text NOT NULL,
CONSTRAINT xx_pkey PRIMARY KEY (id )
)
主キーをテーブル制約にする利点は、よりわかりやすい方法で主キーに名前を付けることができることです。
そして、最初のアプローチ(テーブル制約)のもう1つの利点は、複合主キーを作成することにした場合、それを実現することが可能です:
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)
);
列の制約でこれを行うことはできません:
create table yy
(
country_id int not null primary key,
city_id int not null primary key,
population int not null
);
いずれにせよ、あなたの友人は列の制約について正確ではありません.列の制約(sic)などはありません(列レベルの主キーを意味する可能性があります)、列の主キーネスの情報は保存されません列レベルで(単一列の主キーを使用している場合でも)
PRIMARY KEY を列レベルに配置するのは構文上の便宜ですが、そこには保存されません。RDBMS はその情報をテーブルレベルに配置します。
主キーに対する正確な答えではありませんが、開発者が手作りした列レベルおよびテーブルレベルのものの例を次に示します。
SQLサーバー:
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)
);
列レベルの意図したものが実際に列に存在するかどうかは、Sql Server 管理ツールで確認できます。
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
列レベルのチェック制約 (Lastname フィールド) のみが列レベルの処理を受けます。主キー(単一のフィールドであっても)や、2つの数値がバランスしているかどうかの制約チェックなどの他のことは、テーブルレベルにあります。
列の制約(主キー)を列レベルに配置することでデータベースがどのように役立つかわかりません。主キー情報はとにかくテーブルレベルで保存されます