2012-12-07 1 views
2

Utilisation de SQL Server J'essaie d'injecter une chaîne dans une instruction SQL basée sur une instruction if, notez que j'essaie de l'accomplir dans une procédure stockée.Procédure stockée SQL Server si chaîne d'injection d'instructions

Je reçois actuellement une erreur pour ce code:

Declare @topString varchar(240) 

IF @topRecords > 0 
SET @topString = 'top 500' 
ELSE 
SET @topString = '' 

SELECT @topString * FROM(//incorrect syntax near FROM 

SELECT top 500 c.Id as [Customer Id],.... 
    UNION 
    SELECT top 500 c.Id as [Customer Id],.... 
)as table1 
Order by 1 desc 

Modifier

if somethingTrue 
@whereCondition = '1 = 1 ' 
else 
@whereCondition = branch = @branch 

select * from table 
where @whereCondition AND etc... 

Correct

pour injection à l'intérieur d'une instruction if aller avec Jodrell
mais si vous avez besoin d'un top dynamique alors aller avec ce qui a été suggéré par Kaf.
merci à la fois pour l'aide!

Répondre

3

Vous ne pouvez pas injecter des parties d'instructions en tant que variables, mais vous pouvez modifier la plupart des valeurs des paramètres. Avoir une procédure stockée effectuer des opérations qui peuvent nécessiter des plans de requête différents, basé sur un paramètre est une mauvaise idée, les résultats de ce SP pourraient varier fortement en fonction de la valeur du paramètre @topRecords. Vous devez utiliser l'option RECOMPILE pour avertir le moteur de recherche, ce qui réduit considérablement les avantages des fournisseurs de services. Avez-vous envisagé d'avoir deux procédures stockées?

Si vous voulez le faire de manière dynamique, vous pouvez construire l'ensemble de l'instruction dynamiquement, en faisant une grande chaîne, puis l'exécuter.

Vous devez rechercher en utilisant sp_executesql pour exécuter le string/VarChar. Ensuite, les requêtes similaires bénéficieront de la réutilisation du plan de requête.

Comme toujours Sommarskog est un good reference.


Quelque chose comme ça

DECLARE @topString varchar(240); 
DECLARE @statement varchar(max); 

IF @topRecords > 0 
    SET @topString = 'TOP 500'; 
ELSE 
    SET @topString = ''; 

SET @statement = 'SELECT ' + @topString + ' * FROM 
    (
     SELECT TOP 500 c.Id as [Customer Id], .... 
     UNION 
     SELECT TOP 500 c.Id as [Customer Id], .... 
    ) table1 
    ORDER BY 1 DESC' 

/* Then execute @statement */ 
EXEC sp_executesql @statement 
+0

merci pour l'aide, je vais probablement aller avec ce que vous avez dit mais le problème est que le sql est vraiment très grand, alors maintenant j'ai besoin de finir un nombre infini de guillemets simples ... zzz – rtp

+0

@rtp Je ne peux pas nier sa douleur. J'essaye de faire mon SQL dynamique dans le client, si vous employez. Net il vient en grande partie gratuitement. – Jodrell

+0

@Jodrell +1 pour lire et répondre à quelque chose qui n'apparaissait pas sur le message original. – Kaf

4

Si vous voulez decide number of top records depending on @topRecords, vous pouvez le faire en utilisant un INT ou BIGINT en fonction du nombre d'enregistrements nécessaires.

DECLARE @top INT --This is declared as an int here 

IF @topRecords > 0 
    SET @top = 500 
ELSE 
    SET @top = 5000000 --Make it more than records if you need all 
           --or make it 0 if no records needed. 
           [email protected] has to be >=0 

--How to use it 
SELECT TOP (@top) * FROM YourTable 

EDIT: Votre question avait seulement une injection par le haut au départ. Cependant, si vous avez besoin de plus d'injections (selon votre question récente éditer) alors je suggère d'utiliser une requête dynamique selon @Jordell's answer.

+2

+1 'Top 0' ne fonctionnera pas. Cela renvoie zéro lignes. La plus grande valeur possible qui peut être passée est bigint '9223372036854775807'. On pourrait aussi utiliser 'OPTION (RECOMPILE)' pour que l'on prenne en compte la valeur réelle de 'TOP' si cela change le plan. –

+0

@MartinSmith oui, 0 est pour aucun enregistrement. s'il n'en a pas besoin. – Kaf

+0

Cela fonctionne mais, dans mes tests de toute façon sur SQL 2005. Une valeur littérale offre des performances supérieures à une variable. – Jodrell