2008-09-23 3 views
5

J'écrivais un extrait SQL (apparemment) direct qui supprime une colonne après s'être assuré que la colonne existe.
Le problème: si la colonne n'existe pas, le code à l'intérieur la clause IF se plaint de ne pas trouver la colonne! Eh bien, doh, c'est pourquoi c'est dans la clause IF!
Donc ma question est, pourquoi un morceau de code qui ne devrait pas être exécuté donner des erreurs?Pourquoi un bloc T-SQL donne-t-il une erreur même s'il ne devrait même pas être exécuté?

est ici l'extrait:

IF exists (select * from syscolumns 
    WHERE id=object_id('Table_MD') and name='timeout') 
BEGIN 
    ALTER TABLE [dbo].[Table_MD] 
     DROP COLUMN timeout 
END 
GO 

... et voici l'erreur:

Error executing SQL script [...]. Invalid column name 'timeout'

J'utilise Microsoft SQL Server 2005 Express Edition.

Répondre

10
IF exists (select * from syscolumns 
    WHERE id=object_id('Table_MD') and name='timeout') 
BEGIN 
    DECLARE @SQL nvarchar(1000) 
    SET @SQL = N'ALTER TABLE [dbo].[Table_MD] DROP COLUMN timeout' 
    EXEC sp_executesql @SQL 
END 
GO 

Raison: Lorsque le serveur Sql compile le code, ils vérifient pour les objets utilisés (si elles existent) . Cette procédure de vérification ignore les constructions "IF", "WHILE", etc ... et vérifie simplement tous les objets utilisés dans le code.

+0

Correct. Vous obtiendrez également cette erreur s'il existe des tables temporaires que le sproc utilise. – ConcernedOfTunbridgeWells

+0

Pour clarifier, si une table temporaire existe alors les colonnes seront vérifiées lorsque vous compilez le sproc. Lorsque le sproc crée réellement la table (par exemple avec un select into), vous devrez peut-être supprimer la table avant de recompiler le sproc. – ConcernedOfTunbridgeWells

+0

Ceci est une très bonne réponse :) –

0

Il ne peut jamais être exécuté, mais il est analysé pour la validité par SQL Server. La seule façon de « contourner » est de construire un bloc de sql dynamique puis exécuter sélectivement

0

Voilà comment je l'ai eu à travailler:

intérieur de la clause IF, j'ai changé la commande ALTER ... DROP ... avec exec ('ALTER ... DROP ...')

Il semble que le serveur SQL effectue une vérification de la validité du code lors de l'analyse, et voit qu'une colonne inexistante est référencée quelque part (même si ce morceau de code ne sera jamais exécuté).
L'utilisation de la commande exec(ute) encapsule le code problématique dans une chaîne, l'analyseur ne se plaint pas et le code est uniquement exécuté si nécessaire. est ici l'extrait modifié:

IF exists (select * from syscolumns 
    WHERE id=object_id('Table_MD') and name='timeout') 
BEGIN 
    exec ('ALTER TABLE [dbo].[Table_MD] DROP COLUMN timeout') 
END 
GO 
0

Par ailleurs, il y a un problème similaire dans Oracle, et une solution de contournement similaire en utilisant la clause « exécution immédiate ».

Questions connexes