Um procedimento armazenado pode ter parâmetros dinâmicos a serem usados ​​em uma cláusula "in"?

StackOverflow https://stackoverflow.com/questions/977021

Pergunta

Eu quero executar uma consulta como esta:

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

Mas a quantidade de IdentidadePassado para a cláusula IN é determinado apenas em tempo de execução.

Eu tenho que usar o SQL dinâmico ou isso pode ser feito com um procedimento armazenado?

ATUALIZAR:Se qualquer uma das opções estiver disponível, qual é melhor?

Obrigado.

Foi útil?

Solução

Dependendo da sua versão do SQL Server, você pode fazer essa de duas maneiras diferentes.

Para o SQL 2000/2005, você pode usar um parâmetro (tipo VARCHAR) que possui uma lista delimitada de IDs. Crie um UDF que analisasse o Varchar e retorne uma tabela que contém os itens. Em seguida, faça sua cláusula no IN vá contra a tabela (ou seja ... em (selecione ID de @RETURNTABLE)).

Aqui está um exemplo de como seria o conteúdo da UDF:http://pietschsoft.com/post/2006/02/03/t-sql-parse-delimited-string.aspx

Para o SQL 2008, você pode fazer a mesma coisa; No entanto, em vez de passar em um parâmetro VARCHAR, você pode simplesmente cortar para a perseguição e passar em um parâmetro de tabela. A cláusula in ainda teria uma subconsulta, mas funcionaria da mesma forma. Como alternativa, depois de ter a tabela, você pode simplesmente fazer uma junção interna e contornar a necessidade da cláusula In.

Editar: Adicionado UDF para analisar um link de string delimitado.

Outras dicas

Solução descrita aqui:

Matrizes e listas no SQL Server 2005

Um texto SQL de Erland Sommarskog, SQL Server MVP

http://www.sommarskog.se/arrays-in-sql-2005.html

Você pode absolutamente fazer isso em um procedimento armazenado.

Crie uma tabela de temperatura dentro do procedimento armazenado e insira os valores divididos nas vírgulas ou em qualquer delimitador, faça isso

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

Em seguida, exclua a tabela.

Aqui está um UDF que eu uso desde o MSSQL 2000. Encontrei isso em algum lugar - desculpe, não me lembro onde.

Basicamente, você pode fazer uma junção no UDF, onde o primeiro parâmetro é a sequência delimitada, e o segundo param é o delimitador.

Selecione T1.Somecolumn de algum consumo interno T1 DBO.SPLIT (@DelimitedVar, ',') T2 em 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

No SQL 2008, você pode usar um Tabela Parâmetro avaliado.

No SQL 2005, você deve usar o SQL dinâmico, a menos que queira passar a lista como XML e usar o processamento XML no procedimento para destruir o XML em uma variável de tabela.

Declare uma tabela @temp e divida os valores nela. Então você poderia fazer

Selecione * do Studio S Inner Junção @temptable TB em s.id = tb.id

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top