Pergunta

Existe uma graciosa maneira de lidar com a passagem de uma lista de ids como um parâmetro para um procedimento armazenado?

Por exemplo, eu quero departamentos 1, 2, 5, 7, 20 retornado pelo meu procedimento armazenado.No passado, eu passei em uma lista delimitada por vírgulas de ids, como o código abaixo, mas me sinto muito sujo fazê-lo.

O SQL Server 2005 é a minha única limitação aplicável, eu acho.

create procedure getDepartments
  @DepartmentIds varchar(max)
as
  declare @Sql varchar(max)     
  select @Sql = 'select [Name] from Department where DepartmentId in (' + @DepartmentIds + ')'
  exec(@Sql)
Foi útil?

Solução

Erland Sommarskog tem mantido a autorização resposta a esta questão, durante os últimos 16 anos: Matrizes e Listas no SQL Server.

Há pelo menos uma dúzia de maneiras para passar uma matriz ou lista para uma consulta;cada um tem seus próprios prós e contras.

Eu realmente não posso recomendar o suficiente para leia o artigo para saber sobre as diferenças entre todas essas opções.

Outras dicas

Sim, a solução actual é propenso a ataques de injeção de SQL.

A melhor solução que eu encontrei é usar uma função que divide o texto em palavras (há alguns postado aqui, ou você pode usar um presente do meu blog) e, em seguida, aderir à sua mesa.Algo como:

SELECT d.[Name]
FROM Department d
    JOIN dbo.SplitWords(@DepartmentIds) w ON w.Value = d.DepartmentId

Você pode usar XML.

E. g.

declare @xmlstring as  varchar(100) 
set @xmlstring = '<args><arg value="42" /><arg2>-1</arg2></args>' 

declare @docid int 

exec sp_xml_preparedocument @docid output, @xmlstring

select  [id],parentid,nodetype,localname,[text]
from    openxml(@docid, '/args', 1) 

O comando sp_xml_preparedocument é construído em.

Isso produziria o resultado:

id  parentid    nodetype    localname   text
0   NULL        1           args        NULL
2   0           1           arg         NULL
3   2           2           value       NULL
5   3           3           #text       42
4   0           1           arg2        NULL
6   4           3           #text       -1

que tem tudo (mais?) do que você precisa.

Um método que você pode querer considerar se você estiver indo para trabalhar com valores muito é gravá-los em uma tabela temporária em primeiro lugar.Então você acabou de se juntar a ela como normal.

Desta forma, você está apenas a análise de uma vez.

É mais fácil utilizar um dos 'Split' UDFs, mas muitas pessoas têm postado exemplos de pessoas, eu pensei em ir para um caminho diferente ;)

Este exemplo cria uma tabela temporária para participar em (#tmpDept) e preenchê-lo com o departamento de identificação do que é passado.Eu estou supondo que você está, separando-os com vírgulas, mas você pode -- claro -- alterá-lo para o que você quiser.

IF OBJECT_ID('tempdb..#tmpDept', 'U') IS NOT NULL
BEGIN
    DROP TABLE #tmpDept
END

SET @DepartmentIDs=REPLACE(@DepartmentIDs,' ','')

CREATE TABLE #tmpDept (DeptID INT)
DECLARE @DeptID INT
IF IsNumeric(@DepartmentIDs)=1
BEGIN
    SET @DeptID=@DepartmentIDs
    INSERT INTO #tmpDept (DeptID) SELECT @DeptID
END
ELSE
BEGIN
        WHILE CHARINDEX(',',@DepartmentIDs)>0
        BEGIN
            SET @DeptID=LEFT(@DepartmentIDs,CHARINDEX(',',@DepartmentIDs)-1)
            SET @DepartmentIDs=RIGHT(@DepartmentIDs,LEN(@DepartmentIDs)-CHARINDEX(',',@DepartmentIDs))
            INSERT INTO #tmpDept (DeptID) SELECT @DeptID
        END
END

Isso permitirá que você para passar um id de departamento, vários identificação com vírgulas entre eles, ou até mesmo vários identificação com vírgulas e espaços entre eles.

Então, se você fez algo como:

SELECT Dept.Name 
FROM Departments 
JOIN #tmpDept ON Departments.DepartmentID=#tmpDept.DeptID
ORDER BY Dept.Name

Você gostaria de ver os nomes de todos do departamento de IDs de que você passou em...

Novamente, isso pode ser simplificada usando-se uma função para preencher a tabela temporária...Eu, principalmente, o fez sem um só para matar o tédio :-P

-- Kevin Fairchild

Um super XML Método, se você quiser usar um procedimento armazenado e passar a lista separada por vírgula do Departamento de IDs :

Declare @XMLList xml
SET @XMLList=cast('<i>'+replace(@DepartmentIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from @XMLList.nodes('i') x(i))

Todo o crédito vai para o Guru Brad Schulz Blog

Tente Este:

@list_of_params varchar(20) -- value 1, 2, 5, 7, 20 

SELECT d.[Name]
FROM Department d
where @list_of_params like ('%'+ CONVERT(VARCHAR(10),d.Id)  +'%')

muito simples.

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