2012-07-20 6 views
0

Tous, je le tableau suivant appelé Foo qui est la sortie d'un PIVOT complexe requêtedynamique clause SQL where

Example Result Set

J'ai besoin de supprimer des lignes dans ce tableau qui ont (DB1, DB2, DB3) tous NULL. Pour ce faire, normalement, nous pourrions utiliser quelque chose comme

DELETE FROM Foo 
WHERE [DB1] IS NULL 
    AND [DB2] IS NULL 
    AND [DB3] IS NULL; 

mais le problème est que ce code est appelé à partir de C# et les colonnes (DB1, DB2, DB3) passera de l'exécution à l'exécution.

Comment est-ce que je peux faire ceci dynamiquement?

Merci pour votre temps.

Édition1. J'ai une autre table Bar qui contient les colonnes DB#, donc il est possible d'utiliser cette table SELECT DISTINCT ... pour obtenir la liste des colonnes dont j'ai besoin dans la clause WHERE. Cependant, je n'ai jamais fait cela avant et je ne sais pas par où commencer ... Toute aide est appréciée.

Édition2. Je ne peux en aucun cas utiliser C#. Le code C# est un analyseur de SQL et fonctionne avec le fichier .sql donné. Cela doit être fait entièrement en SQL.

Répondre

1

sp_executesql permet d'exécuter une chaîne SQL construite en script SQL.

http://msdn.microsoft.com/en-us/library/ms188001.aspx

À partir de votre table de bar

create proc DumpFooJunk 
as 
begin 
    declare @strCols nvarchar(max) 
    select @strCols = N'' 
    select @strCols = @strCols + ' AND ' + name + ' IS NULL ' from [bar] 
    select @strCols = N'DELETE FROM [foo] WHERE ' + substring(@strCols,5,LEN(@strcols)) 
    select @strCols 
    -- exec sp_executesql @strCols 
end 
+0

Merci pour ça. Cela m'a donné quelques idées, mais il y a toujours la question du nom ici. Comment l'obtenir? Aussi votre sous-chaîne commence à 5, pourquoi? Les longueurs des noms (c'est-à-dire DB1 etc.) sont de longueur variable. Merci pour votre temps. – MoonKnight

+0

la chaîne commence à 5 car elle est construite avec un 'AND' supplémentaire au début. Si vous le souhaitez, vous pouvez mettre ce code dans une procédure stockée et l'appeler ainsi - voir Modifier. Ou voulez-vous dire comment accéder au sql? décommentez simplement la ligne SQL sp_execute. – podiluska

+0

Ce sera dans un SP. Mais le problème demeure, même avec ce que vous avez fourni - comment puis-je obtenir les noms de colonnes dont j'ai besoin. Voir Edit1. Encore une fois, merci pour votre temps. – MoonKnight

1

Vous pouvez construire dynamiquement votre clause WHERE en utilisant StringBuilder, en supposant que le code C# est conscient des colonnes qui doivent être présentes dans la sortie.

Généralement, lorsque vous faites cela, vous voulez inclure des espaces réservés aux paramètres dans la clause WHERE dynamique, et ajouter des paramètres dynamiquement à la requête afin d'éviter l'injection SQL. Cependant, dans ce cas, il n'y a pas de valeurs variables. Juste concaténer les parties de la clause WHERE dynamiquement en C#.

+0

Pour diverses raisons, je ne peux pas utiliser C# pour m'aider de toute façon. Le code C# est un analyseur pour SQL et exécute les fichiers SQL Script à la volée.Cela doit être fait dans le fichier de script SQL. Merci pour votre temps. – MoonKnight

0

Essayez d'obtenir les colonnes par leur valeur d'index si elles sont toujours les mêmes positions et obtenir les noms d'en-tête de colonne, puis construire votre instruction SQL en utilisant leur.

par exemple.

string colHeader1 = (string)dr[3]; 
string colHeader2 = (string)dr[4]; 
string colHeader3 = (string)dr[5]; 
+0

Je ne peux pas utiliser C#. Voir le commentaire que j'ai fait ci-dessus. Merci beaucoup ... – MoonKnight

1

En dehors de la construction du WHERE dynamique, vous pouvez aussi essayer quelque chose comme ceci:

DELETE FROM Foo 
WHERE 
    (0 = @db1 AND [DB1] IS NULL) 
    AND (0 = @db2 AND [DB2] IS NULL) 
    AND (0 = @db3 AND [DB3] IS NULL) 
    -- Etc... 
; 

En définissant des paramètres liés @db_-0, vous pouvez effectivement « turn-off » le IS NULL correspondant. Donc, il suffit de mettre ceux qui doivent être testés à une valeur différente de 0.

+0

Merci, mais à ce stade, je ne peux pas supposer que les noms (DB1, DB2, etc.) seront consistants (ils pourraient être n'importe quoi) et il pourrait y avoir un certain nombre d'entre eux. Comme je l'ai dit dans l'édition je peux obtenir ces noms d'une autre table 'Bar' où je peux' SELECT DISTINCT ... ', mais je ne sais toujours pas comment construire la clause' WHERE' dont j'ai besoin. Merci pour votre temps ... – MoonKnight

+0

@Killercam Voulez-vous dire que vous stockez réellement le champ _names_ dans l'autre table? Si oui, vous avez de plus gros problèmes;) Si non, il suffit de lister tous les champs possibles dans ce 'WHERE'. –

+0

J'ai accepté la réponse ci-dessus. En effet, je l'obtenais d'une autre table, je n'avais aucune idée de comment faire cela et @podiluska est venu avec une solution fantastique! Merci encore pour votre temps... – MoonKnight