简体   繁体   中英

Can i use a SELECT statement to define a CHECK constraint?

In MS SQL server, can i use a SELECT statement to define a CHECK constraint? Say i have to work with two tables "Customer Master" and "Indian Customer" in ideal situation both tables are compleatly different, and are not interrelated in anyways. however they share the same database

Content of "Customer Master":
CustomerName (colomn): a, b, c, d, e
Branchlocation (colomn): IN, AU, IN, IN, UK

Content of "Indian Customer":
customerID (colomn): 1, 2, 3
CustomerName  (colomn): a, c, d
customer details (colomn): details1, details, details
.
.
.

In Table "Indian Customer" i want to put a constraint so that the users entring data in this table should not be able to enter customers that dont exist in "Customer Master" or whose branch location is not IN. also the tables are in the same project but are NOT directly related . In other words you can say Only indian customer from "Customer Master" should be in table "Indian Customer".

select CustomerName from "Customer Master"
where Branchlocation = 'IN'

the output of the above query should only be allowed in ["Indian Customer"].[CustomerName]

You can add some additional constraints and superkeys, and get what you want:

CREATE TABLE CustomerMaster (
     CustomerName varchar(100) not null,
     LocationCode char(2) not null,
     constraint PK_CustomerMaster PRIMARY KEY (CustomerName),
     constraint UQ_CustomerMaster_Location UNIQUE (CustomerName,LocationCode), /* <-- Superkey here */
     constraint CK_CustomerMaster_Locations CHECK (
         LocationCode in ('IN','UK','AU')
)

CREATE TABLE IndianCustomer (
     CustomerID int not null,
     CustomerName varchar(100) not null,
     CustomerDetails varchar(max) not null,
     LocationCode as 'IN' persisted,
     constraint FK_IndianCustomer_CustomerMaster FOREIGN KEY (CustomerName,LocationCode) references CustomerMaster (CustomerName,LocationCode)
)

By having LocationCode as a computed column in IndianCustomer, and having the foreign key against the superkey, you're ensuring the data matches.

You can define an additional FK constraint just for CustomerName -> CustomerName, this can prove useful in some circumstances.


Or, to put it another way - there is one , highly stylised way to construct a constraint based on a "select" statement - and that is a FOREIGN KEY. But you sometimes have to add additional information (such as super keys, computed columns) to satisfy additional filtering requirements.

Normally 3 ways

First way, best, using DRI

  • define an extra column Branchlocation in "Indian Customer"
  • add a CHECK CONSTRAINT to limit it to "IN"
  • add a unique constraint on "Customer Master" for CustomerName/ID, Branchlocation
  • foreign key on both CustomerName/ID, Branchlocation from "Indian Customer" to "Customer Master"

This works cleanly without code or triggers

Edit: as per Damien_The_Unbeliever's answer

Second way, OK, triggers

  • On insert or update of "Indian Customer", check Customer Master

Third way, not so good, use a function

  • A check constraint on "Indian Customer" uses a function to hide the SELECT

This is not safe for concurrency and is not guaranteed to work

NOTE :- As far as I know, there is no possible way to check constraint using a select statement. However for your case you can use a simple select query with where clause as given below

select * from A 
where somecolumn not in 
( select somecolumn from B where <condition for B> )

For your query, assuming you have sno as foreignkey in B -

select somedata from A
where someforeignKey = ( select sno from B where sno = 55 ) 

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