2009-08-29 6 views
3

L'exécution de l'instruction suivante avec SQL Server 2005 (Mes tests via SSMS) aboutit à la réussite de la première exécution et à l'échec des exécutions ultérieures.La sélection échoue avec les colonnes Nonexisitent

IF OBJECT_ID('tempdb..#test') IS NULL 
    CREATE TABLE #test (GoodColumn INT) 
IF 1 = 0 
    SELECT BadColumn 
    FROM #test 

Ce que cela signifie est que quelque chose compare les colonnes que je suis dans ma déclaration un accès de sélection contre les colonnes qui existent sur une table lorsque le script est « compilé ». Pour mes fins, c'est une fonctionnalité indésirable. Ma question est la suivante: y a-t-il quelque chose qui puisse être fait pour que ce code s'exécute avec succès à chaque exécution, ou si ce n'est pas possible, peut-être que quelqu'un pourrait expliquer pourquoi la fonctionnalité démontrée est souhaitable. Les seules solutions que j'ai actuellement est d'envelopper le select avec EXEC ou select *, mais je n'aime pas l'une ou l'autre de ces solutions.

Merci

Répondre

0

Que ce soit du point de vue d'un programmeur ou non ce comportement est « souhaitable » est discutable bien sûr - il se résume à la différence entre les langues et dynamiquement typés statiquement typés. Du point de vue des performances, il est souhaitable car SQL Server a besoin d'informations complètes pour compiler et optimiser le plan d'exécution (ainsi que les plans d'exécution du cache). En un mot, T-SQL est pas un langage interprété ou typé dynamiquement, et donc vous ne pouvez pas écrire le code comme ceci. Vos options sont soit d'utiliser EXEC, soit d'utiliser une autre langue et d'y incorporer les requêtes SQL.

3

Si vous mettez:

IF OBJECT_ID('tempdb..#test') IS NOT NULL 
    DROP TABLE #test 
GO 

Au début, le problème disparaîtra, car le lot va s'analysable avant la table existe #test.

Ce que vous demandez, c'est que le système reconnaisse que "1 = 0" sera toujours faux. Si cela était vrai (ce qui pourrait potentiellement être le cas dans la plupart des situations de la vie réelle), alors vous voudriez probablement savoir que vous étiez sur le point de lancer quelque chose qui causerait un échec.

Si vous laissez tomber la table temporaire, puis créez une procédure stockée qui fait la même:

CREATE PROC dbo.test 
AS 
BEGIN 
    IF OBJECT_ID('tempdb..#test') IS NULL 
    CREATE TABLE #test (GoodColumn INT) 

    IF 1 = 0 
    SELECT BadColumn 
    FROM #test 
END 

Ensuite, ce sera avec plaisir créé et vous pouvez l'exécuter autant de fois que vous le souhaitez.

Rob

+0

J'ai essayé deux solutions dans SQL et les deux échoue avec « nom de colonne non valide « BadColumn »." –

+0

Si l'objet temporaire n'existe pas, alors je peux créer ce proc dbo.test, et l'exécuter à plusieurs reprises Si l'objet temporaire existe, alors vous obtiendrez l'erreur –

+0

+1 pour une bonne explication. table signifie que le BadCOlumn est introuvable et que la "résolution de nom différée" s'applique à l'utilisation ultérieure. – gbn

0

Ce problème est également visible dans ces situations:

IF 1 = 1 
    select dummy = GETDATE() into #tmp 
ELSE 
    select dummy = GETDATE() into #tmp 

Bien que la deuxième déclaration est jamais exécuté la même erreur se produit. Il semble que la validation du premier niveau du moteur de recherche ignore toutes les instructions conditionnelles.

0

Vous dites que vous avez des problèmes avec la requête suivante et que c'est parce que l'objet existe déjà. Il a recommandé que vous déposez vos tables temporaires dès que possible lorsque vous avez terminé avec elle.

En savoir plus sur les performances de la table temporaire: SQL Server performance.com

Questions connexes