2011-06-13 4 views
4

J'ai l'instruction d'exécution suivante qui crée une table (en utilisant les données d'une autre procédure), insère les valeurs dans une table temporaire, ajoute une colonne d'image (car elles ne peuvent pas être inclus dans le groupe), et le met à jour en fonction des critères d'une autre table temporaire (les champs de table résultant est donc utilisé dans un rapport de SSRS, donc je dois retenir le type de données d'image):La vérification de l'existence d'une colonne dans une table temporaire retourne toujours false dans SQL Server

EXEC ('SELECT ' + @COL_TO_GROUP_BY + @COL_ADDITONAL + @sColVals + ' INTO 
#RESULTS_TABLE from (' + @SQL_STATEMENT + ') A ' + @WHERE_CLAUSE + ' GROUP BY ' + 
@COL_TO_GROUP_BY + 

' ALTER TABLE #RESULTS_TABLE 
ADD IMAGE_DATA IMAGE 

IF EXISTS(SELECT * FROM tempdb.INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 
''COLUMN_A'' and TABLE_NAME LIKE ''#RESULTS_TABLE%'') 
BEGIN 
    UPDATE #RESULTS_TABLE 
    SET IMAGE_DATA = FILE_DATA 
    FROM #RESULTS_TABLE A, #IMAGE_TABLE B 
    WHERE A.COLUMN_A = B.COLUMN_A 
END 

SELECT * FROM #RESULTS_TABLE') 

le problème est que, que COLUMN_A existe ou non, la colonne pour IMAGE_DATA est toujours NULL. Existe-t-il un autre moyen d'obtenir des données dans la colonne IMAGE_DATA? S'il vous plaît aider!

Note: Je vais pas accepter toutes les réponses qui concluent que le problème est lié au contenu d'autres tables, plus précisément de la clause WHERE. J'ai fait plusieurs validations pour m'assurer que les conditions peuvent être vraies et fausses (lignes correspondantes, pas de lignes correspondantes, etc.). Donc, cela exclut l'énoncé conditionnel. Merci.

EDIT:

Je ne suis toujours pas tout à fait sûr de ce que la cause exacte de c'était, mais je fini par créer une table temporaire globale et couru deux procédures distinctes, maintenant il semble fonctionner très bien. J'ai dû accepter la réponse qui correspondait le mieux à ma propre solution. Toutes les réponses et les commentaires étaient très viables. Merci!

+0

Tout d'abord je voudrais essayer d'omettre la condition 'WHERE A.COLUMN_A = B.IMAGE_VALUE' il me semble que cela suffit pour trouver la bonne ligne par' OBJ_ID' –

+0

Merci d'avoir signalé cela. Dans mon cas, j'ai besoin d'avoir les deux conditions parce qu'il y a des lignes avec des OBJ_ID en double. J'ai simplifié mon code original et j'aurais dû le retirer aussi car cela semble trompeur. Je vais éditer la question. –

+0

Je ne sais pas si cela aide, mais je pense que vous pouvez ajouter la colonne image dans votre instruction select comme ceci 'cast (null comme image) comme IMAGE_DATA' sans avoir à l'ajouter à la clause group by car c'est une constante. BTW, pourquoi avez-vous besoin de tester si la colonne existe? –

Répondre

2

Correct.

Au moment de la compilation, la colonne n'existe pas. En d'autres termes, SQL Server examine l'ensemble des commandes et les analyse/compile. Les effets d'un ALTER TABLE dans le code ne seront pas visibles aux commandes ultérieures.

Vous devez faire ALTER TABLE séparément la mise à jour

Remarque: Pour SQL Server 2005, vous auriez varbinary (max) qui est beaucoup plus souple et de supprimer une certaine complexité

+0

Merci pour votre réponse. J'utilise SQL Server 2008. J'ai essayé de convertir la colonne image en varbinary (max), et même en varbinary à partir de binary (par d'autres suggestions) mais cela me donne du charabia, donc ce n'était pas une option. Pouvez-vous clarifier comment je devrais faire une ALTER TABLE séparément de la mise à jour? L'exécution de deux instructions EXEC est hors de portée pour la table temporaire. Merci. –

3

Vous avez plusieurs problèmes dans votre script:

  • TempDB n'est pas le nom correct de tempdb. Votre code se casse sur un serveur installé avec un classement sensible à la casse. Utilisez toujours le cas approprié pour tous les noms de bases de données. Votre code est susceptible de se rompre de la même manière sur les noms de colonne de résultat, comme COLUMN_A, s'il est exécuté sous un déploiement sensible à la casse.
  • La logique est incorrecte sous la simultanéité: la session A verra la table #temp de la session B et effectuera des actions incorrectes.
  • Un simple test montre que les colonnes sont visibles:

.

EXEC ('SELECT * INTO #RESULTS_TABLE from 
    (select *, newid() as COLUMN_A from master..spt_values) A; 
ALTER TABLE #RESULTS_TABLE 
ADD IMAGE_DATA varbinary(max); 
IF EXISTS(SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 
''COLUMN_A'' and TABLE_NAME LIKE ''#RESULTS_TABLE%'') 
BEGIN 
    update #RESULTS_TABLE 
     set IMAGE_DATA = 0xBAADF00D; 
END 
SELECT * FROM #RESULTS_TABLE') 

Ce test montre que la colonne a été mis à jour, de sorte que le chèque de EXISTE réussi. La conclusion évidente est que dans votre cas, la jointure OBJ_ID entre #RESULTS_TABLE et #IMAGE_TABLE ne trouve aucune correspondance, ce qui est un problème qui dépend entièrement du contenu de vos tables.

Modifier

Vous pouvez faire le COLUMN_A être dynamique, il fonctionne toujours très bien lorsqu'il est testé:

declare @cn sysname = case 
     when RAND() * 100 >= 50 then 'COLUMN_A' 
     else 'COLUMN_B' end; 

EXEC (N'SELECT * INTO #RESULTS_TABLE from (
    select *, newid() as ' + @cn + N' from master..spt_values) A; 
... 
+0

Merci pour votre réponse. S'il vous plaît voir les modifications à la question. Bare avec moi car c'est ma première question sur ce forum, j'aurais donc dû poser la question plus clairement la première fois. Je vais essayer d'utiliser la procédure que vous avez utilisée pour votre test. –

+0

Pas d'offense, mais chaque fois que je suis confronté à «votre mot contre un comportement testé», je choisis un «comportement testé». La balle est dans votre camp, vous devez prouver que la branche IF n'est pas prise. –

+0

J'ai regardé votre script et je me suis rendu compte qu'il y avait une différence dans la façon dont vous l'avez exécuté par rapport à ce que j'avais. Mon script ne crée pas explicitement COLUMN_A. COLUMN_A apparaît en fonction du contenu extrait d'une autre procédure (une autre table) et est donc dynamique. Vous avez raison, si je le fais de cette façon, ça fonctionne bien (et je n'aurais probablement pas besoin de faire la vérification du tout dans ce cas). Je pense que le problème est avec les colonnes créées dynamiquement. –

3

Vous pouvez vérifier si la colonne existe dans le tableau temporaire en utilisant ..

IF EXISTS (SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'Column' AND TABLE_NAME LIKE '#TempTable%') 
    PRINT 'Column exists' 
ELSE 
    PRINT 'Column doesn''t exists' 
Questions connexes