web-dev-qa-db-fra.com

Sous-requêtes dans la contrainte de contrôle

J'ai la table conçue dans SQL-Server 2008 R2.

J'ai une colonne dans cette table qui doit être vérifiée par rapport à une autre table lors de l'insertion de données. 

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

Cela cause une erreur 

Les sous-requêtes ne sont pas autorisées dans ce contexte. Seules les expressions scalaires sont autorisées.

J'ai examiné cette question à propos de Contrainte de contrôle - Les sous-requêtes ne sont pas autorisées dans ce contexte .

Y a-t-il un moyen d'y parvenir sans utiliser de déclencheur?

25
Highland

Notez que vous voulez vraiment une contrainte de clé étrangère. Cela dit, pour obtenir une "requête" dans un contrôle, vous pouvez écrire une fonction qui contient la requête et génère une valeur scalaire, puis utilisez cette fonction dans la contrainte de contrôle.

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

Quelque chose comme ca. Pas testé.

Ensuite, vous pouvez l'ajouter à votre chèque comme si

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

Vous ne pouvez pas avoir de sous-requêtes dans les contraintes de vérification. Ce que vous pouvez faire est d'utiliser une fonction utilisateur qui renvoie une valeur scalaire dans la contrainte de vérification. 

Étape 1: Créer la 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
)

Étape 2: Créez la fonction utilisateur qui renvoie un scalaire

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

Étape 3: Modifiez le tableau pour ajouter la contrainte CHECK

ALTER TABLE RawMaterialByGender 
ADD CONSTRAINT check_LevelMasterID CHECK (dbo.IsValidLevelMasterGender(LeveLMasterID) = 'true')
7
ALTER TABLE Table1
ADD CONSTRAINT FK_Table1_Code FOREIGN KEY (MyField)
REFERENCES Table2 (Field) ;

Réf: http://msdn.Microsoft.com/en-us/library/ms190273.aspx
Remarque: Je n'ai pas vérifié la syntaxe ci-dessus.

3
shahkalpesh

Il y a des problèmes avec FK Constraint.

Другой возможностью является использование voir с WITH CHECK OPTION et plus encore

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;

Vous avez besoin de "ограничение", нарушают ваше "ограничение", например:

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

Ты получишь:

Попытка вставки или обновления завершилась неудачно, поскольку целевое представление либо задает AVEC CHECK OPTION, либо охватывает представление, которое задает AVEC CHECK OPTION, а одна или несколько строк, полученных в результате операции, не соответствуют ограничению CHECK OPTION.

Заявление было прекращено.

LiveDemo

0
Lukasz Szozda