可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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