SQL Serverの制約は、単一または複数の列に適用できる事前定義されたルールです。これらの制約は、これらの列に格納されている値の整合性、信頼性、および精度を維持するのに役立ちます。 CREATETABLEまたはALTERTableステートメントを使用して制約を作成できます。 ALTER TABLEステートメントを使用する場合、SQLServerは制約を作成する前に既存の列データをチェックします。
制約ルールの条件を満たす列にデータを挿入すると、SQLServerはデータを正常に挿入します。ただし、データが制約に違反している場合、挿入ステートメントはエラーメッセージとともに中止されます。
たとえば、給与を含む組織の従業員データを格納する[Employee]テーブルがあるとします。給与列の値に関しては、いくつかの経験則があります。
- 列に-10,000や-15,000USDなどの負の値を設定することはできません。
- 最大給与値も指定する必要があります。たとえば、最高給与は2,000,000米ドル未満である必要があります。
制約が設定された新しいレコードを挿入すると、SQLServerは定義されたルールに対して値を検証します。
挿入された値:
給与80,000:正常に挿入されました
給与-50,000:エラー
この記事では、SQLServerの次の制約について説明します。
- NULLではありません
- ユニーク
- 確認
- 主キー
- 外部キー
- デフォルト
NOTNULL制約
デフォルトでは、SQLServerではNULL値を列に格納できます。これらのNULL値は有効なデータを表していません。
たとえば、組織内のすべての従業員は、Emp ID、名、性別、住所を持っている必要があります。したがって、NOT NULL制約のある列を指定して、常に有効な値を確保できます。
以下のCREATETABLEスクリプトは、[ID]、[FirstName]、[LastName]、[Gender]、および[Address]列にNOTNULL制約を定義します。
CREATE TABLE Employees ( ID INT NOT NULL, [FirstName] Varchar(100) NOT NULL, [MiddleName] Varchar(50) NULL, [LastName] Varchar(100) NOT NULL, [Gender] char(1) NOT NULL, [Address] Varchar(200) NOT NULL )
NOT NULLの制約、動作を検証するために、次のINSERTステートメントを使用します。
- すべての列の値を挿入します(NULLおよびNOT NULL) –正常に挿入します
INSERT INTO Employees (ID,[FirstName],[MiddleName],[LastName],[gender],[Address]) VALUES(1,'Raj','','Gupta','M','India')
- NOTNULLプロパティを持つ列の値を挿入します–正常に挿入します
INSERT INTO Employees (ID,[FirstName],[LastName],[gender],[Address]) VALUES(2, 'Shyam','Agarwal','M','UK')
- NOT NULL制約のある[LastName]列の挿入値をスキップします–失敗+
INSERT INTO Employees (ID,[FirstName],[gender],[Address]) VALUES(3,'Sneha','F','India')
最後のINSERTステートメントでエラーが発生しました–列にNULL値を挿入できません 。
このテーブルには、[従業員]テーブルに次の値が挿入されています。
HR要件に従って、[MiddleName]列にNULL値が必要ないとします。この目的のために、ALTERTABLEステートメントを使用できます。
ALTER TABLE Employees ALTER COLUMN [MiddleName] VARCHAR(50) NOT NULL
[MiddleName]列の既存の値が原因で、このALTERTABLEステートメントは失敗します。制約を適用するには、これらのNULL値を削除してから、ALTERステートメントを実行する必要があります。
UPDATE Employees SET [MiddleName]='' WHERE [MiddleName] IS NULL Go ALTER TABLE Employees ALTER COLUMN [MiddleName] VARCHAR(50) NOT NULL
SSMSテーブルデザイナを使用して、NOTNULL制約を検証することもできます。
UNIQUE制約
SQL ServerのUNIQUE制約により、単一の列または列の組み合わせに重複する値がないことが保証されます。これらの列は、UNIQUE制約の一部である必要があります。 UNIQUE制約が定義されると、SQLServerは自動的にインデックスを作成します。列に含めることができる一意の値は1つだけです(NULLを含む)。
たとえば、[ID]列にUNIQUE制約がある[DemoTable]を作成します。
CREATE TABLE DemoTable ( [ID] INT UNIQUE NOT NULL, [EmpName] VARCHAR(50) NOT NULL )
次に、SSMSでテーブルを展開すると、以下に示すように、一意のインデックス(非クラスター化)が作成されます。
インデックスを右クリックして、スクリプトを生成してください。以下に示すように、制約にADDUNIQUENONCLUSTEREDキーワードを使用します。
次の挿入ステートメントは、重複する値を挿入しようとするため、エラーになります。
INSERT INTO DemoTable ([ID],[EmpName]) VALUES (1,'Raj') GO INSERT INTO DemoTable ([ID],[EmpName]) VALUES (2,'Alisha') GO INSERT INTO DemoTable ([ID],[EmpName]) VALUES (1,'Raj') GO
SQL ServerのCHECK制約は、指定された列に挿入できる有効な値の範囲を定義します。挿入または変更された各値を評価し、それが満たされた場合、SQLステートメントは正常に完了します。
次のSQLスクリプトは、[Age]列に制約を設定します。その値は18年より大きくする必要があります。
CREATE TABLE DemoCheckConstraint ( ID INT PRIMARY KEY, [EmpName] VARCHAR(50) NULL, [Age] INT CHECK (Age>18) ) GO
このテーブルに2つのレコードを挿入しましょう。クエリは最初のレコードを正常に挿入します。
INSERT INTO DemoCheckConstraint (ID,[EmpName],[Age])VALUES (1,'Raj',20) Go INSERT INTO DemoCheckConstraint (ID,[EmpName],[Age])VALUES (2,'Sohan',17) GO
2番目のINSERTステートメントは、CHECK制約条件を満たしていないため、失敗します。
CHECK制約のもう1つの使用例は、郵便番号の有効な値を格納することです。以下のスクリプトでは、新しい列[ZipCode]を追加し、CHECK制約を使用して値を検証します。
ALTER TABLE DemoCheckConstraint ADD zipcode int GO ALTER TABLE DemoCheckConstraint ADD CONSTRAINT CK_zipcode CHECK (zipcode LIKE REPLICATE ('[0-9]', 5))
このCHECK制約は、無効な郵便番号を許可しません。たとえば、2番目のINSERTステートメントはエラーを生成します。
INSERT INTO DemoCheckConstraint values(3,'Sneha',19,30203) Go INSERT INTO DemoCheckConstraint values(4,'Jenny',21,122102)
PRIMARYKEY制約
SQLServerのPRIMARYKEY制約は、リレーショナルテーブルに一意の値を実装するためのデータベースプロフェッショナルの間で人気のある選択肢です。 UNIQUE制約とNOTNULL制約を組み合わせます。 PRIMARY KEY制約を定義すると、SQLServerはクラスター化インデックスを自動的に作成します。単一の列または一連の組み合わせを使用して、行の一意の値を定義できます。
その主な目的は、一意のエンティティまたは列の値を使用してテーブルの整合性を強化することです。
これはUNIQUE制約に似ていますが、次の違いがあります。
PRIMARYKEY列にNULL値を挿入することはできません。 | |
デフォルトでは、PRIMARYKEY列のクラスター化インデックスが作成されます。 | UNIQUE KEYは、主キー列の非クラスター化インデックスを作成します。 |
次のスクリプトは、ID列に主キーを定義します。
CREATE TABLE PrimaryKeyDemo ( ID INT PRIMARY KEY, [Name] VARCHAR(100) NULL )
以下に示すように、ID列でPRIMARY KEYを定義すると、クラスター化されたキーのインデックスが作成されます。
次のINSERTステートメントを使用して、レコードを[PrimaryKeyDemo]テーブルに挿入しましょう。
INSERT INTO PrimaryKeyDemo ([ID],[NAME]) VALUES (1,'Raj') GO INSERT INTO PrimaryKeyDemo ([NAME]) VALUES ('Mohan') GO
NULL値を挿入しようとするため、2番目のINSERTステートメントでエラーが発生します。
同様に、重複する値を挿入しようとすると、次のエラーメッセージが表示されます。
SQLServerのFOREIGNKEY制約は、2つのテーブル間の関係を作成します。この関係は、親子関係として知られています。 SQLServerで参照整合性を適用します。
子テーブルの外部キーには、親の主キー列に対応するエントリが必要です。最初に親テーブルに値を挿入せずに、子テーブルに値を挿入することはできません。同様に、最初に、親テーブルから値を削除する前に、子テーブルから値を削除する必要があります。
PRIMARY KEY制約に重複する値を含めることはできないため、子テーブルでも重複またはNULLを許可しません。
次のSQLスクリプトは、主キーを持つ親テーブルと、親テーブル[EmpID]列への主キーおよび外部キー参照を持つ子テーブルを作成します。
CREATE TABLE ParentTable ( [EmpID] INT PRIMARY KEY, [Name] VARCHAR(50) NULL ) GO CREATE TABLE ChildTable ( [ID] INT PRIMARY KEY, [EmpID] INT FOREIGN KEY REFERENCES ParentTable(EmpID) )
両方のテーブルにレコードを挿入します。子テーブルの外部キー値には、親テーブルにエントリがあることに注意してください。
INSERT INTO ParentTable VALUES (1,'Raj'),(2,'Komal') INSERT INTO ChildTable VALUES (101,1),(102,2)
親テーブルの主キーを参照しないレコードを子テーブルに直接挿入しようとすると、次のエラーメッセージが表示されます。
DEFAULT制約
SQL ServerのDEFAULT制約は、列のデフォルト値を提供します。 DEFAULT制約のある列のINSERTステートメントで値を指定しない場合、SQLServerはデフォルトで割り当てられた値を使用します。たとえば、注文テーブルにすべての顧客の注文のレコードがあるとします。 GETDATE()関数を使用すると、明示的な値を指定せずに注文日を取得できます。
CREATE TABLE Orders ( [OrderID] INT PRIMARY KEY, [OrderDate] DATETIME NOT NULL DEFAULT GETDATE() ) GO
このテーブルにレコードを挿入するには、[OrderDate]列への値の割り当てをスキップできます。
INSERT INTO Orders([OrderID]) values (1) GO
SELECT*FROM注文
DEFAULT制約列で明示的な値が指定されると、SQLServerはデフォルト値の代わりにこの明示的な値を格納します。
SQL Serverの制約は、次の場合に役立ちます。
- ビジネスロジックの実施
- 参照整合性の実施
- SQLServerテーブルへの不適切なデータの保存の防止
- 列データの一意性を強制する
- クエリオプティマイザが一意のデータを認識し、値のセットを検証するため、クエリのパフォーマンスが向上します
- SQLテーブルにNULL値を格納しないようにする
- アプリケーションでデータを表示するときにNULLを回避するためのコードの記述