Sub queries in check constraint

匿名 (未验证) 提交于 2019-12-03 02:22:01

问题:

I have table designed in SQL-Server 2008 R2.

I have a column in that table which needs to be checked against another table when data is inserting.

ALTER TABLE Table1         WITH CHECK ADD CONSTRAINT CK_Code         CHECK (MyField in (Select Field From Table2)) 

This cause an error

Sub-queries are not allowed in this context. Only scalar expressions are allowed.

I have looked at this question about Check Constraint - Subqueries are not allowed in this context.

Is there any way of achieving this without using a trigger?

回答1:

Note, what you really want is a foreign key constraint. That said, to get a "query" into a check you can write a function that contains the query and outputs a scalar value, then use that function in the check constraint.

CREATE FUNCTION myFunction (     @field DATATYPE(?) ) RETURNS VARCHAR(5) AS BEGIN     IF EXISTS (SELECT* FROM Table2 WHERE MYFIELD = @field)         return 'True'     return 'False' END 

Something like that. Not tested.

Then you can add it to your check like so

ALTER TABLE Table1     WITH CHECK ADD CONSTRAINT CK_Code     CHECK (myFunction(MYFIELD) = 'True') 


回答2:

You can't have sub queries inside check constraints. What you can do is use a UDF that returns a scalar value inside the check constraint.

Step 1: Create the table

USE CTBX GO  CREATE TABLE RawMaterialByGender  ( RMGID int primary key identity(1,1), RMID smallint foreign key references RawMaterialMaster(RMID), LeveLMasterID smallint foreign key references LevelMaster(LevelTextID), IsDeleted bit ) 

Step 2 : Create the UDF that returns a scalar

Create FUNCTION [dbo].[IsValidLevelMasterGender](@LevelMasterID smallint)      RETURNS bit     AS     BEGIN      DECLARE @count smallint;      DECLARE @return bit;       SELECT @count = count(LevelTextID)            FROM [LevelMaster]      WHERE LevelCategoryID = 3 AND IsActive = 1 AND LevelTextID=@LevelMasterID       IF(@count = 0)      SET @return = 'false';      ELSE      SET @return = 'true';       RETURN @return;      END;     GO 

Step 3 : Alter table to add the CHECK constraint

ALTER TABLE RawMaterialByGender  ADD CONSTRAINT check_LevelMasterID CHECK (dbo.IsValidLevelMasterGender(LeveLMasterID) = 'true') 


回答3:

ALTER TABLE Table1 ADD CONSTRAINT FK_Table1_Code FOREIGN KEY (MyField) REFERENCES Table2 (Field) ; 

Ref: http://msdn.microsoft.com/en-us/library/ms190273.aspx
Note: I haven't checked the above for syntax.



回答4:

First of all in your example you clearly need FK Constraint.

Another posibility is to use view with WITH CHECK OPTION and give access to user through it:

CREATE TABLE Table1(i INT PRIMARY KEY, CK_Code CHAR(1)); CREATE TABLE Table2(Field CHAR(1)); INSERT INTO Table2(Field) VALUES ('A'),('B'), ('C'); GO  CREATE VIEW v_Table1 AS SELECT * FROM Table1 WHERE CK_code IN (SELECT Field FROM Table2)  -- here goes your subquery check WITH CHECK OPTION; 

When you try to insert data that violates your "constraint" like:

INSERT INTO v_Table1(i, CK_Code) VALUES(10, 'D'); 

You will get:

The attempted insert or update failed because the target view either specifies WITH CHECK OPTION or spans a view that specifies WITH CHECK OPTION and one or more rows resulting from the operation did not qualify under the CHECK OPTION constraint.

The statement has been terminated.

LiveDemo



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!