Je dois vérifier si certains enregistrements avec des conditions spécifiques existent dans une table qui peut ne pas exister et je dois le faire dans une fonction scalaire.

Voici mon code:

CREATE FUNCTION CheckIfRecordsExistInTestTable()
RETURNS INT
BEGIN
DECLARE @Result INT
SELECT @Result = 
CASE WHEN OBJECT_ID('TestTable') IS NULL THEN 0
ELSE
CASE WHEN EXISTS(SELECT * FROM TestTable) THEN
1
ELSE
0
END
END
RETURN @Result
END

En l'essayant dans SQL Server en exécutant l'instruction suivante:

SELECT dbo.CheckIfRecordsExistInTestTable()

Chaque fois que TestTable existe, il renvoie mon résultat attendu. Mais chaque fois que ce n'est pas le cas, SQL Server lève une exception (nom d'objet invalide 'TestTable') et je ne peux pas obtenir ce que j'attends (je veux une valeur de retour nulle dans cette situation). Alors, que proposez-vous de faire pour ce problème qui peut être codé en fonction scalaire?

5
hamid reza 3 janv. 2016 à 12:07

3 réponses

Meilleure réponse

Essayez de changer le function comme ceci

CREATE FUNCTION Checkifrecordsexistintesttable() 
returns INT 
  BEGIN 
      DECLARE @Result INT 

      IF Object_id('TestTable') IS NULL 
        SET @Result = 0 
      ELSE 
        SELECT @Result = CASE 
                           WHEN EXISTS(SELECT 1 FROM testtable) THEN 1 
                           ELSE 0 
                         END 

      RETURN @Result 
  END; 

Pour en savoir plus sur la raison de l'erreur que vous obtenez, vérifiez la réponse de Martin.

4
Pரதீப் 3 janv. 2016 à 10:54

L'autre réponse donne une solution de contournement correcte.

Quant à savoir pourquoi vous rencontrez le problème ...

Il s'agit d'une erreur de compilation.

Si l'instruction fait référence à un objet inexistant, la compilation est différée juste avant l'exécution, mais finalement, toute l'instruction doit être compilée dans un plan d'exécution avant d'être exécutée.

Cela échoue lorsque la table n'existe pas et que l'exécution de cette instruction ne commence même pas.

(Plan d'exécution qu'il tente de créer - en utilisant un prédicat passthru pour éviter l'évaluation de la condition si le CASE n'est pas satisfait)

enter image description here

Dans la solution de contournement, SELECT contre testtable est déplacé dans une autre instruction . La compilation de cette instruction est toujours différée et comme l'instruction n'est jamais exécutée, tout fonctionne correctement.

5
Martin Smith 3 janv. 2016 à 11:05

Fonction de mise à jour comme celle-ci:

CREATE FUNCTION CheckIfRecordsExistInTestTable()
RETURNS INT
BEGIN
DECLARE @Result INT
SELECT @Result = case when count(1) = 0 then 0 else 1 end  from sys.tables where name = 'TestTable'

RETURN @result

END 
0
The Hill Boy 5 janv. 2016 à 11:01