2010-02-24 3 views
1

Comme ceci:Les paramètres de sqlcommand peuvent-ils fournir le nom des colonnes de la base de données?

select * from foo where @nameofdbcolumnprovidedbyparam = 1 ? 

Chaque fois que j'essayer avec SqlDataSource ou plus tarder je reçois des erreurs telles que:

Erreur de syntaxe convertissant la valeur nvarchar « foo » à une colonne de type de données int.

+0

Je pense que vous pourriez être confus entre passer des paramètres à SQL et contraindre dynamiquement votre SQL? – Kane

+0

insérez-vous ou sélectionnez-vous un enregistrement? –

+0

@asad le select est assez explicite. –

Répondre

0

Je pense que dans ce cas, vous devez générer dynamiquement le SQL sans liaison de paramètre. La liaison de paramètres est généralement destinée à l'assainissement d'entrée de données et non à la personnalisation de la structure de requête.

- modifier -

cette logique peut répondre à vos besoins

SELECT * 
FROM Line 
WHERE (@foo = 'monTotal' AND monTotal IS NULL) 
    OR (@foo = 'monUnitPrice' AND monUnitPrice IS NULL) 
+0

Merci, pourriez-vous me donner un exemple de la façon de générer dynamiquement sql? – Phil

+1

utilisez simplement des opérations de chaîne. x + y + z où y est votre SQL dynamique. assurez-vous simplement que vos chaînes sont codées en dur dans l'application (pour vous protéger de l'injection SQL) –

+0

oh merci beaucoup! c'était beaucoup plus simple que prévu. – Phil

0

Changez votre SQL (dans votre code):

string sqlToExecute = "EXEC ('SELECT * from foo WHERE ' + @nameofdbcolumnprovidedbyparam + ' =1')"; 

Maintenant Sql Server exécutera votre requête et le substitut dans le paramètre dans le SQL, donc si vous l'avez passé en tant que "Column1", le Sql réel exécuté serait:

"EXEC('SELECT * from foo WHERE Column1 =1')"; 

Le « exec (« ») » bits permet Sql d'exécuter un morceau de dynamique construit Sql


Ce n'est pas idéal car il vous rend plus vulnérables aux attaques par injection SQL qui sont pas bon, donc ce serait mieux si vous pouviez construire le Sql à exécuter en limitant le nombre de colonnes sélectionnables à une liste contrôlée et en basculant l'instruction en cours d'exécution en fonction de cela. Si ce n'est pas possible, alors l'autre solution serait d'utiliser une procédure stockée qui prend des paramètres nullables, tels que:

CREATE PROCEDURE dbo.MyProc 
@param1 VARCHAR(10), 
@param2 VARCHAR(10) 
@param3 VARCHAR(10) 
AS 
BEGIN 
SELECT * 
FROM dbo.foo 
WHERE ISNULL(@param1, column1) = column1 
AND ISNULL(@param2, column2) = column2 
AND ISNULL(@param3, column3) = column3 
END 

En appelant cette procédure et en passant NULL pour les colonnes que vous ne se soucient pas, seulement les enregistrements de la table "foo" qui correspondent à la colonne que vous recherchez seront retournés.

+0

L'exec devrait vraiment être un dernier recours - AFAIK le moteur ne peut pas se souvenir (cache + stats) de quoi que ce soit à faire avec un exec. –

+0

Je crois que c'est le seul moyen d'utiliser le paramétrage SQL, tout en restant ouvert aux attaques par injection SQL. – Meff

+0

@Hassan Syed, Sql Server est beaucoup mieux à la mise en cache des plans d'exécution pour à peu près tout ce qu'il fait dans les versions plus récentes, donc ce n'est plus un souci. Ma seule préoccupation serait le risque d'injection de Sql inhérent à cette approche. Cela dit, il en va de même pour la concaténation de chaînes sans désinfecter fortement l'entrée de l'utilisateur. – Rob

0

Vous pouvez le faire avec un cas

WHERE ( 
CASE @macolumn 
WHEN 'toto' THEN toto 
WHEN 'tutu' THEN tutu 
WHEN 'titi' THEN titi 
ELSE null END 
) = 1 

C'est une petite bouchée laid, mais il fonctionne et vous ne devez pas faire sql dynamique.

Questions connexes