none
Contrainte Check " Subqueries are not allowed in this context " RRS feed

  • Question

  • Bonjour,

    J'ai une erreur lorsque j'essaye de créer une contrainte check

    ALTER TABLE PROGRAM_HC
    
    ADD CONSTRAINT CHK_PROGRAMHC_HCANUM CHECK ((CAST(LEN(HC_ANUM) as INT)<=				(select PROGRAM_LEN FROM PROGRAM WHERE PROGRAM_ID=PROGRAM_ID ))
    
    				or (HC_ANUM IS NULL))
    
    

    Je voudrais vérifier la taille de mon HC_NUM afin de savoir s'il correspond à la taille renseigné dans le PROGRAM_LEN

    et j'ai l'erreur suivante :

    Subqueries are not allowed in this context. Only scalar expressions are allowed.

    j'ai une table HC, PROGRAM, PROGRAM_HC

    J'ai vu des exemples de sous requête qui marchait dans des contraintes check mais pourquoi la mienne ne marche pas ? Qu'est ce que j'ai fait de mal ? x( 

    lundi 11 octobre 2010 11:50

Réponses

  • Bonsoir,

    Dans ce cas précis, il faut utiliser les triggers. (CREATE TRIGGER ... ON maTable FOR / AFTER INSERT / DELETE / UPDATE ... AS)

    ++


    MCDBA | MCITP SQL Server 2005 / SQL Server 2008 | LPI Linux 1
    • Marqué comme réponse Alex Petrescu mardi 12 octobre 2010 10:50
    lundi 11 octobre 2010 17:32
    Modérateur
  •  

    Contrairement à ce qui a été dit, il est parfaitement possible de créer une telle contrainte directement sans passer par des déclencheurs. Mais il faut procéder en deux temps :

    1) créer une fonction (UDF) qui récupère les données externes à la table

    2) intégrer cette fonction dans la contrainte CHECK.

    Exemple :


     

    CREATE FUNCTION dbo.F_CHECK_PROGRAM_LENGTH (@PROGRAM_ID INT)
    RETURNS INTEGER
    AS
    BEGIN
      RETURN (select PROGRAM_LEN
          FROM  PROGRAM
          WHERE PROGRAM_ID = @PROGRAM_ID);
    END;
    GO 
    
    
    Et le contrainte intégrant l'UDF :

     

    ALTER TABLE PROGRAM_HC
       ADD CONSTRAINT CHK_PROGRAMHC_HCANUM
         CHECK (LEN(HC_ANUM) <= dbo.F_CHECK_PROGRAM_LENGTH (PROGRAM_ID)
              OR (HC_ANUM IS NULL));
    GO 
    

                            
    A +

    Frédéric BROUARD, Spécialiste modélisation, SGBR relationnel, optimisation, langage SQL.
    Le site sur le langage SQL et les SGBD relationnels : http://sqlpro.developpez.com/
    Expert SQL Server http://www.sqlspot.com : audit, optimisation, tuning, formation
    Le blog sur SQL / MS SQL Server http://blog.developpez.com/sqlpro
    * * * * * Enseignant au CNAM PACA et à l'ISEN à Toulon * * * * *

     

     


    Frédéric BROUARD, Spécialiste modélisation, SGBR relationnel, optimisation, langage SQL * * * Le site sur le langage SQL et les SGBD relationnels : http://sqlpro.developpez.com/ * * * Expert SQL Server http://www.sqlspot.com : audit, optimisation, tuning, formation * * * Le blog sur SQL / MS SQL Server http://blog.developpez.com/sqlpro * * * Enseignant CNAM PACA, ISEN Toulon, CESI/EXIA Aix En Provence
    • Marqué comme réponse Olivierrrrrrr dimanche 17 octobre 2010 11:47
    dimanche 17 octobre 2010 11:01

Toutes les réponses

  • Bonjour,

    Comme l'indique le message ce n'est pas possible à ma connaissance (ou c'est nouveau dans une version récente mais cela m'étonnerait).

    Un lien vers ces exemples ? Cela ne serait pas une confusion avec le IN <Liste de valeurs> qui n'est pas une sous-requête ?

     


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
    lundi 11 octobre 2010 12:07
  • oui sans doute ! Comment puis je traduire cette contrainte alors ?

    Faire une procédure stickée qui renvoit vrai ou faux et je fais appel à cette fonction dans la contrainte check ? ça ma l'air un peu compliquée pour une si simple containte qu'en pensez vous ?

     

    lundi 11 octobre 2010 12:46
  • Bonsoir,

    Dans ce cas précis, il faut utiliser les triggers. (CREATE TRIGGER ... ON maTable FOR / AFTER INSERT / DELETE / UPDATE ... AS)

    ++


    MCDBA | MCITP SQL Server 2005 / SQL Server 2008 | LPI Linux 1
    • Marqué comme réponse Alex Petrescu mardi 12 octobre 2010 10:50
    lundi 11 octobre 2010 17:32
    Modérateur
  • Merci !
    mercredi 13 octobre 2010 06:30
  •  

    Contrairement à ce qui a été dit, il est parfaitement possible de créer une telle contrainte directement sans passer par des déclencheurs. Mais il faut procéder en deux temps :

    1) créer une fonction (UDF) qui récupère les données externes à la table

    2) intégrer cette fonction dans la contrainte CHECK.

    Exemple :


     

    CREATE FUNCTION dbo.F_CHECK_PROGRAM_LENGTH (@PROGRAM_ID INT)
    RETURNS INTEGER
    AS
    BEGIN
      RETURN (select PROGRAM_LEN
          FROM  PROGRAM
          WHERE PROGRAM_ID = @PROGRAM_ID);
    END;
    GO 
    
    
    Et le contrainte intégrant l'UDF :

     

    ALTER TABLE PROGRAM_HC
       ADD CONSTRAINT CHK_PROGRAMHC_HCANUM
         CHECK (LEN(HC_ANUM) <= dbo.F_CHECK_PROGRAM_LENGTH (PROGRAM_ID)
              OR (HC_ANUM IS NULL));
    GO 
    

                            
    A +

    Frédéric BROUARD, Spécialiste modélisation, SGBR relationnel, optimisation, langage SQL.
    Le site sur le langage SQL et les SGBD relationnels : http://sqlpro.developpez.com/
    Expert SQL Server http://www.sqlspot.com : audit, optimisation, tuning, formation
    Le blog sur SQL / MS SQL Server http://blog.developpez.com/sqlpro
    * * * * * Enseignant au CNAM PACA et à l'ISEN à Toulon * * * * *

     

     


    Frédéric BROUARD, Spécialiste modélisation, SGBR relationnel, optimisation, langage SQL * * * Le site sur le langage SQL et les SGBD relationnels : http://sqlpro.developpez.com/ * * * Expert SQL Server http://www.sqlspot.com : audit, optimisation, tuning, formation * * * Le blog sur SQL / MS SQL Server http://blog.developpez.com/sqlpro * * * Enseignant CNAM PACA, ISEN Toulon, CESI/EXIA Aix En Provence
    • Marqué comme réponse Olivierrrrrrr dimanche 17 octobre 2010 11:47
    dimanche 17 octobre 2010 11:01