2009-06-10 10 views
6

Voglio eseguire una query come questa:Una stored procedure può avere parametri dinamici da utilizzare in una clausola "IN"?

SELECT * FROM Studio WHERE Id IN (134, 144, 132, 138, 7432, 7543, 2566) 

ma la quantità di Id 's passati alla clausola è determinato solo in fase di esecuzione.

Devo utilizzare SQL dinamico o può essere eseguito con una procedura memorizzata?

UPDATE: Se l'opzione è disponibile, quale è il migliore?

Grazie.

+0

sono l'id del generato da input dell'utente? – Eric

+0

L'utente seleziona i record da cercare con una casella di controllo, ma non ha il controllo su cosa sia l'effettivo "Id". – orandov

+0

Quindi SQL dinamico non è una cattiva idea se non è soggetto ad iniezione ... ma prova la risposta che ho postato invece di essere al sicuro. – Eric

risposta

8

A seconda della versione di SQL Server, puoi farlo in due modi diversi.

Per Sql 2000/2005, è possibile utilizzare un parametro (tipo varchar) con un elenco delimitato di ID. Creare una UDF che analizzerebbe il varchar e restituirà una tabella contenente gli elementi. Quindi fai in modo che la tua clausola IN vada contro il tavolo (ad esempio ... IN (Seleziona ID FROM @ReturnTable)).

Ecco un esempio di ciò che il contenuto del UDF sarà simile: http://pietschsoft.com/post/2006/02/03/T-SQL-Parse-a-delimited-string.aspx

Per SQL 2008, è possibile fare la stessa cosa; tuttavia, invece di passare in un parametro varchar, puoi semplicemente passare al chase e passare un parametro Table. La clausola IN avrebbe comunque una sottoquery ma funzionerebbe lo stesso. In alternativa, una volta che hai il tavolo puoi semplicemente fare un Inner Join su di esso e aggirare la necessità della clausola IN.

MODIFICA: aggiunta UDF per l'analisi di un collegamento stringa delimitato.

+0

Poiché il tuo link non funziona più, condividerò questo che fa: http://jerrytech.blogspot.com/2008/04/no-split-in-sql-well-here-method-you .html –

0

In SQL 2008 è possibile utilizzare uno table valued parameter.

In SQL 2005 è necessario utilizzare l'SQL dinamico a meno che non si desideri passare l'elenco come XML e utilizzare l'elaborazione XML nella procedura per distruggere l'XML in una variabile di tabella.

+0

Non è necessario SQL dinamico per analizzare un elenco delimitato. Vedi la pagina di Erland Sommarskog, come menzionato da Alex. –

+0

Hey Remus, Non sono d'accordo. Lavoro nel 2005, inserisco i numeri in un'immagine e li analizzo utilizzando una UDF: http://www.sommarskog.se/arrays-in-sql-2005.html –

+0

true, penso che l'elaborazione delle stringhe sia un'alternativa valida e dovrei dirlo. Caffè privato post :) –

0

dichiarare una tabella @temp e dividere i valori in essa. allora si potrebbe fare

select * from Studio s inner join @temptable tb su s.ID = tb.ID

3

È assolutamente possibile farlo in una stored procedure.

creare una tabella temporanea all'interno della stored procedure e inserire i valori divisi sulla virgole o qualsiasi delimitatore poi fare questo

SELECT * FROM Studio WHERE Id IN (select id from temptable) 

quindi eliminare la tabella.

+0

Questa è probabilmente la soluzione migliore perché non si sa mai quanti dati puzzolenti si sta passando in quella stored procedure. È possibile migliorare in modo significativo le prestazioni utilizzando una tabella temporanea come quella se la quantità è elevata. –

1

Ecco una UDF che utilizzo da MSSQL 2000. L'ho trovata da qualche parte, mi dispiace, non ricordo dove.

Fondamentalmente, è possibile eseguire un join sull'UDF, dove il primo parametro è la stringa delimitata e il secondo parametro è il delimitatore.

SELEZIONA t1.somecolumn DA SomeTable t1 INNER JOIN dbo.Split (@delimitedVar, '') t2 ON t1.ID = t2.Element

CREATE FUNCTION [dbo].[Split] 
(
@vcDelimitedString varchar(max), 
@vcDelimiter varchar(100) 
) 
RETURNS @tblArray TABLE 
    (
    ElementID smallint IDENTITY(1,1), --Array index 
    Element varchar(1000) --Array element contents 
    ) 
AS 
BEGIN 
    DECLARE @siIndex smallint, @siStart smallint, @siDelSize smallint 
    SET @siDelSize = LEN(@vcDelimiter) 
    --loop through source string and add elements to destination table array 
    WHILE LEN(@vcDelimitedString) > 0 
    BEGIN 
     SET @siIndex = CHARINDEX(@vcDelimiter, @vcDelimitedString) 
     IF @siIndex = 0 
     BEGIN 
      INSERT INTO @tblArray VALUES(@vcDelimitedString) 
      BREAK 
     END 
     ELSE 
     BEGIN 
      INSERT INTO @tblArray VALUES(SUBSTRING(@vcDelimitedString, 1,@siIndex - 1)) 
      SET @siStart = @siIndex + @siDelSize 
      SET @vcDelimitedString = SUBSTRING(@vcDelimitedString, @siStart , LEN(@vcDelimitedString) - @siStart + 1) 
     END 
    END 
    RETURN 
END 
Problemi correlati